From 7de7e5915a5492db964bc8ac48f17b1485e705d5 Mon Sep 17 00:00:00 2001 From: Petr Sabata Date: Tue, 11 Dec 2012 06:42:52 +0000 Subject: [PATCH 01/60] iproute2: ss - change default filter to include all socket types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently the default filter lists TCP sockets only which is rather confusing especially when the '-a/--all' flag is used. This patch changes the default to include all sockets, imitating netstat(8) behavior. Signed-off-by: Petr Šabata Acked-by: David S. Miller --- misc/ss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc/ss.c b/misc/ss.c index b45f5ba1..b8cd60de 100644 --- a/misc/ss.c +++ b/misc/ss.c @@ -105,7 +105,7 @@ struct filter }; struct filter default_filter = { - .dbs = (1< Date: Tue, 11 Dec 2012 09:52:39 -0800 Subject: [PATCH 02/60] v3.7.0 --- include/SNAPSHOT.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/SNAPSHOT.h b/include/SNAPSHOT.h index d4fc137c..b3738737 100644 --- a/include/SNAPSHOT.h +++ b/include/SNAPSHOT.h @@ -1 +1 @@ -static const char SNAPSHOT[] = "121001"; +static const char SNAPSHOT[] = "121211"; From 910773dc0df1131cbe5220d8b6971ae44a7221bd Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 11 Dec 2012 11:16:36 -0800 Subject: [PATCH 03/60] Update kernel headers to 3.8-pre Sanitized headers from net-next --- include/linux/atm.h | 6 ++--- include/linux/genetlink.h | 6 ++--- include/linux/hdlc/ioctl.h | 7 ++++-- include/linux/if_arp.h | 6 ++--- include/linux/if_ether.h | 7 +++--- include/linux/if_link.h | 28 +++++++++++++++++++++--- include/linux/if_tun.h | 13 ++++++++--- include/linux/if_tunnel.h | 26 +++++++++++++++++++--- include/linux/if_vlan.h | 6 ++--- include/linux/inet_diag.h | 9 ++++---- include/linux/l2tp.h | 6 ++--- include/linux/netdevice.h | 6 ++--- include/linux/netfilter.h | 6 ++--- include/linux/netfilter/x_tables.h | 6 ++--- include/linux/netfilter_ipv4.h | 6 ++--- include/linux/netfilter_ipv4/ip_tables.h | 6 ++--- include/linux/netlink.h | 6 ++--- include/linux/rtnetlink.h | 26 +++++++++++++++++++--- include/linux/sock_diag.h | 6 ++--- include/linux/socket.h | 6 ++--- include/linux/types.h | 6 ++--- include/linux/unix_diag.h | 1 + 22 files changed, 138 insertions(+), 63 deletions(-) diff --git a/include/linux/atm.h b/include/linux/atm.h index 2fafdfb9..08e27beb 100644 --- a/include/linux/atm.h +++ b/include/linux/atm.h @@ -8,8 +8,8 @@ * Instead, #include */ -#ifndef _UAPI_LINUX_ATM_H -#define _UAPI_LINUX_ATM_H +#ifndef _LINUX_ATM_H +#define _LINUX_ATM_H /* * BEGIN_xx and END_xx markers are used for automatic generation of @@ -238,4 +238,4 @@ struct atmif_sioc { typedef unsigned short atm_backend_t; -#endif /* _UAPI_LINUX_ATM_H */ +#endif /* _LINUX_ATM_H */ diff --git a/include/linux/genetlink.h b/include/linux/genetlink.h index c880a417..1f85a276 100644 --- a/include/linux/genetlink.h +++ b/include/linux/genetlink.h @@ -1,5 +1,5 @@ -#ifndef _UAPI__LINUX_GENERIC_NETLINK_H -#define _UAPI__LINUX_GENERIC_NETLINK_H +#ifndef __LINUX_GENERIC_NETLINK_H +#define __LINUX_GENERIC_NETLINK_H #include #include @@ -81,4 +81,4 @@ enum { #define CTRL_ATTR_MCAST_GRP_MAX (__CTRL_ATTR_MCAST_GRP_MAX - 1) -#endif /* _UAPI__LINUX_GENERIC_NETLINK_H */ +#endif /* __LINUX_GENERIC_NETLINK_H */ diff --git a/include/linux/hdlc/ioctl.h b/include/linux/hdlc/ioctl.h index 58397236..04bc0274 100644 --- a/include/linux/hdlc/ioctl.h +++ b/include/linux/hdlc/ioctl.h @@ -34,13 +34,15 @@ #define LMI_CCITT 3 /* ITU-T Annex A */ #define LMI_CISCO 4 /* The "original" LMI, aka Gang of Four */ -typedef struct { +#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 { +typedef struct { unsigned int clock_rate; /* bits per second */ unsigned int clock_type; /* internal, external, TX-internal etc. */ unsigned short loopback; @@ -78,4 +80,5 @@ typedef struct { /* PPP doesn't need any info now - supply length = 0 to ioctl */ +#endif /* __ASSEMBLY__ */ #endif /* __HDLC_IOCTL_H__ */ diff --git a/include/linux/if_arp.h b/include/linux/if_arp.h index 82c7d1bd..6a48d55a 100644 --- a/include/linux/if_arp.h +++ b/include/linux/if_arp.h @@ -20,8 +20,8 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ -#ifndef _UAPI_LINUX_IF_ARP_H -#define _UAPI_LINUX_IF_ARP_H +#ifndef _LINUX_IF_ARP_H +#define _LINUX_IF_ARP_H #include @@ -156,4 +156,4 @@ struct arphdr { }; -#endif /* _UAPI_LINUX_IF_ARP_H */ +#endif /* _LINUX_IF_ARP_H */ diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h index 0343e1f0..730410a8 100644 --- a/include/linux/if_ether.h +++ b/include/linux/if_ether.h @@ -18,8 +18,8 @@ * 2 of the License, or (at your option) any later version. */ -#ifndef _UAPI_LINUX_IF_ETHER_H -#define _UAPI_LINUX_IF_ETHER_H +#ifndef _LINUX_IF_ETHER_H +#define _LINUX_IF_ETHER_H #include @@ -48,6 +48,7 @@ #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 */ @@ -132,4 +133,4 @@ struct ethhdr { } __attribute__((packed)); -#endif /* _UAPI_LINUX_IF_ETHER_H */ +#endif /* _LINUX_IF_ETHER_H */ diff --git a/include/linux/if_link.h b/include/linux/if_link.h index 012d95a5..8ca3afe7 100644 --- a/include/linux/if_link.h +++ b/include/linux/if_link.h @@ -1,5 +1,5 @@ -#ifndef _UAPI_LINUX_IF_LINK_H -#define _UAPI_LINUX_IF_LINK_H +#ifndef _LINUX_IF_LINK_H +#define _LINUX_IF_LINK_H #include #include @@ -203,6 +203,24 @@ enum { #define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1) +enum { + BRIDGE_MODE_UNSPEC, + BRIDGE_MODE_HAIRPIN, +}; + +enum { + IFLA_BRPORT_UNSPEC, + IFLA_BRPORT_STATE, /* Spanning tree state */ + IFLA_BRPORT_PRIORITY, /* " priority */ + IFLA_BRPORT_COST, /* " cost */ + IFLA_BRPORT_MODE, /* mode (hairpin) */ + IFLA_BRPORT_GUARD, /* bpdu guard */ + IFLA_BRPORT_PROTECT, /* root port protection */ + IFLA_BRPORT_FAST_LEAVE, /* multicast fast leave */ + __IFLA_BRPORT_MAX +}; +#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) + struct ifla_cacheinfo { __u32 max_reasm_len; __u32 tstamp; /* ipv6InterfaceTable updated timestamp */ @@ -283,6 +301,10 @@ enum { 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) @@ -424,4 +446,4 @@ enum { #define IFLA_IPOIB_MAX (__IFLA_IPOIB_MAX - 1) -#endif /* _UAPI_LINUX_IF_LINK_H */ +#endif /* _LINUX_IF_LINK_H */ diff --git a/include/linux/if_tun.h b/include/linux/if_tun.h index 25a585ce..dffb1927 100644 --- a/include/linux/if_tun.h +++ b/include/linux/if_tun.h @@ -13,8 +13,8 @@ * GNU General Public License for more details. */ -#ifndef _UAPI__IF_TUN_H -#define _UAPI__IF_TUN_H +#ifndef __IF_TUN_H +#define __IF_TUN_H #include #include @@ -31,9 +31,11 @@ #define TUN_FASYNC 0x0010 #define TUN_NOCHECKSUM 0x0020 #define TUN_NO_PI 0x0040 +/* This flag has no real effect */ #define TUN_ONE_QUEUE 0x0080 #define TUN_PERSIST 0x0100 #define TUN_VNET_HDR 0x0200 +#define TUN_TAP_MQ 0x0400 /* Ioctl defines */ #define TUNSETNOCSUM _IOW('T', 200, int) @@ -53,14 +55,19 @@ #define TUNDETACHFILTER _IOW('T', 214, struct sock_fprog) #define TUNGETVNETHDRSZ _IOR('T', 215, int) #define TUNSETVNETHDRSZ _IOW('T', 216, int) +#define TUNSETQUEUE _IOW('T', 217, int) /* TUNSETIFF ifr flags */ #define IFF_TUN 0x0001 #define IFF_TAP 0x0002 #define IFF_NO_PI 0x1000 +/* This flag has no real effect */ #define IFF_ONE_QUEUE 0x2000 #define IFF_VNET_HDR 0x4000 #define IFF_TUN_EXCL 0x8000 +#define IFF_MULTI_QUEUE 0x0100 +#define IFF_ATTACH_QUEUE 0x0200 +#define IFF_DETACH_QUEUE 0x0400 /* Features for GSO (TUNSETOFFLOAD). */ #define TUN_F_CSUM 0x01 /* You can hand me unchecksummed packets. */ @@ -91,4 +98,4 @@ struct tun_filter { __u8 addr[0][ETH_ALEN]; }; -#endif /* _UAPI__IF_TUN_H */ +#endif /* __IF_TUN_H */ diff --git a/include/linux/if_tunnel.h b/include/linux/if_tunnel.h index 5db59425..9f471ca1 100644 --- a/include/linux/if_tunnel.h +++ b/include/linux/if_tunnel.h @@ -1,5 +1,5 @@ -#ifndef _UAPI_IF_TUNNEL_H_ -#define _UAPI_IF_TUNNEL_H_ +#ifndef _IF_TUNNEL_H_ +#define _IF_TUNNEL_H_ #include #include @@ -37,6 +37,26 @@ struct ip_tunnel_parm { 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_MAX, +}; +#define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1) + /* SIT-mode i_flags */ #define SIT_ISATAP 0x0001 @@ -93,4 +113,4 @@ enum { }; #define IFLA_VTI_MAX (__IFLA_VTI_MAX - 1) -#endif /* _UAPI_IF_TUNNEL_H_ */ +#endif /* _IF_TUNNEL_H_ */ diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index 0744f8e6..3be1ca61 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -10,8 +10,8 @@ * */ -#ifndef _UAPI_LINUX_IF_VLAN_H_ -#define _UAPI_LINUX_IF_VLAN_H_ +#ifndef _LINUX_IF_VLAN_H_ +#define _LINUX_IF_VLAN_H_ /* VLAN IOCTLs are found in sockios.h */ @@ -60,4 +60,4 @@ struct vlan_ioctl_args { short vlan_qos; }; -#endif /* _UAPI_LINUX_IF_VLAN_H_ */ +#endif /* _LINUX_IF_VLAN_H_ */ diff --git a/include/linux/inet_diag.h b/include/linux/inet_diag.h index 8c469af9..e34f2477 100644 --- a/include/linux/inet_diag.h +++ b/include/linux/inet_diag.h @@ -1,5 +1,5 @@ -#ifndef _UAPI_INET_DIAG_H_ -#define _UAPI_INET_DIAG_H_ +#ifndef _INET_DIAG_H_ +#define _INET_DIAG_H_ #include @@ -109,9 +109,10 @@ enum { INET_DIAG_TOS, INET_DIAG_TCLASS, INET_DIAG_SKMEMINFO, + INET_DIAG_SHUTDOWN, }; -#define INET_DIAG_MAX INET_DIAG_SKMEMINFO +#define INET_DIAG_MAX INET_DIAG_SHUTDOWN /* INET_DIAG_MEM */ @@ -133,4 +134,4 @@ struct tcpvegas_info { }; -#endif /* _UAPI_INET_DIAG_H_ */ +#endif /* _INET_DIAG_H_ */ diff --git a/include/linux/l2tp.h b/include/linux/l2tp.h index 02a567b3..c4bec823 100644 --- a/include/linux/l2tp.h +++ b/include/linux/l2tp.h @@ -4,8 +4,8 @@ * Author: James Chapman */ -#ifndef _UAPI_LINUX_L2TP_H_ -#define _UAPI_LINUX_L2TP_H_ +#ifndef _LINUX_L2TP_H_ +#define _LINUX_L2TP_H_ #include #include @@ -175,4 +175,4 @@ enum l2tp_seqmode { #define L2TP_GENL_NAME "l2tp" #define L2TP_GENL_VERSION 0x1 -#endif /* _UAPI_LINUX_L2TP_H_ */ +#endif /* _LINUX_L2TP_H_ */ diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 6b9500bc..adc72607 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -22,8 +22,8 @@ * * Moved to /usr/include/linux for NET3 */ -#ifndef _UAPI_LINUX_NETDEVICE_H -#define _UAPI_LINUX_NETDEVICE_H +#ifndef _LINUX_NETDEVICE_H +#define _LINUX_NETDEVICE_H #include #include @@ -50,4 +50,4 @@ enum { }; -#endif /* _UAPI_LINUX_NETDEVICE_H */ +#endif /* _LINUX_NETDEVICE_H */ diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 9961e7f6..f05c3d92 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -1,5 +1,5 @@ -#ifndef _UAPI__LINUX_NETFILTER_H -#define _UAPI__LINUX_NETFILTER_H +#ifndef __LINUX_NETFILTER_H +#define __LINUX_NETFILTER_H #include @@ -67,4 +67,4 @@ union nf_inet_addr { struct in6_addr in6; }; -#endif /* _UAPI__LINUX_NETFILTER_H */ +#endif /* __LINUX_NETFILTER_H */ diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index 92a06f30..41209700 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -1,5 +1,5 @@ -#ifndef _UAPI_X_TABLES_H -#define _UAPI_X_TABLES_H +#ifndef _X_TABLES_H +#define _X_TABLES_H #include #include @@ -182,4 +182,4 @@ struct xt_counters_info { (pos)->u.match_size)) -#endif /* _UAPI_X_TABLES_H */ +#endif /* _X_TABLES_H */ diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h index 77a3e439..a5f4dc78 100644 --- a/include/linux/netfilter_ipv4.h +++ b/include/linux/netfilter_ipv4.h @@ -1,8 +1,8 @@ /* IPv4-specific defines for netfilter. * (C)1998 Rusty Russell -- This code is GPL. */ -#ifndef _UAPI__LINUX_IP_NETFILTER_H -#define _UAPI__LINUX_IP_NETFILTER_H +#ifndef __LINUX_IP_NETFILTER_H +#define __LINUX_IP_NETFILTER_H #include @@ -76,4 +76,4 @@ enum nf_ip_hook_priorities { #define SO_ORIGINAL_DST 80 -#endif /* _UAPI__LINUX_IP_NETFILTER_H */ +#endif /* __LINUX_IP_NETFILTER_H */ diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h index 6ba9b093..38542b4f 100644 --- a/include/linux/netfilter_ipv4/ip_tables.h +++ b/include/linux/netfilter_ipv4/ip_tables.h @@ -12,8 +12,8 @@ * Port numbers are stored in HOST byte order. */ -#ifndef _UAPI_IPTABLES_H -#define _UAPI_IPTABLES_H +#ifndef _IPTABLES_H +#define _IPTABLES_H #include @@ -224,4 +224,4 @@ ipt_get_target(struct ipt_entry *e) /* * Main firewall chains definitions and global var's definitions. */ -#endif /* _UAPI_IPTABLES_H */ +#endif /* _IPTABLES_H */ diff --git a/include/linux/netlink.h b/include/linux/netlink.h index 78d5b8a5..ced0e1a7 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -1,5 +1,5 @@ -#ifndef _UAPI__LINUX_NETLINK_H -#define _UAPI__LINUX_NETLINK_H +#ifndef __LINUX_NETLINK_H +#define __LINUX_NETLINK_H #include /* for __kernel_sa_family_t */ #include @@ -150,4 +150,4 @@ struct nlattr { #define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr))) -#endif /* _UAPI__LINUX_NETLINK_H */ +#endif /* __LINUX_NETLINK_H */ diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index 0e3e0c17..c82a159d 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -1,5 +1,5 @@ -#ifndef _UAPI__LINUX_RTNETLINK_H -#define _UAPI__LINUX_RTNETLINK_H +#ifndef __LINUX_RTNETLINK_H +#define __LINUX_RTNETLINK_H #include #include @@ -120,6 +120,14 @@ enum { RTM_SETDCB, #define RTM_SETDCB RTM_SETDCB + RTM_NEWNETCONF = 80, +#define RTM_NEWNETCONF RTM_NEWNETCONF + RTM_GETNETCONF = 82, +#define RTM_GETNETCONF RTM_GETNETCONF + + RTM_GETMDB = 86, +#define RTM_GETMDB RTM_GETMDB + __RTM_MAX, #define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1) }; @@ -222,6 +230,7 @@ enum { #define RTPROT_XORP 14 /* XORP */ #define RTPROT_NTK 15 /* Netsukuku */ #define RTPROT_DHCP 16 /* DHCP client */ +#define RTPROT_MROUTED 17 /* Multicast daemon */ /* rtm_scope @@ -283,6 +292,7 @@ enum rtattr_type_t { RTA_MP_ALGO, /* no longer used */ RTA_TABLE, RTA_MARK, + RTA_MFC_STATS, __RTA_MAX }; @@ -403,6 +413,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. ****/ @@ -585,6 +601,10 @@ enum rtnetlink_groups { #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_MAX }; #define RTNLGRP_MAX (__RTNLGRP_MAX - 1) @@ -607,4 +627,4 @@ struct tcamsg { -#endif /* _UAPI__LINUX_RTNETLINK_H */ +#endif /* __LINUX_RTNETLINK_H */ diff --git a/include/linux/sock_diag.h b/include/linux/sock_diag.h index b00e29ef..78996e23 100644 --- a/include/linux/sock_diag.h +++ b/include/linux/sock_diag.h @@ -1,5 +1,5 @@ -#ifndef _UAPI__SOCK_DIAG_H__ -#define _UAPI__SOCK_DIAG_H__ +#ifndef __SOCK_DIAG_H__ +#define __SOCK_DIAG_H__ #include @@ -23,4 +23,4 @@ enum { SK_MEMINFO_VARS, }; -#endif /* _UAPI__SOCK_DIAG_H__ */ +#endif /* __SOCK_DIAG_H__ */ diff --git a/include/linux/socket.h b/include/linux/socket.h index 76ab0c68..8c1e5017 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -1,5 +1,5 @@ -#ifndef _UAPI_LINUX_SOCKET_H -#define _UAPI_LINUX_SOCKET_H +#ifndef _LINUX_SOCKET_H +#define _LINUX_SOCKET_H /* * Desired design of maximum size and alignment (see RFC2553) @@ -18,4 +18,4 @@ struct __kernel_sockaddr_storage { /* _SS_MAXSIZE value minus size of ss_family */ } __attribute__ ((aligned(_K_SS_ALIGNSIZE))); /* force desired alignment */ -#endif /* _UAPI_LINUX_SOCKET_H */ +#endif /* _LINUX_SOCKET_H */ diff --git a/include/linux/types.h b/include/linux/types.h index 54c5df3d..23ea78fd 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -1,5 +1,5 @@ -#ifndef _UAPI_LINUX_TYPES_H -#define _UAPI_LINUX_TYPES_H +#ifndef _LINUX_TYPES_H +#define _LINUX_TYPES_H #include @@ -48,4 +48,4 @@ typedef __u32 __bitwise __wsum; #define __aligned_le64 __le64 __attribute__((aligned(8))) #endif /* __ASSEMBLY__ */ -#endif /* _UAPI_LINUX_TYPES_H */ +#endif /* _LINUX_TYPES_H */ diff --git a/include/linux/unix_diag.h b/include/linux/unix_diag.h index b1d2bf16..b8a24941 100644 --- a/include/linux/unix_diag.h +++ b/include/linux/unix_diag.h @@ -37,6 +37,7 @@ enum { UNIX_DIAG_ICONS, UNIX_DIAG_RQLEN, UNIX_DIAG_MEMINFO, + UNIX_DIAG_SHUTDOWN, UNIX_DIAG_MAX, }; From 08342500eeb9f2cefa49ded2b4a6183becdaf419 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 11 Dec 2012 16:43:36 -0800 Subject: [PATCH 04/60] bridge: add if_bridge.h header Since system may not have upto date kernel headers, keep if_bridge.h in set of exported headers used to build iproute. --- include/linux/if_bridge.h | 174 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 include/linux/if_bridge.h diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h new file mode 100644 index 00000000..151a8bbe --- /dev/null +++ b/include/linux/if_bridge.h @@ -0,0 +1,174 @@ +/* + * 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 + +#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 { + __u32 ifindex; +}; + +struct br_mdb_entry { + __u32 ifindex; + struct { + union { + __be32 ip4; + struct in6_addr ip6; + } u; + __be16 proto; + } addr; +}; + +#endif /* _LINUX_IF_BRIDGE_H */ From e06c7f7e2ec2ab17dd9a6ed92b9d1a8bc250eff9 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Tue, 11 Dec 2012 16:46:22 -0800 Subject: [PATCH 05/60] iproute2: add mdb sub-command to bridge Sample output: # ./bridge/bridge mdb show dev br0 bridge br0 port eth1 group 224.8.8.9 bridge br0 port eth0 group 224.8.8.8 # ./bridge/bridge -d mdb show dev br0 bridge br0 port eth1 group 224.8.8.9 bridge br0 port eth0 group 224.8.8.8 router ports on br0: eth0 Signed-off-by: Cong Wang --- bridge/Makefile | 2 +- bridge/br_common.h | 3 +- bridge/bridge.c | 1 + bridge/mdb.c | 172 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 176 insertions(+), 2 deletions(-) create mode 100644 bridge/mdb.c diff --git a/bridge/Makefile b/bridge/Makefile index 9a6743e5..67aceb4d 100644 --- a/bridge/Makefile +++ b/bridge/Makefile @@ -1,4 +1,4 @@ -BROBJ = bridge.o fdb.o monitor.o link.o +BROBJ = bridge.o fdb.o monitor.o link.o mdb.o include ../Config diff --git a/bridge/br_common.h b/bridge/br_common.h index 718ecb9a..892fb76c 100644 --- a/bridge/br_common.h +++ b/bridge/br_common.h @@ -5,10 +5,11 @@ extern int print_fdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg); extern int do_fdb(int argc, char **argv); +extern int do_mdb(int argc, char **argv); extern int do_monitor(int argc, char **argv); extern int preferred_family; extern int show_stats; -extern int show_detail; +extern int show_details; extern int timestamp; extern struct rtnl_handle rth; diff --git a/bridge/bridge.c b/bridge/bridge.c index e2c33b0f..1fcd365a 100644 --- a/bridge/bridge.c +++ b/bridge/bridge.c @@ -43,6 +43,7 @@ static const struct cmd { int (*func)(int argc, char **argv); } cmds[] = { { "fdb", do_fdb }, + { "mdb", do_mdb }, { "monitor", do_monitor }, { "help", do_help }, { 0 } diff --git a/bridge/mdb.c b/bridge/mdb.c new file mode 100644 index 00000000..390d7f61 --- /dev/null +++ b/bridge/mdb.c @@ -0,0 +1,172 @@ +/* + * Get mdb table with netlink + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "libnetlink.h" +#include "br_common.h" +#include "rt_names.h" +#include "utils.h" + +#ifndef MDBA_RTA +#define MDBA_RTA(r) \ + ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct br_port_msg)))) +#endif + +int filter_index; + +static void usage(void) +{ + fprintf(stderr, " bridge mdb {show} [ dev DEV ]\n"); + exit(-1); +} + +static void br_print_router_ports(FILE *f, struct rtattr *attr) +{ + uint32_t *port_ifindex; + struct rtattr *i; + int rem; + + rem = RTA_PAYLOAD(attr); + for (i = RTA_DATA(attr); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) { + port_ifindex = RTA_DATA(i); + fprintf(f, "%s ", ll_index_to_name(*port_ifindex)); + } + + fprintf(f, "\n"); +} + +static void print_mdb_entry(FILE *f, int ifindex, struct br_mdb_entry *e) +{ + SPRINT_BUF(abuf); + + if (e->addr.proto == htons(ETH_P_IP)) + fprintf(f, "bridge %s port %s group %s\n", ll_index_to_name(ifindex), + ll_index_to_name(e->ifindex), + inet_ntop(AF_INET, &e->addr.u.ip4, abuf, sizeof(abuf))); + else + fprintf(f, "bridge %s port %s group %s\n", ll_index_to_name(ifindex), + ll_index_to_name(e->ifindex), + inet_ntop(AF_INET6, &e->addr.u.ip6, abuf, sizeof(abuf))); +} + +static void br_print_mdb_entry(FILE *f, int ifindex, struct rtattr *attr) +{ + struct rtattr *i; + int rem; + struct br_mdb_entry *e; + + rem = RTA_PAYLOAD(attr); + for (i = RTA_DATA(attr); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) { + e = RTA_DATA(i); + print_mdb_entry(f, ifindex, e); + } +} + +int print_mdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) +{ + FILE *fp = arg; + struct br_port_msg *r = NLMSG_DATA(n); + int len = n->nlmsg_len; + struct rtattr * tb[MDBA_MAX+1]; + + if (n->nlmsg_type != RTM_GETMDB) { + fprintf(stderr, "Not RTM_GETMDB: %08x %08x %08x\n", + n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); + + return 0; + } + + len -= NLMSG_LENGTH(sizeof(*r)); + if (len < 0) { + fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); + return -1; + } + + if (filter_index && filter_index != r->ifindex) + return 0; + + parse_rtattr(tb, MDBA_MAX, MDBA_RTA(r), n->nlmsg_len - NLMSG_LENGTH(sizeof(*r))); + + if (tb[MDBA_MDB]) { + struct rtattr *i; + int rem = RTA_PAYLOAD(tb[MDBA_MDB]); + + for (i = RTA_DATA(tb[MDBA_MDB]); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) + br_print_mdb_entry(fp, r->ifindex, i); + } + + if (tb[MDBA_ROUTER]) { + if (show_details) { + fprintf(fp, "router ports on %s: ", ll_index_to_name(r->ifindex)); + br_print_router_ports(fp, tb[MDBA_ROUTER]); + } + } + + return 0; +} + +static int mdb_show(int argc, char **argv) +{ + char *filter_dev = NULL; + + while (argc > 0) { + if (strcmp(*argv, "dev") == 0) { + NEXT_ARG(); + if (filter_dev) + duparg("dev", *argv); + filter_dev = *argv; + } + argc--; argv++; + } + + if (filter_dev) { + filter_index = if_nametoindex(filter_dev); + if (filter_index == 0) { + fprintf(stderr, "Cannot find device \"%s\"\n", + filter_dev); + return -1; + } + } + + if (rtnl_wilddump_request(&rth, PF_BRIDGE, RTM_GETMDB) < 0) { + perror("Cannot send dump request"); + exit(1); + } + + if (rtnl_dump_filter(&rth, print_mdb, stdout) < 0) { + fprintf(stderr, "Dump terminated\n"); + exit(1); + } + + return 0; +} + +int do_mdb(int argc, char **argv) +{ + ll_init_map(&rth); + + if (argc > 0) { + if (matches(*argv, "show") == 0 || + matches(*argv, "lst") == 0 || + matches(*argv, "list") == 0) + return mdb_show(argc-1, argv+1); + if (matches(*argv, "help") == 0) + usage(); + } else + return mdb_show(0, NULL); + + fprintf(stderr, "Command \"%s\" is unknown, try \"bridge mdb help\".\n", *argv); + exit(-1); +} From caadda9308dad90d52fb38fa8ab68f330cefc54c Mon Sep 17 00:00:00 2001 From: Andreas Henriksson Date: Wed, 12 Dec 2012 12:23:48 +0100 Subject: [PATCH 06/60] iproute2: fix tc ematch manpage section The debian package checking tool, lintian, spotted that the tc ematch manpage seems to have an error in the specified section. Signed-off-by: Andreas Henriksson --- man/man8/tc-ematch.8 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/man8/tc-ematch.8 b/man/man8/tc-ematch.8 index 2eafc290..957a22e9 100644 --- a/man/man8/tc-ematch.8 +++ b/man/man8/tc-ematch.8 @@ -1,4 +1,4 @@ -.TH filter ematch "6 August 2012" iproute2 Linux +.TH ematch 8 "6 August 2012" iproute2 Linux . .SH NAME ematch \- extended matches for use with "basic" or "flow" filters From 4852ba750a2cc122e5b933b1ce852c60ef1471fc Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Wed, 12 Dec 2012 09:05:51 -0800 Subject: [PATCH 07/60] ip: add support of netconf messages Example of the output: $ ip monitor netconf& [1] 24901 $ echo 0 > /proc/sys/net/ipv6/conf/all/forwarding ipv6 dev lo forwarding off ipv6 dev eth0 forwarding off ipv6 all forwarding off $ echo 1 > /proc/sys/net/ipv4/conf/eth0/forwarding ipv4 dev eth0 forwarding on $ ip -6 netconf ipv6 all forwarding on mc_forwarding 0 $ ip netconf show dev eth0 ipv4 dev eth0 forwarding on rp_filter off mc_forwarding 1 Signed-off-by: Nicolas Dichtel Minor cleanup of original patch, made sure netconf.h matched result of santized kernel headers --- include/linux/netconf.h | 24 ++++++ ip/ipnetconf.c | 183 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 207 insertions(+) create mode 100644 include/linux/netconf.h create mode 100644 ip/ipnetconf.c diff --git a/include/linux/netconf.h b/include/linux/netconf.h new file mode 100644 index 00000000..52c44244 --- /dev/null +++ b/include/linux/netconf.h @@ -0,0 +1,24 @@ +#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_MAX +}; +#define NETCONFA_MAX (__NETCONFA_MAX - 1) + +#define NETCONFA_IFINDEX_ALL -1 +#define NETCONFA_IFINDEX_DEFAULT -2 + +#endif /* _LINUX_NETCONF_H_ */ diff --git a/ip/ipnetconf.c b/ip/ipnetconf.c new file mode 100644 index 00000000..66d667bc --- /dev/null +++ b/ip/ipnetconf.c @@ -0,0 +1,183 @@ +/* + * ipnetconf.c "ip netconf". + * + * 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. + * + * Authors: Nicolas Dichtel, + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rt_names.h" +#include "utils.h" +#include "ip_common.h" + +static struct +{ + int family; + int ifindex; +} filter; + +static void usage(void) __attribute__((noreturn)); + +static void usage(void) +{ + fprintf(stderr, "Usage: ip netconf show [ dev STRING ]\n"); + exit(-1); +} + +#define NETCONF_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct netconfmsg)))) + +int print_netconf(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) +{ + FILE *fp = (FILE*)arg; + struct netconfmsg *ncm = NLMSG_DATA(n); + int len = n->nlmsg_len; + struct rtattr *tb[NETCONFA_MAX+1]; + + if (n->nlmsg_type == NLMSG_ERROR) + return -1; + if (n->nlmsg_type != RTM_NEWNETCONF) { + fprintf(stderr, "Not RTM_NEWNETCONF: %08x %08x %08x\n", + n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); + + return -1; + } + len -= NLMSG_SPACE(sizeof(*ncm)); + if (len < 0) { + fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); + return -1; + } + + if (filter.family && filter.family != ncm->ncm_family) + return 0; + + parse_rtattr(tb, NETCONFA_MAX, NETCONF_RTA(ncm), + NLMSG_PAYLOAD(n, sizeof(*ncm))); + + switch (ncm->ncm_family) { + case AF_INET: + fprintf(fp, "ipv4 "); + break; + case AF_INET6: + fprintf(fp, "ipv6 "); + break; + default: + fprintf(fp, "unknown "); + break; + } + + if (tb[NETCONFA_IFINDEX]) { + int *ifindex = (int *)RTA_DATA(tb[NETCONFA_IFINDEX]); + + switch (*ifindex) { + case NETCONFA_IFINDEX_ALL: + fprintf(fp, "all "); + break; + case NETCONFA_IFINDEX_DEFAULT: + fprintf(fp, "default "); + break; + default: + fprintf(fp, "dev %s ", ll_index_to_name(*ifindex)); + break; + } + } + + if (tb[NETCONFA_FORWARDING]) + fprintf(fp, "forwarding %s ", + *(int *)RTA_DATA(tb[NETCONFA_FORWARDING])?"on":"off"); + if (tb[NETCONFA_RP_FILTER]) { + int rp_filter = *(int *)RTA_DATA(tb[NETCONFA_RP_FILTER]); + + if (rp_filter == 0) + fprintf(fp, "rp_filter off "); + else if (rp_filter == 1) + fprintf(fp, "rp_filter strict "); + else if (rp_filter == 2) + fprintf(fp, "rp_filter loose "); + else + fprintf(fp, "rp_filter unknown mode "); + } + if (tb[NETCONFA_MC_FORWARDING]) + fprintf(fp, "mc_forwarding %d ", + *(int *)RTA_DATA(tb[NETCONFA_MC_FORWARDING])); + + fprintf(fp, "\n"); + fflush(fp); + return 0; +} + +void ipnetconf_reset_filter(void) +{ + memset(&filter, 0, sizeof(filter)); +} + +int do_show(int argc, char **argv) +{ + struct { + struct nlmsghdr n; + struct netconfmsg ncm; + char buf[1024]; + } req; + + ipnetconf_reset_filter(); + filter.family = preferred_family; + if (filter.family == AF_UNSPEC) + filter.family = AF_INET; + filter.ifindex = NETCONFA_IFINDEX_ALL; + + while (argc > 0) { + if (strcmp(*argv, "dev") == 0) { + NEXT_ARG(); + filter.ifindex = ll_name_to_index(*argv); + if (filter.ifindex <= 0) { + fprintf(stderr, "Device \"%s\" does not exist.\n", + *argv); + return -1; + } + } + argv++; argc--; + } + + ll_init_map(&rth); + memset(&req, 0, sizeof(req)); + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct netconfmsg)); + req.n.nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK; + req.n.nlmsg_type = RTM_GETNETCONF; + req.ncm.ncm_family = filter.family; + addattr_l(&req.n, sizeof(req), NETCONFA_IFINDEX, &filter.ifindex, + sizeof(filter.ifindex)); + + rtnl_send(&rth, &req.n, req.n.nlmsg_len); + rtnl_listen(&rth, print_netconf, stdout); + + return 0; +} + +int do_ipnetconf(int argc, char **argv) +{ + if (argc > 0) { + if (matches(*argv, "show") == 0 || + matches(*argv, "lst") == 0 || + matches(*argv, "list") == 0) + return do_show(argc-1, argv+1); + if (matches(*argv, "help") == 0) + usage(); + } else + return do_show(0, NULL); + + fprintf(stderr, "Command \"%s\" is unknown, try \"ip netconf help\".\n", *argv); + exit(-1); +} From 9d0efc10487b92861a84fd6f171a841c1e026c6c Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Wed, 12 Dec 2012 09:09:23 -0800 Subject: [PATCH 08/60] ip: add support of 'ip link type ip6tnl' This patch allows to manage ip6 tunnels via the interface ip link. The syntax for parameters is the same that 'ip -6 tunnel'. It also allows to display tunnels parameters with 'ip -details link' or 'ip -details monitor link'. Signed-off-by: Nicolas Dichtel --- include/libnetlink.h | 1 + ip/Makefile | 2 +- ip/ip.c | 1 + ip/ip_common.h | 3 + ip/iplink.c | 3 +- ip/ipmonitor.c | 16 ++ ip/link_ip6tnl.c | 344 +++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 368 insertions(+), 2 deletions(-) create mode 100644 ip/link_ip6tnl.c diff --git a/include/libnetlink.h b/include/libnetlink.h index 81649afe..4a6b8789 100644 --- a/include/libnetlink.h +++ b/include/libnetlink.h @@ -8,6 +8,7 @@ #include #include #include +#include struct rtnl_handle { diff --git a/ip/Makefile b/ip/Makefile index 1676f0ff..abf54bf7 100644 --- a/ip/Makefile +++ b/ip/Makefile @@ -4,7 +4,7 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \ ipxfrm.o xfrm_state.o xfrm_policy.o xfrm_monitor.o \ iplink_vlan.o link_veth.o link_gre.o iplink_can.o \ iplink_macvlan.o iplink_macvtap.o ipl2tp.o link_vti.o \ - iplink_vxlan.o tcp_metrics.o iplink_ipoib.o + iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o RTMONOBJ=rtmon.o diff --git a/ip/ip.c b/ip/ip.c index e0f7e609..632d2717 100644 --- a/ip/ip.c +++ b/ip/ip.c @@ -85,6 +85,7 @@ static const struct cmd { { "mroute", do_multiroute }, { "mrule", do_multirule }, { "netns", do_netns }, + { "netconf", do_ipnetconf }, { "help", do_help }, { 0 } }; diff --git a/ip/ip_common.h b/ip/ip_common.h index 2fd66b74..a3946690 100644 --- a/ip/ip_common.h +++ b/ip/ip_common.h @@ -25,6 +25,8 @@ extern int print_prefix(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg); extern int print_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg); +extern int print_netconf(const struct sockaddr_nl *who, + struct nlmsghdr *n, void *arg); extern int do_ipaddr(int argc, char **argv); extern int do_ipaddrlabel(int argc, char **argv); extern int do_iproute(int argc, char **argv); @@ -43,6 +45,7 @@ extern int do_netns(int argc, char **argv); extern int do_xfrm(int argc, char **argv); extern int do_ipl2tp(int argc, char **argv); extern int do_tcp_metrics(int argc, char **argv); +extern int do_ipnetconf(int argc, char **argv); static inline int rtm_get_table(struct rtmsg *r, struct rtattr **tb) { diff --git a/ip/iplink.c b/ip/iplink.c index 7451aa02..8aac9fc9 100644 --- a/ip/iplink.c +++ b/ip/iplink.c @@ -83,7 +83,8 @@ void iplink_usage(void) if (iplink_have_newlink()) { fprintf(stderr, "\n"); - fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | can | bridge | ipoib }\n"); + fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | can |\n"); + fprintf(stderr, " bridge | ipoib | ip6tnl }\n"); } exit(-1); } diff --git a/ip/ipmonitor.c b/ip/ipmonitor.c index 4b1d469d..d87e58f1 100644 --- a/ip/ipmonitor.c +++ b/ip/ipmonitor.c @@ -85,6 +85,12 @@ int accept_msg(const struct sockaddr_nl *who, print_rule(who, n, arg); return 0; } + if (n->nlmsg_type == RTM_NEWNETCONF) { + if (prefix_banner) + fprintf(fp, "[NETCONF]"); + print_netconf(who, n, arg); + return 0; + } if (n->nlmsg_type == 15) { char *tstr; time_t secs = ((__u32*)NLMSG_DATA(n))[0]; @@ -118,6 +124,7 @@ int do_ipmonitor(int argc, char **argv) int lroute=0; int lprefix=0; int lneigh=0; + int lnetconf=0; rtnl_close(&rth); ipaddr_reset_filter(1); @@ -143,6 +150,9 @@ int do_ipmonitor(int argc, char **argv) } else if (matches(*argv, "neigh") == 0) { lneigh = 1; groups = 0; + } else if (matches(*argv, "netconf") == 0) { + lnetconf = 1; + groups = 0; } else if (strcmp(*argv, "all") == 0) { groups = ~RTMGRP_TC; prefix_banner=1; @@ -176,6 +186,12 @@ int do_ipmonitor(int argc, char **argv) if (lneigh) { groups |= nl_mgrp(RTNLGRP_NEIGH); } + if (lnetconf) { + if (!preferred_family || preferred_family == AF_INET) + groups |= nl_mgrp(RTNLGRP_IPV4_NETCONF); + if (!preferred_family || preferred_family == AF_INET6) + groups |= nl_mgrp(RTNLGRP_IPV6_NETCONF); + } if (file) { FILE *fp; fp = fopen(file, "r"); diff --git a/ip/link_ip6tnl.c b/ip/link_ip6tnl.c new file mode 100644 index 00000000..29473648 --- /dev/null +++ b/ip/link_ip6tnl.c @@ -0,0 +1,344 @@ +/* + * link_ip6tnl.c ip6tnl driver module + * + * 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. + * + * Authors: Nicolas Dichtel + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include "rt_names.h" +#include "utils.h" +#include "ip_common.h" +#include "tunnel.h" + +#define IP6_FLOWINFO_TCLASS htonl(0x0FF00000) +#define IP6_FLOWINFO_FLOWLABEL htonl(0x000FFFFF) + +#define DEFAULT_TNL_HOP_LIMIT (64) + +static void usage(void) __attribute__((noreturn)); +static void usage(void) +{ + fprintf(stderr, "Usage: ip link { add | set | change | replace | del } NAME\n"); + fprintf(stderr, " type ip6tnl [ remote ADDR ] [ local ADDR ]\n"); + fprintf(stderr, " [ dev PHYS_DEV ] [ encaplimit ELIM ]\n"); + fprintf(stderr ," [ hoplimit HLIM ] [ tclass TCLASS ] [ flowlabel FLOWLABEL ]\n"); + fprintf(stderr, " [ dscp inherit ] [ fwmark inherit ]\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Where: NAME := STRING\n"); + fprintf(stderr, " ADDR := IPV6_ADDRESS\n"); + fprintf(stderr, " ELIM := { none | 0..255 }(default=%d)\n", + IPV6_DEFAULT_TNL_ENCAP_LIMIT); + fprintf(stderr, " HLIM := 0..255 (default=%d)\n", + DEFAULT_TNL_HOP_LIMIT); + fprintf(stderr, " TCLASS := { 0x0..0xff | inherit }\n"); + fprintf(stderr, " FLOWLABEL := { 0x0..0xfffff | inherit }\n"); + exit(-1); +} + +static int ip6tunnel_parse_opt(struct link_util *lu, int argc, char **argv, + struct nlmsghdr *n) +{ + struct { + struct nlmsghdr n; + struct ifinfomsg i; + char buf[2048]; + } req; + struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1); + struct rtattr *tb[IFLA_MAX + 1]; + struct rtattr *linkinfo[IFLA_INFO_MAX+1]; + struct rtattr *iptuninfo[IFLA_IPTUN_MAX + 1]; + int len; + struct in6_addr laddr; + struct in6_addr raddr; + __u8 hop_limit = DEFAULT_TNL_HOP_LIMIT; + __u8 encap_limit = IPV6_DEFAULT_TNL_ENCAP_LIMIT; + __u32 flowinfo = 0; + __u32 flags = 0; + __u32 link = 0; + __u8 proto = 0; + + memset(&laddr, 0, sizeof(laddr)); + memset(&raddr, 0, sizeof(raddr)); + + if (!(n->nlmsg_flags & NLM_F_CREATE)) { + memset(&req, 0, sizeof(req)); + + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)); + req.n.nlmsg_flags = NLM_F_REQUEST; + req.n.nlmsg_type = RTM_GETLINK; + req.i.ifi_family = preferred_family; + req.i.ifi_index = ifi->ifi_index; + + if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) { +get_failed: + fprintf(stderr, + "Failed to get existing tunnel info.\n"); + return -1; + } + + len = req.n.nlmsg_len; + len -= NLMSG_LENGTH(sizeof(*ifi)); + if (len < 0) + goto get_failed; + + parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len); + + if (!tb[IFLA_LINKINFO]) + goto get_failed; + + parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]); + + if (!linkinfo[IFLA_INFO_DATA]) + goto get_failed; + + parse_rtattr_nested(iptuninfo, IFLA_IPTUN_MAX, + linkinfo[IFLA_INFO_DATA]); + + if (iptuninfo[IFLA_IPTUN_LOCAL]) + memcpy(&laddr, RTA_DATA(iptuninfo[IFLA_IPTUN_LOCAL]), + sizeof(laddr)); + + if (iptuninfo[IFLA_IPTUN_REMOTE]) + memcpy(&raddr, RTA_DATA(iptuninfo[IFLA_IPTUN_REMOTE]), + sizeof(raddr)); + + if (iptuninfo[IFLA_IPTUN_TTL]) + hop_limit = rta_getattr_u8(iptuninfo[IFLA_IPTUN_TTL]); + + if (iptuninfo[IFLA_IPTUN_ENCAP_LIMIT]) + encap_limit = rta_getattr_u8(iptuninfo[IFLA_IPTUN_ENCAP_LIMIT]); + + if (iptuninfo[IFLA_IPTUN_FLOWINFO]) + flowinfo = rta_getattr_u32(iptuninfo[IFLA_IPTUN_FLOWINFO]); + + if (iptuninfo[IFLA_IPTUN_FLAGS]) + flags = rta_getattr_u32(iptuninfo[IFLA_IPTUN_FLAGS]); + + if (iptuninfo[IFLA_IPTUN_LINK]) + link = rta_getattr_u32(iptuninfo[IFLA_IPTUN_LINK]); + + if (iptuninfo[IFLA_IPTUN_PROTO]) + proto = rta_getattr_u8(iptuninfo[IFLA_IPTUN_PROTO]); + } + + while (argc > 0) { + if (matches(*argv, "mode") == 0) { + NEXT_ARG(); + if (strcmp(*argv, "ipv6/ipv6") == 0 || + strcmp(*argv, "ip6ip6") == 0) + proto = IPPROTO_IPV6; + else if (strcmp(*argv, "ip/ipv6") == 0 || + strcmp(*argv, "ipv4/ipv6") == 0 || + strcmp(*argv, "ipip6") == 0 || + strcmp(*argv, "ip4ip6") == 0) + proto = IPPROTO_IPIP; + else if (strcmp(*argv, "any/ipv6") == 0 || + strcmp(*argv, "any") == 0) + proto = 0; + else + invarg("Cannot guess tunnel mode.", *argv); + } else if (strcmp(*argv, "remote") == 0) { + inet_prefix addr; + NEXT_ARG(); + get_prefix(&addr, *argv, preferred_family); + if (addr.family == AF_UNSPEC) + invarg("\"remote\" address family is AF_UNSPEC", *argv); + memcpy(&raddr, addr.data, addr.bytelen); + } else if (strcmp(*argv, "local") == 0) { + inet_prefix addr; + NEXT_ARG(); + get_prefix(&addr, *argv, preferred_family); + if (addr.family == AF_UNSPEC) + invarg("\"local\" address family is AF_UNSPEC", *argv); + memcpy(&laddr, addr.data, addr.bytelen); + } else if (matches(*argv, "dev") == 0) { + NEXT_ARG(); + link = if_nametoindex(*argv); + if (link == 0) + invarg("\"dev\" is invalid", *argv); + } else if (strcmp(*argv, "hoplimit") == 0 || + strcmp(*argv, "ttl") == 0 || + strcmp(*argv, "hlim") == 0) { + __u8 uval; + NEXT_ARG(); + if (get_u8(&uval, *argv, 0)) + invarg("invalid HLIM", *argv); + hop_limit = uval; + } else if (matches(*argv, "encaplimit") == 0) { + NEXT_ARG(); + if (strcmp(*argv, "none") == 0) { + flags |= IP6_TNL_F_IGN_ENCAP_LIMIT; + } else { + __u8 uval; + if (get_u8(&uval, *argv, 0) < -1) + invarg("invalid ELIM", *argv); + encap_limit = uval; + flags &= ~IP6_TNL_F_IGN_ENCAP_LIMIT; + } + } else if (strcmp(*argv, "tclass") == 0 || + strcmp(*argv, "tc") == 0 || + strcmp(*argv, "tos") == 0 || + matches(*argv, "dsfield") == 0) { + __u8 uval; + NEXT_ARG(); + flowinfo &= ~IP6_FLOWINFO_TCLASS; + if (strcmp(*argv, "inherit") == 0) + flags |= IP6_TNL_F_USE_ORIG_TCLASS; + else { + if (get_u8(&uval, *argv, 16)) + invarg("invalid TClass", *argv); + flowinfo |= htonl((__u32)uval << 20) & IP6_FLOWINFO_TCLASS; + flags &= ~IP6_TNL_F_USE_ORIG_TCLASS; + } + } else if (strcmp(*argv, "flowlabel") == 0 || + strcmp(*argv, "fl") == 0) { + __u32 uval; + NEXT_ARG(); + flowinfo &= ~IP6_FLOWINFO_FLOWLABEL; + if (strcmp(*argv, "inherit") == 0) + flags |= IP6_TNL_F_USE_ORIG_FLOWLABEL; + else { + if (get_u32(&uval, *argv, 16)) + invarg("invalid Flowlabel", *argv); + if (uval > 0xFFFFF) + invarg("invalid Flowlabel", *argv); + flowinfo |= htonl(uval) & IP6_FLOWINFO_FLOWLABEL; + flags &= ~IP6_TNL_F_USE_ORIG_FLOWLABEL; + } + } else if (strcmp(*argv, "dscp") == 0) { + NEXT_ARG(); + if (strcmp(*argv, "inherit") != 0) + invarg("not inherit", *argv); + flags |= IP6_TNL_F_RCV_DSCP_COPY; + } else if (strcmp(*argv, "fwmark") == 0) { + NEXT_ARG(); + if (strcmp(*argv, "inherit") != 0) + invarg("not inherit", *argv); + flags |= IP6_TNL_F_USE_ORIG_FWMARK; + } else + usage(); + argc--, argv++; + } + + addattr8(n, 1024, IFLA_IPTUN_PROTO, proto); + addattr_l(n, 1024, IFLA_IPTUN_LOCAL, &laddr, sizeof(laddr)); + addattr_l(n, 1024, IFLA_IPTUN_REMOTE, &raddr, sizeof(raddr)); + addattr8(n, 1024, IFLA_IPTUN_TTL, hop_limit); + addattr8(n, 1024, IFLA_IPTUN_ENCAP_LIMIT, encap_limit); + addattr32(n, 1024, IFLA_IPTUN_FLOWINFO, flowinfo); + addattr32(n, 1024, IFLA_IPTUN_FLAGS, flags); + addattr32(n, 1024, IFLA_IPTUN_LINK, link); + + return 0; +} + +static void ip6tunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) +{ + char s1[256]; + char s2[64]; + int flags = 0; + __u32 flowinfo = 0; + + if (!tb) + return; + + if (tb[IFLA_IPTUN_FLAGS]) + flags = rta_getattr_u32(tb[IFLA_IPTUN_FLAGS]); + + if (tb[IFLA_IPTUN_FLOWINFO]) + flowinfo = rta_getattr_u32(tb[IFLA_IPTUN_FLOWINFO]); + + if (tb[IFLA_IPTUN_PROTO]) { + switch (rta_getattr_u8(tb[IFLA_IPTUN_PROTO])) { + case IPPROTO_IPIP: + fprintf(f, "ipip6 "); + break; + case IPPROTO_IPV6: + fprintf(f, "ip6ip6 "); + break; + case 0: + fprintf(f, "any "); + break; + } + } + + if (tb[IFLA_IPTUN_REMOTE]) { + fprintf(f, "remote %s ", + rt_addr_n2a(AF_INET6, + RTA_PAYLOAD(tb[IFLA_IPTUN_REMOTE]), + RTA_DATA(tb[IFLA_IPTUN_REMOTE]), + s1, sizeof(s1))); + } + + if (tb[IFLA_IPTUN_LOCAL]) { + fprintf(f, "local %s ", + rt_addr_n2a(AF_INET6, + RTA_PAYLOAD(tb[IFLA_IPTUN_LOCAL]), + RTA_DATA(tb[IFLA_IPTUN_LOCAL]), + s1, sizeof(s1))); + } + + if (tb[IFLA_IPTUN_LINK] && rta_getattr_u32(tb[IFLA_IPTUN_LINK])) { + unsigned link = rta_getattr_u32(tb[IFLA_IPTUN_LINK]); + const char *n = if_indextoname(link, s2); + + if (n) + fprintf(f, "dev %s ", n); + else + fprintf(f, "dev %u ", link); + } + + if (flags & IP6_TNL_F_IGN_ENCAP_LIMIT) + printf("encaplimit none "); + else if (tb[IFLA_IPTUN_ENCAP_LIMIT]) + fprintf(f, "encaplimit %u ", + rta_getattr_u8(tb[IFLA_IPTUN_ENCAP_LIMIT])); + + if (tb[IFLA_IPTUN_TTL]) + fprintf(f, "hoplimit %u ", rta_getattr_u8(tb[IFLA_IPTUN_TTL])); + + if (flags & IP6_TNL_F_USE_ORIG_TCLASS) + printf("tclass inherit "); + else if (tb[IFLA_IPTUN_FLOWINFO]) { + __u32 val = ntohl(flowinfo & IP6_FLOWINFO_TCLASS); + + printf("tclass 0x%02x ", (__u8)(val >> 20)); + } + + if (flags & IP6_TNL_F_USE_ORIG_FLOWLABEL) + printf("flowlabel inherit "); + else + printf("flowlabel 0x%05x ", ntohl(flowinfo & IP6_FLOWINFO_FLOWLABEL)); + + printf("(flowinfo 0x%08x) ", ntohl(flowinfo)); + + if (flags & IP6_TNL_F_RCV_DSCP_COPY) + printf("dscp inherit "); + + if (flags & IP6_TNL_F_MIP6_DEV) + fprintf(f, "mip6 "); + + if (flags & IP6_TNL_F_USE_ORIG_FWMARK) + fprintf(f, "fwmark inherit "); +} + +struct link_util ip6tnl_link_util = { + .id = "ip6tnl", + .maxattr = IFLA_IPTUN_MAX, + .parse_opt = ip6tunnel_parse_opt, + .print_opt = ip6tunnel_print_opt, +}; From 1ce2de97386e38c258ee2048a80ee28d0e8bad01 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Wed, 12 Dec 2012 10:51:47 +0100 Subject: [PATCH 09/60] ip: add support of 'ip link type [ipip|sit]' This patch allows to manage ip tunnels via the interface ip link. The syntax for parameters is the same that 'ip tunnel'. It also allows to display tunnels parameters with 'ip -details link' or 'ip -details monitor link'. Signed-off-by: Nicolas Dichtel --- ip/Makefile | 3 +- ip/iplink.c | 2 +- ip/link_iptnl.c | 340 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 343 insertions(+), 2 deletions(-) create mode 100644 ip/link_iptnl.c diff --git a/ip/Makefile b/ip/Makefile index abf54bf7..2b606d47 100644 --- a/ip/Makefile +++ b/ip/Makefile @@ -4,7 +4,8 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \ ipxfrm.o xfrm_state.o xfrm_policy.o xfrm_monitor.o \ iplink_vlan.o link_veth.o link_gre.o iplink_can.o \ iplink_macvlan.o iplink_macvtap.o ipl2tp.o link_vti.o \ - iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o + iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o \ + link_iptnl.o RTMONOBJ=rtmon.o diff --git a/ip/iplink.c b/ip/iplink.c index 8aac9fc9..d73c705a 100644 --- a/ip/iplink.c +++ b/ip/iplink.c @@ -84,7 +84,7 @@ void iplink_usage(void) if (iplink_have_newlink()) { fprintf(stderr, "\n"); fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | can |\n"); - fprintf(stderr, " bridge | ipoib | ip6tnl }\n"); + fprintf(stderr, " bridge | ipoib | ip6tnl | ipip | sit }\n"); } exit(-1); } diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c new file mode 100644 index 00000000..238722d1 --- /dev/null +++ b/ip/link_iptnl.c @@ -0,0 +1,340 @@ +/* + * link_iptnl.c ipip and sit driver module + * + * 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. + * + * Authors: Nicolas Dichtel + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include "rt_names.h" +#include "utils.h" +#include "ip_common.h" +#include "tunnel.h" + +static void usage(int sit) __attribute__((noreturn)); +static void usage(int sit) +{ + fprintf(stderr, "Usage: ip link { add | set | change | replace | del } NAME\n"); + fprintf(stderr, " type { ipip | sit } [ remote ADDR ] [ local ADDR ]\n"); + fprintf(stderr, " [ ttl TTL ] [ tos TOS ] [ [no]pmtudisc ] [ dev PHYS_DEV ]\n"); + fprintf(stderr, " [ 6rd-prefix ADDR ] [ 6rd-relay_prefix ADDR ] [ 6rd-reset ]\n"); + if (sit) + fprintf(stderr, " [ isatap ]\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Where: NAME := STRING\n"); + fprintf(stderr, " ADDR := { IP_ADDRESS | any }\n"); + fprintf(stderr, " TOS := { NUMBER | inherit }\n"); + fprintf(stderr, " TTL := { 1..255 | inherit }\n"); + exit(-1); +} + +static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv, + struct nlmsghdr *n) +{ + struct { + struct nlmsghdr n; + struct ifinfomsg i; + char buf[2048]; + } req; + struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1); + struct rtattr *tb[IFLA_MAX + 1]; + struct rtattr *linkinfo[IFLA_INFO_MAX+1]; + struct rtattr *iptuninfo[IFLA_IPTUN_MAX + 1]; + int len; + __u32 link = 0; + __u32 laddr = 0; + __u32 raddr = 0; + __u8 ttl = 0; + __u8 tos = 0; + __u8 pmtudisc = 1; + __u16 iflags = 0; + struct in6_addr ip6rdprefix; + __u16 ip6rdprefixlen = 0; + __u32 ip6rdrelayprefix = 0; + __u16 ip6rdrelayprefixlen = 0; + + memset(&ip6rdprefix, 0, sizeof(ip6rdprefix)); + + if (!(n->nlmsg_flags & NLM_F_CREATE)) { + memset(&req, 0, sizeof(req)); + + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)); + req.n.nlmsg_flags = NLM_F_REQUEST; + req.n.nlmsg_type = RTM_GETLINK; + req.i.ifi_family = preferred_family; + req.i.ifi_index = ifi->ifi_index; + + if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) { +get_failed: + fprintf(stderr, + "Failed to get existing tunnel info.\n"); + return -1; + } + + len = req.n.nlmsg_len; + len -= NLMSG_LENGTH(sizeof(*ifi)); + if (len < 0) + goto get_failed; + + parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len); + + if (!tb[IFLA_LINKINFO]) + goto get_failed; + + parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]); + + if (!linkinfo[IFLA_INFO_DATA]) + goto get_failed; + + parse_rtattr_nested(iptuninfo, IFLA_IPTUN_MAX, + linkinfo[IFLA_INFO_DATA]); + + if (iptuninfo[IFLA_IPTUN_LOCAL]) + laddr = rta_getattr_u32(iptuninfo[IFLA_IPTUN_LOCAL]); + + if (iptuninfo[IFLA_IPTUN_REMOTE]) + raddr = rta_getattr_u32(iptuninfo[IFLA_IPTUN_REMOTE]); + + if (iptuninfo[IFLA_IPTUN_TTL]) + ttl = rta_getattr_u8(iptuninfo[IFLA_IPTUN_TTL]); + + if (iptuninfo[IFLA_IPTUN_TOS]) + tos = rta_getattr_u8(iptuninfo[IFLA_IPTUN_TOS]); + + if (iptuninfo[IFLA_IPTUN_PMTUDISC]) + pmtudisc = + rta_getattr_u8(iptuninfo[IFLA_IPTUN_PMTUDISC]); + + if (iptuninfo[IFLA_IPTUN_FLAGS]) + iflags = rta_getattr_u16(iptuninfo[IFLA_IPTUN_FLAGS]); + + if (iptuninfo[IFLA_IPTUN_LINK]) + link = rta_getattr_u32(iptuninfo[IFLA_IPTUN_LINK]); + + if (iptuninfo[IFLA_IPTUN_6RD_PREFIX]) + memcpy(&ip6rdprefix, + RTA_DATA(iptuninfo[IFLA_IPTUN_6RD_PREFIX]), + sizeof(laddr)); + + if (iptuninfo[IFLA_IPTUN_6RD_PREFIXLEN]) + ip6rdprefixlen = + rta_getattr_u16(iptuninfo[IFLA_IPTUN_6RD_PREFIXLEN]); + + if (iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIX]) + ip6rdrelayprefix = + rta_getattr_u32(iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIX]); + + if (iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]) + ip6rdrelayprefixlen = + rta_getattr_u16(iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]); + } + + while (argc > 0) { + if (strcmp(*argv, "remote") == 0) { + NEXT_ARG(); + if (strcmp(*argv, "any")) + raddr = get_addr32(*argv); + else + raddr = 0; + } else if (strcmp(*argv, "local") == 0) { + NEXT_ARG(); + if (strcmp(*argv, "any")) + laddr = get_addr32(*argv); + else + laddr = 0; + } else if (matches(*argv, "dev") == 0) { + NEXT_ARG(); + link = if_nametoindex(*argv); + if (link == 0) + invarg("\"dev\" is invalid", *argv); + } else if (strcmp(*argv, "ttl") == 0 || + strcmp(*argv, "hoplimit") == 0) { + NEXT_ARG(); + if (strcmp(*argv, "inherit") != 0) { + if (get_u8(&ttl, *argv, 0)) + invarg("invalid TTL\n", *argv); + } else + ttl = 0; + } else if (strcmp(*argv, "tos") == 0 || + strcmp(*argv, "tclass") == 0 || + matches(*argv, "dsfield") == 0) { + __u32 uval; + NEXT_ARG(); + if (strcmp(*argv, "inherit") != 0) { + if (rtnl_dsfield_a2n(&uval, *argv)) + invarg("bad TOS value", *argv); + tos = uval; + } else + tos = 1; + } else if (strcmp(*argv, "nopmtudisc") == 0) { + pmtudisc = 0; + } else if (strcmp(*argv, "pmtudisc") == 0) { + pmtudisc = 1; + } else if (strcmp(lu->id, "sit") == 0 && + strcmp(*argv, "isatap") == 0) { + iflags |= SIT_ISATAP; + } else if (strcmp(*argv, "6rd-prefix") == 0) { + inet_prefix prefix; + NEXT_ARG(); + if (get_prefix(&prefix, *argv, AF_INET6)) + invarg("invalid 6rd_prefix\n", *argv); + memcpy(&ip6rdprefix, prefix.data, 16); + ip6rdprefixlen = prefix.bitlen; + } else if (strcmp(*argv, "6rd-relay_prefix") == 0) { + inet_prefix prefix; + NEXT_ARG(); + if (get_prefix(&prefix, *argv, AF_INET)) + invarg("invalid 6rd-relay_prefix\n", *argv); + memcpy(&ip6rdrelayprefix, prefix.data, 4); + ip6rdrelayprefixlen = prefix.bitlen; + } else if (strcmp(*argv, "6rd-reset") == 0) { + inet_prefix prefix; + get_prefix(&prefix, "2002::", AF_INET6); + memcpy(&ip6rdprefix, prefix.data, 16); + ip6rdprefixlen = 16; + ip6rdrelayprefix = 0; + ip6rdrelayprefixlen = 0; + } else + usage(strcmp(lu->id, "sit") == 0); + argc--, argv++; + } + + if (ttl && pmtudisc == 0) { + fprintf(stderr, "ttl != 0 and noptmudisc are incompatible\n"); + exit(-1); + } + + addattr32(n, 1024, IFLA_IPTUN_LINK, link); + addattr32(n, 1024, IFLA_IPTUN_LOCAL, laddr); + addattr32(n, 1024, IFLA_IPTUN_REMOTE, raddr); + addattr8(n, 1024, IFLA_IPTUN_TTL, ttl); + addattr8(n, 1024, IFLA_IPTUN_TOS, tos); + addattr8(n, 1024, IFLA_IPTUN_PMTUDISC, pmtudisc); + if (strcmp(lu->id, "sit") == 0) { + addattr16(n, 1024, IFLA_IPTUN_FLAGS, iflags); + if (ip6rdprefixlen) { + addattr_l(n, 1024, IFLA_IPTUN_6RD_PREFIX, + &ip6rdprefix, sizeof(ip6rdprefix)); + addattr16(n, 1024, IFLA_IPTUN_6RD_PREFIXLEN, + ip6rdprefixlen); + addattr32(n, 1024, IFLA_IPTUN_6RD_RELAY_PREFIX, + ip6rdrelayprefix); + addattr16(n, 1024, IFLA_IPTUN_6RD_RELAY_PREFIXLEN, + ip6rdrelayprefixlen); + } + } + + return 0; +} + +static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) +{ + char s1[1024]; + char s2[64]; + const char *local = "any"; + const char *remote = "any"; + + if (!tb) + return; + + if (tb[IFLA_IPTUN_REMOTE]) { + unsigned addr = rta_getattr_u32(tb[IFLA_IPTUN_REMOTE]); + + if (addr) + remote = format_host(AF_INET, 4, &addr, s1, sizeof(s1)); + } + + fprintf(f, "remote %s ", remote); + + if (tb[IFLA_IPTUN_LOCAL]) { + unsigned addr = rta_getattr_u32(tb[IFLA_IPTUN_LOCAL]); + + if (addr) + local = format_host(AF_INET, 4, &addr, s1, sizeof(s1)); + } + + fprintf(f, "local %s ", local); + + if (tb[IFLA_IPTUN_LINK] && rta_getattr_u32(tb[IFLA_IPTUN_LINK])) { + unsigned link = rta_getattr_u32(tb[IFLA_IPTUN_LINK]); + const char *n = if_indextoname(link, s2); + + if (n) + fprintf(f, "dev %s ", n); + else + fprintf(f, "dev %u ", link); + } + + if (tb[IFLA_IPTUN_TTL] && rta_getattr_u8(tb[IFLA_IPTUN_TTL])) + fprintf(f, "ttl %d ", rta_getattr_u8(tb[IFLA_IPTUN_TTL])); + else + fprintf(f, "ttl inherit "); + + if (tb[IFLA_IPTUN_TOS] && rta_getattr_u8(tb[IFLA_IPTUN_TOS])) { + int tos = rta_getattr_u8(tb[IFLA_IPTUN_TOS]); + + fputs("tos ", f); + if (tos == 1) + fputs("inherit ", f); + else + fprintf(f, "0x%x ", tos); + } + + if (tb[IFLA_IPTUN_PMTUDISC] && rta_getattr_u8(tb[IFLA_IPTUN_PMTUDISC])) + fprintf(f, "pmtudisc "); + else + fprintf(f, "nopmtudisc "); + + if (tb[IFLA_IPTUN_FLAGS]) { + __u16 iflags = rta_getattr_u16(tb[IFLA_IPTUN_FLAGS]); + + if (iflags & SIT_ISATAP) + fprintf(f, "isatap "); + } + + if (tb[IFLA_IPTUN_6RD_PREFIXLEN] && + *(__u16 *)RTA_DATA(tb[IFLA_IPTUN_6RD_PREFIXLEN])) { + __u16 prefixlen = rta_getattr_u16(tb[IFLA_IPTUN_6RD_PREFIXLEN]); + __u16 relayprefixlen = + rta_getattr_u16(tb[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]); + __u32 relayprefix = + rta_getattr_u32(tb[IFLA_IPTUN_6RD_RELAY_PREFIX]); + + printf("6rd-prefix %s/%u ", + inet_ntop(AF_INET6, RTA_DATA(tb[IFLA_IPTUN_6RD_PREFIX]), + s1, sizeof(s1)), + prefixlen); + if (relayprefix) { + printf("6rd-relay_prefix %s/%u ", + format_host(AF_INET, 4, &relayprefix, s1, + sizeof(s1)), + relayprefixlen); + } + } +} + +struct link_util ipip_link_util = { + .id = "ipip", + .maxattr = IFLA_IPTUN_MAX, + .parse_opt = iptunnel_parse_opt, + .print_opt = iptunnel_print_opt, +}; + +struct link_util sit_link_util = { + .id = "sit", + .maxattr = IFLA_IPTUN_MAX, + .parse_opt = iptunnel_parse_opt, + .print_opt = iptunnel_print_opt, +}; From 1556e29d3cce735f9bd93481f4efe4f6e1bbc419 Mon Sep 17 00:00:00 2001 From: David L Stevens Date: Wed, 12 Dec 2012 10:02:19 -0800 Subject: [PATCH 10/60] add DOVE extensions for iproute2 This patch adds a new flag to iproute2 for vxlan devices to enable DOVE features. It also adds support for L2 and L3 switch lookup miss netlink messages to "ip monitor". Changes since v2: fix merge conflict Changes since v1: - split "dove" flag into separate feature flags: - "proxy" for ARP reduction - "rsc" for route short circuiting - "l2miss" for L2 switch miss notifications - "l3miss" for L3 switch miss notifications Signed-off-by: David L Stevens --- ip/iplink_vxlan.c | 44 +++++++++++++++++++++++++++++++++++++++++--- ip/ipmonitor.c | 3 ++- ip/ipneigh.c | 5 ++++- 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/ip/iplink_vxlan.c b/ip/iplink_vxlan.c index ba5c4ab6..4b72361e 100644 --- a/ip/iplink_vxlan.c +++ b/ip/iplink_vxlan.c @@ -26,6 +26,8 @@ static void explain(void) fprintf(stderr, "Usage: ... vxlan id VNI [ group ADDR ] [ local ADDR ]\n"); fprintf(stderr, " [ ttl TTL ] [ tos TOS ] [ dev PHYS_DEV ]\n"); fprintf(stderr, " [ port MIN MAX ] [ [no]learning ]\n"); + fprintf(stderr, " [ [no]proxy ] [ [no]rsc ]\n"); + fprintf(stderr, " [ [no]l2miss ] [ [no]l3miss ]\n"); fprintf(stderr, "\n"); fprintf(stderr, "Where: VNI := 0-16777215\n"); fprintf(stderr, " ADDR := { IP_ADDRESS | any }\n"); @@ -44,6 +46,10 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv, __u8 tos = 0; __u8 ttl = 0; __u8 learning = 1; + __u8 proxy = 0; + __u8 rsc = 0; + __u8 l2miss = 0; + __u8 l3miss = 0; __u8 noage = 0; __u32 age = 0; __u32 maxaddr = 0; @@ -123,6 +129,22 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv, learning = 0; } else if (!matches(*argv, "learning")) { learning = 1; + } else if (!matches(*argv, "noproxy")) { + proxy = 0; + } else if (!matches(*argv, "proxy")) { + proxy = 1; + } else if (!matches(*argv, "norsc")) { + rsc = 0; + } else if (!matches(*argv, "rsc")) { + rsc = 1; + } else if (!matches(*argv, "nol2miss")) { + l2miss = 0; + } else if (!matches(*argv, "l2miss")) { + l2miss = 1; + } else if (!matches(*argv, "nol3miss")) { + l3miss = 0; + } else if (!matches(*argv, "l3miss")) { + l3miss = 1; } else if (matches(*argv, "help") == 0) { explain(); return -1; @@ -148,6 +170,10 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv, addattr8(n, 1024, IFLA_VXLAN_TTL, ttl); addattr8(n, 1024, IFLA_VXLAN_TOS, tos); addattr8(n, 1024, IFLA_VXLAN_LEARNING, learning); + addattr8(n, 1024, IFLA_VXLAN_PROXY, proxy); + addattr8(n, 1024, IFLA_VXLAN_RSC, rsc); + addattr8(n, 1024, IFLA_VXLAN_L2MISS, l2miss); + addattr8(n, 1024, IFLA_VXLAN_L3MISS, l3miss); if (noage) addattr32(n, 1024, IFLA_VXLAN_AGEING, 0); else if (age) @@ -190,7 +216,7 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) if (tb[IFLA_VXLAN_LOCAL]) { __be32 addr = rta_getattr_u32(tb[IFLA_VXLAN_LOCAL]); if (addr) - fprintf(f, "local %s ", + fprintf(f, "local %s ", format_host(AF_INET, 4, &addr, s1, sizeof(s1))); } @@ -208,12 +234,24 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) const struct ifla_vxlan_port_range *r = RTA_DATA(tb[IFLA_VXLAN_PORT_RANGE]); fprintf(f, "port %u %u ", ntohs(r->low), ntohs(r->high)); - } + } if (tb[IFLA_VXLAN_LEARNING] && !rta_getattr_u8(tb[IFLA_VXLAN_LEARNING])) fputs("nolearning ", f); - + + if (tb[IFLA_VXLAN_PROXY] && rta_getattr_u8(tb[IFLA_VXLAN_PROXY])) + fputs("proxy ", f); + + if (tb[IFLA_VXLAN_RSC] && rta_getattr_u8(tb[IFLA_VXLAN_RSC])) + fputs("rsc ", f); + + if (tb[IFLA_VXLAN_L2MISS] && rta_getattr_u8(tb[IFLA_VXLAN_L2MISS])) + fputs("l2miss ", f); + + if (tb[IFLA_VXLAN_L3MISS] && rta_getattr_u8(tb[IFLA_VXLAN_L3MISS])) + fputs("l3miss ", f); + if (tb[IFLA_VXLAN_TOS] && (tos = rta_getattr_u8(tb[IFLA_VXLAN_TOS]))) { if (tos == 1) diff --git a/ip/ipmonitor.c b/ip/ipmonitor.c index d87e58f1..d971623d 100644 --- a/ip/ipmonitor.c +++ b/ip/ipmonitor.c @@ -67,7 +67,8 @@ int accept_msg(const struct sockaddr_nl *who, print_addrlabel(who, n, arg); return 0; } - if (n->nlmsg_type == RTM_NEWNEIGH || n->nlmsg_type == RTM_DELNEIGH) { + if (n->nlmsg_type == RTM_NEWNEIGH || n->nlmsg_type == RTM_DELNEIGH || + n->nlmsg_type == RTM_GETNEIGH) { if (prefix_banner) fprintf(fp, "[NEIGH]"); print_neigh(who, n, arg); diff --git a/ip/ipneigh.c b/ip/ipneigh.c index 56e56b2d..1b7600bb 100644 --- a/ip/ipneigh.c +++ b/ip/ipneigh.c @@ -189,7 +189,8 @@ int print_neigh(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) struct rtattr * tb[NDA_MAX+1]; char abuf[256]; - if (n->nlmsg_type != RTM_NEWNEIGH && n->nlmsg_type != RTM_DELNEIGH) { + if (n->nlmsg_type != RTM_NEWNEIGH && n->nlmsg_type != RTM_DELNEIGH && + n->nlmsg_type != RTM_GETNEIGH) { fprintf(stderr, "Not RTM_NEWNEIGH: %08x %08x %08x\n", n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); @@ -251,6 +252,8 @@ int print_neigh(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) if (n->nlmsg_type == RTM_DELNEIGH) fprintf(fp, "delete "); + else if (n->nlmsg_type == RTM_GETNEIGH) + fprintf(fp, "miss "); if (tb[NDA_DST]) { fprintf(fp, "%s ", format_host(r->ndm_family, From 9dca676721215f82327c9f4b6630a6a37bbd60a4 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Tue, 11 Dec 2012 22:23:09 +0000 Subject: [PATCH 11/60] iproute2: implement add/del mdb entry This patch implements: bridge mdb { add | del } dev DEV port PORT grp GROUP Cc: Stephen Hemminger Cc: Thomas Graf Signed-off-by: Cong Wang --- bridge/mdb.c | 76 +++++++++++++++++++++++++++++++++++++++ include/linux/if_bridge.h | 8 +++++ include/linux/rtnetlink.h | 4 +++ 3 files changed, 88 insertions(+) diff --git a/bridge/mdb.c b/bridge/mdb.c index 390d7f61..4d8a8966 100644 --- a/bridge/mdb.c +++ b/bridge/mdb.c @@ -28,6 +28,7 @@ int filter_index; static void usage(void) { + fprintf(stderr, "Usage: bridge mdb { add | del } dev DEV port PORT grp GROUP\n"); fprintf(stderr, " bridge mdb {show} [ dev DEV ]\n"); exit(-1); } @@ -153,11 +154,86 @@ static int mdb_show(int argc, char **argv) return 0; } +static int mdb_modify(int cmd, int flags, int argc, char **argv) +{ + struct { + struct nlmsghdr n; + struct br_port_msg bpm; + char buf[1024]; + } req; + struct br_mdb_entry entry; + char *d = NULL, *p = NULL, *grp = NULL; + + memset(&req, 0, sizeof(req)); + memset(&entry, 0, sizeof(entry)); + + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct br_port_msg)); + req.n.nlmsg_flags = NLM_F_REQUEST|flags; + req.n.nlmsg_type = cmd; + req.bpm.family = PF_BRIDGE; + + while (argc > 0) { + if (strcmp(*argv, "dev") == 0) { + NEXT_ARG(); + d = *argv; + } else if (strcmp(*argv, "grp") == 0) { + NEXT_ARG(); + grp = *argv; + } else { + if (strcmp(*argv, "port") == 0) { + NEXT_ARG(); + p = *argv; + } + if (matches(*argv, "help") == 0) + usage(); + } + argc--; argv++; + } + + if (d == NULL || grp == NULL || p == NULL) { + fprintf(stderr, "Device, group address and port name are required arguments.\n"); + exit(-1); + } + + req.bpm.ifindex = ll_name_to_index(d); + if (req.bpm.ifindex == 0) { + fprintf(stderr, "Cannot find device \"%s\"\n", d); + return -1; + } + + entry.ifindex = ll_name_to_index(p); + if (entry.ifindex == 0) { + fprintf(stderr, "Cannot find device \"%s\"\n", p); + return -1; + } + + if (!inet_pton(AF_INET, grp, &entry.addr.u.ip4)) { + if (!inet_pton(AF_INET6, grp, &entry.addr.u.ip6)) { + fprintf(stderr, "Invalid address \"%s\"\n", grp); + return -1; + } else + entry.addr.proto = htons(ETH_P_IPV6); + } else + entry.addr.proto = htons(ETH_P_IP); + + addattr_l(&req.n, sizeof(req), MDBA_SET_ENTRY, &entry, sizeof(entry)); + + if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) + exit(2); + + return 0; +} + int do_mdb(int argc, char **argv) { ll_init_map(&rth); if (argc > 0) { + if (matches(*argv, "add") == 0) + return mdb_modify(RTM_NEWMDB, NLM_F_CREATE|NLM_F_EXCL, argc-1, argv+1); + if (matches(*argv, "delete") == 0) + return mdb_modify(RTM_DELMDB, 0, argc-1, argv+1); + if (matches(*argv, "show") == 0 || matches(*argv, "lst") == 0 || matches(*argv, "list") == 0) diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h index 151a8bbe..b3b6a67e 100644 --- a/include/linux/if_bridge.h +++ b/include/linux/if_bridge.h @@ -157,6 +157,7 @@ enum { #define MDBA_ROUTER_MAX (__MDBA_ROUTER_MAX - 1) struct br_port_msg { + __u8 family; __u32 ifindex; }; @@ -171,4 +172,11 @@ struct br_mdb_entry { } addr; }; +enum { + MDBA_SET_ENTRY_UNSPEC, + MDBA_SET_ENTRY, + __MDBA_SET_ENTRY_MAX, +}; +#define MDBA_SET_ENTRY_MAX (__MDBA_SET_ENTRY_MAX - 1) + #endif /* _LINUX_IF_BRIDGE_H */ diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index c82a159d..3ea85dce 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -125,6 +125,10 @@ enum { 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 From 4a4ee61699b8b3ee05fa97f1e90305e4676cf4ec Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Tue, 11 Dec 2012 22:23:10 +0000 Subject: [PATCH 12/60] iproute2: add support to monitor mdb entries too This patch implements `bridge monitor mdb`. Cc: Stephen Hemminger Cc: Thomas Graf Signed-off-by: Cong Wang --- bridge/br_common.h | 2 ++ bridge/mdb.c | 4 ++-- bridge/monitor.c | 14 ++++++++++++++ include/linux/rtnetlink.h | 2 ++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/bridge/br_common.h b/bridge/br_common.h index 892fb76c..10f6ce91 100644 --- a/bridge/br_common.h +++ b/bridge/br_common.h @@ -3,6 +3,8 @@ extern int print_linkinfo(const struct sockaddr_nl *who, void *arg); extern int print_fdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg); +extern int print_mdb(const struct sockaddr_nl *who, + struct nlmsghdr *n, void *arg); extern int do_fdb(int argc, char **argv); extern int do_mdb(int argc, char **argv); diff --git a/bridge/mdb.c b/bridge/mdb.c index 4d8a8966..121ce9c2 100644 --- a/bridge/mdb.c +++ b/bridge/mdb.c @@ -82,8 +82,8 @@ int print_mdb(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) int len = n->nlmsg_len; struct rtattr * tb[MDBA_MAX+1]; - if (n->nlmsg_type != RTM_GETMDB) { - fprintf(stderr, "Not RTM_GETMDB: %08x %08x %08x\n", + if (n->nlmsg_type != RTM_GETMDB && n->nlmsg_type != RTM_NEWMDB && n->nlmsg_type != RTM_DELMDB) { + fprintf(stderr, "Not RTM_GETMDB, RTM_NEWMDB or RTM_DELMDB: %08x %08x %08x\n", n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); return 0; diff --git a/bridge/monitor.c b/bridge/monitor.c index 2f606552..44e14d86 100644 --- a/bridge/monitor.c +++ b/bridge/monitor.c @@ -68,6 +68,12 @@ int accept_msg(const struct sockaddr_nl *who, fprintf(fp, "[NEIGH]"); return print_fdb(who, n, arg); + case RTM_NEWMDB: + case RTM_DELMDB: + if (prefix_banner) + fprintf(fp, "[MDB]"); + return print_mdb(who, n, arg); + case 15: return show_mark(fp, n); @@ -84,6 +90,7 @@ int do_monitor(int argc, char **argv) unsigned groups = ~RTMGRP_TC; int llink=0; int lneigh=0; + int lmdb=0; rtnl_close(&rth); @@ -97,6 +104,9 @@ int do_monitor(int argc, char **argv) } else if (matches(*argv, "fdb") == 0) { lneigh = 1; groups = 0; + } else if (matches(*argv, "mdb") == 0) { + lmdb = 1; + groups = 0; } else if (strcmp(*argv, "all") == 0) { groups = ~RTMGRP_TC; prefix_banner=1; @@ -116,6 +126,10 @@ int do_monitor(int argc, char **argv) groups |= nl_mgrp(RTNLGRP_NEIGH); } + if (lmdb) { + groups |= nl_mgrp(RTNLGRP_MDB); + } + if (file) { FILE *fp; fp = fopen(file, "r"); diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index 3ea85dce..87452b4f 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -609,6 +609,8 @@ enum rtnetlink_groups { #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_MAX }; #define RTNLGRP_MAX (__RTNLGRP_MAX - 1) From 176659e38ed381080b0f68d2a780f2db4b244a75 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Fri, 14 Dec 2012 13:59:32 +0800 Subject: [PATCH 13/60] iproute2: update usage info of bridge monitor Cc: Stephen Hemminger Signed-off-by: Cong Wang --- bridge/monitor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bridge/monitor.c b/bridge/monitor.c index 44e14d86..29bb931b 100644 --- a/bridge/monitor.c +++ b/bridge/monitor.c @@ -31,7 +31,7 @@ int prefix_banner; static void usage(void) { - fprintf(stderr, "Usage: bridge monitor\n"); + fprintf(stderr, "Usage: bridge monitor [file | link | fdb | mdb | all]\n"); exit(-1); } From 195f0f62d7ae3eb1f98dda46de852660503370eb Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Fri, 14 Dec 2012 09:50:33 -0800 Subject: [PATCH 14/60] ip/link_iptnl: fix indentation Logged in as shemminger Use tabs instead of space when possible. Signed-off-by: Nicolas Dichtel --- ip/link_iptnl.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c index 238722d1..b00d8d90 100644 --- a/ip/link_iptnl.c +++ b/ip/link_iptnl.c @@ -298,10 +298,10 @@ static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[ fprintf(f, "nopmtudisc "); if (tb[IFLA_IPTUN_FLAGS]) { - __u16 iflags = rta_getattr_u16(tb[IFLA_IPTUN_FLAGS]); + __u16 iflags = rta_getattr_u16(tb[IFLA_IPTUN_FLAGS]); - if (iflags & SIT_ISATAP) - fprintf(f, "isatap "); + if (iflags & SIT_ISATAP) + fprintf(f, "isatap "); } if (tb[IFLA_IPTUN_6RD_PREFIXLEN] && @@ -314,12 +314,12 @@ static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[ printf("6rd-prefix %s/%u ", inet_ntop(AF_INET6, RTA_DATA(tb[IFLA_IPTUN_6RD_PREFIX]), - s1, sizeof(s1)), + s1, sizeof(s1)), prefixlen); if (relayprefix) { printf("6rd-relay_prefix %s/%u ", format_host(AF_INET, 4, &relayprefix, s1, - sizeof(s1)), + sizeof(s1)), relayprefixlen); } } From 2a898320be19c0a12e1eb2c8ab1ab9c9976e9ded Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Fri, 14 Dec 2012 09:56:47 -0800 Subject: [PATCH 15/60] ip: update mand pages and usage() for 'ip mroute' Sync with the current code. Signed-off-by: Nicolas Dichtel --- ip/ipmroute.c | 2 ++ man/man8/ip-mroute.8 | 14 +++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/ip/ipmroute.c b/ip/ipmroute.c index 945727d3..e1f96174 100644 --- a/ip/ipmroute.c +++ b/ip/ipmroute.c @@ -36,6 +36,8 @@ static void usage(void) __attribute__((noreturn)); static void usage(void) { fprintf(stderr, "Usage: ip mroute show [ PREFIX ] [ from PREFIX ] [ iif DEVICE ]\n"); + fprintf(stderr, " [ table TABLE_ID ]\n"); + fprintf(stderr, "TABLE_ID := [ local | main | default | all | NUMBER ]\n"); #if 0 fprintf(stderr, "Usage: ip mroute [ add | del ] DESTINATION from SOURCE [ iif DEVICE ] [ oif DEVICE ]\n"); #endif diff --git a/man/man8/ip-mroute.8 b/man/man8/ip-mroute.8 index 98aab88f..870df5e8 100644 --- a/man/man8/ip-mroute.8 +++ b/man/man8/ip-mroute.8 @@ -1,4 +1,4 @@ -.TH IP\-MROUTE 8 "20 Dec 2011" "iproute2" "Linux" +.TH IP\-MROUTE 8 "13 Dec 2012" "iproute2" "Linux" .SH "NAME" ip-mroute \- multicast routing cache management .SH "SYNOPSIS" @@ -6,12 +6,15 @@ ip-mroute \- multicast routing cache management .ad l .in +8 .ti -8 -.BR "ip mroute show" " [" +.BR "ip " " [ ip-OPTIONS ] " "mroute show" " [ [ " +.BR " to " " ] " .IR PREFIX " ] [ " .B from .IR PREFIX " ] [ " .B iif -.IR DEVICE " ]" +.IR DEVICE " ] [ " +.B table +.IR TABLE_ID " ] " .SH DESCRIPTION .B mroute @@ -42,6 +45,11 @@ the interface on which multicast packets are received. .BI from " PREFIX" the prefix selecting the IP source addresses of the multicast route. +.TP +.BI table " TABLE_ID" +the table id selecting the multicast table. It can be +.BR local ", " main ", " default ", " all " or a number." + .SH SEE ALSO .br .BR ip (8) From 77987911e5c3beab9b3a20c13ba63b5c441e16f5 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Thu, 13 Dec 2012 03:42:52 +0000 Subject: [PATCH 16/60] ip: update man pages for 'ip link' Now 'ip link' supports ipip, sit and ip6tnl. Signed-off-by: Nicolas Dichtel --- man/man8/ip-link.8.in | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in index 43c4ac6b..8d2a6f99 100644 --- a/man/man8/ip-link.8.in +++ b/man/man8/ip-link.8.in @@ -1,4 +1,4 @@ -.TH IP\-LINK 8 "20 Dec 2011" "iproute2" "Linux" +.TH IP\-LINK 8 "13 Dec 2012" "iproute2" "Linux" .SH "NAME" ip-link \- network device configuration .SH "SYNOPSIS" @@ -59,7 +59,10 @@ ip-link \- network device configuration .BR vcan " | " .BR veth " | " .BR vlan " | " -.BR vxlan " ]" +.BR vxlan " |" +.BR ip6tnl " |" +.BR ipip " |" +.BR sit " ]" .ti -8 .BI "ip link delete " DEVICE @@ -174,6 +177,15 @@ Link types: .sp .BR vxlan - Virtual eXtended LAN +.sp +.BR ip6tnl +- Virtual tunnel interface IPv4|IPv6 over IPv6 +.sp +.BR ipip +- Virtual tunnel interface IPv4 over IPv4 +.sp +.BR sit +- Virtual tunnel interface IPv6 over IPv4 .in -8 .TP From e509fb1b68c5091982b2203638837390abd911cc Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Thu, 13 Dec 2012 03:42:53 +0000 Subject: [PATCH 17/60] ip: term OPTIONS was used twice in 'ip route' man pages INFO_SPEC already uses the term 'OPTIONS' and describe it. Signed-off-by: Nicolas Dichtel --- man/man8/ip-route.8.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/man/man8/ip-route.8.in b/man/man8/ip-route.8.in index f06fcbab..2c35a973 100644 --- a/man/man8/ip-route.8.in +++ b/man/man8/ip-route.8.in @@ -1,4 +1,4 @@ -.TH IP\-ROUTE 8 "20 Dec 2011" "iproute2" "Linux" +.TH IP\-ROUTE 8 "13 Dec 2012" "iproute2" "Linux" .SH "NAME" ip-route \- routing table management .SH "SYNOPSIS" @@ -7,7 +7,7 @@ ip-route \- routing table management .in +8 .ti -8 .B ip -.RI "[ " OPTIONS " ]" +.RI "[ " ip-OPTIONS " ]" .B route .RI " { " COMMAND " | " .BR help " }" From e34d3dcce27d43d3ae96a299e74bf457c42badd2 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Fri, 14 Dec 2012 10:08:17 -0800 Subject: [PATCH 18/60] ip: use rtnelink to manage mroute mroute was using /proc/net/ip_mr_[vif|cache] to display mroute entries. Hence, only RT_TABLE_DEFAULT was displayed and only IPv4. With rtnetlink, it is possible to display all tables for IPv4 and IPv6. The output format is kept. Also, like before the patch, statistics are displayed when user specify the '-s' argument. The patch also adds the support of 'ip monitor mroute', which is now possible. Signed-off-by: Nicolas Dichtel --- ip/ip_common.h | 3 + ip/ipmonitor.c | 35 ++++++- ip/ipmroute.c | 275 ++++++++++++++++++++++++++++++------------------- 3 files changed, 203 insertions(+), 110 deletions(-) diff --git a/ip/ip_common.h b/ip/ip_common.h index a3946690..de568101 100644 --- a/ip/ip_common.h +++ b/ip/ip_common.h @@ -16,11 +16,14 @@ extern int ipaddr_list_link(int argc, char **argv); extern int iproute_monitor(int argc, char **argv); extern void iplink_usage(void) __attribute__((noreturn)); extern void iproute_reset_filter(void); +extern void ipmroute_reset_filter(void); extern void ipaddr_reset_filter(int); extern void ipneigh_reset_filter(void); extern void ipntable_reset_filter(void); extern int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg); +extern int print_mroute(const struct sockaddr_nl *who, + struct nlmsghdr *n, void *arg); extern int print_prefix(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg); extern int print_rule(const struct sockaddr_nl *who, diff --git a/ip/ipmonitor.c b/ip/ipmonitor.c index d971623d..09a339cf 100644 --- a/ip/ipmonitor.c +++ b/ip/ipmonitor.c @@ -43,10 +43,26 @@ int accept_msg(const struct sockaddr_nl *who, print_timestamp(fp); if (n->nlmsg_type == RTM_NEWROUTE || n->nlmsg_type == RTM_DELROUTE) { - if (prefix_banner) - fprintf(fp, "[ROUTE]"); - print_route(who, n, arg); - return 0; + struct rtmsg *r = NLMSG_DATA(n); + int len = n->nlmsg_len - NLMSG_LENGTH(sizeof(*r)); + + if (len < 0) { + fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); + return -1; + } + + if (r->rtm_family == RTNL_FAMILY_IPMR || + r->rtm_family == RTNL_FAMILY_IP6MR) { + if (prefix_banner) + fprintf(fp, "[MROUTE]"); + print_mroute(who, n, arg); + return 0; + } else { + if (prefix_banner) + fprintf(fp, "[ROUTE]"); + print_route(who, n, arg); + return 0; + } } if (n->nlmsg_type == RTM_NEWLINK || n->nlmsg_type == RTM_DELLINK) { ll_remember_index(who, n, NULL); @@ -123,6 +139,7 @@ int do_ipmonitor(int argc, char **argv) int llink=0; int laddr=0; int lroute=0; + int lmroute=0; int lprefix=0; int lneigh=0; int lnetconf=0; @@ -130,6 +147,7 @@ int do_ipmonitor(int argc, char **argv) rtnl_close(&rth); ipaddr_reset_filter(1); iproute_reset_filter(); + ipmroute_reset_filter(); ipneigh_reset_filter(); while (argc > 0) { @@ -145,6 +163,9 @@ int do_ipmonitor(int argc, char **argv) } else if (matches(*argv, "route") == 0) { lroute=1; groups = 0; + } else if (matches(*argv, "mroute") == 0) { + lmroute=1; + groups = 0; } else if (matches(*argv, "prefix") == 0) { lprefix=1; groups = 0; @@ -180,6 +201,12 @@ int do_ipmonitor(int argc, char **argv) if (!preferred_family || preferred_family == AF_INET6) groups |= nl_mgrp(RTNLGRP_IPV6_ROUTE); } + if (lmroute) { + if (!preferred_family || preferred_family == AF_INET) + groups |= nl_mgrp(RTNLGRP_IPV4_MROUTE); + if (!preferred_family || preferred_family == AF_INET6) + groups |= nl_mgrp(RTNLGRP_IPV6_MROUTE); + } if (lprefix) { if (!preferred_family || preferred_family == AF_INET6) groups |= nl_mgrp(RTNLGRP_IPV6_PREFIX); diff --git a/ip/ipmroute.c b/ip/ipmroute.c index e1f96174..345576d0 100644 --- a/ip/ipmroute.c +++ b/ip/ipmroute.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -26,16 +27,15 @@ #include #include +#include #include "utils.h" - -char filter_dev[16]; -int filter_family; +#include "ip_common.h" static void usage(void) __attribute__((noreturn)); static void usage(void) { - fprintf(stderr, "Usage: ip mroute show [ PREFIX ] [ from PREFIX ] [ iif DEVICE ]\n"); + fprintf(stderr, "Usage: ip mroute show [ [ to ] PREFIX ] [ from PREFIX ] [ iif DEVICE ]\n"); fprintf(stderr, " [ table TABLE_ID ]\n"); fprintf(stderr, "TABLE_ID := [ local | main | default | all | NUMBER ]\n"); #if 0 @@ -44,151 +44,214 @@ static void usage(void) exit(-1); } -static char *viftable[32]; - struct rtfilter { + int tb; + int af; + int iif; inet_prefix mdst; inet_prefix msrc; } filter; -static void read_viftable(void) +int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { - char buf[256]; - FILE *fp = fopen("/proc/net/ip_mr_vif", "r"); + FILE *fp = (FILE*)arg; + struct rtmsg *r = NLMSG_DATA(n); + int len = n->nlmsg_len; + struct rtattr * tb[RTA_MAX+1]; + char abuf[256]; + char obuf[256]; + SPRINT_BUF(b1); + __u32 table; + int iif = 0; + int family; - if (!fp) - return; - - if (!fgets(buf, sizeof(buf), fp)) { - fclose(fp); - return; + if ((n->nlmsg_type != RTM_NEWROUTE && + n->nlmsg_type != RTM_DELROUTE) || + !(n->nlmsg_flags & NLM_F_MULTI)) { + fprintf(stderr, "Not a multicast route: %08x %08x %08x\n", + n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); + return 0; } - while (fgets(buf, sizeof(buf), fp)) { - int vifi; - char dev[256]; - - if (sscanf(buf, "%d%s", &vifi, dev) < 2) - continue; - - if (vifi<0 || vifi>31) - continue; - - viftable[vifi] = strdup(dev); + len -= NLMSG_LENGTH(sizeof(*r)); + if (len < 0) { + fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); + return -1; } - fclose(fp); -} - -static void read_mroute_list(FILE *ofp) -{ - char buf[256]; - FILE *fp = fopen("/proc/net/ip_mr_cache", "r"); - - if (!fp) - return; - - if (!fgets(buf, sizeof(buf), fp)) { - fclose(fp); - return; + if (r->rtm_type != RTN_MULTICAST) { + fprintf(stderr, "Not a multicast route (type: %s)\n", + rtnl_rtntype_n2a(r->rtm_type, b1, sizeof(b1))); + return 0; } - while (fgets(buf, sizeof(buf), fp)) { - inet_prefix maddr, msrc; - unsigned pkts, b, w; - int vifi; - char oiflist[256]; - char sbuf[256]; - char mbuf[256]; - char obuf[256]; + parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len); + table = rtm_get_table(r, tb); - oiflist[0] = 0; - if (sscanf(buf, "%x%x%d%u%u%u %[^\n]", - maddr.data, msrc.data, &vifi, - &pkts, &b, &w, oiflist) < 6) - continue; + if (filter.tb > 0 && filter.tb != table) + return 0; - if (vifi!=-1 && (vifi < 0 || vifi>31)) - continue; + if (tb[RTA_IIF]) + iif = *(int*)RTA_DATA(tb[RTA_IIF]); + if (filter.iif && filter.iif != iif) + return 0; - if (filter_dev[0] && (vifi<0 || strcmp(filter_dev, viftable[vifi]))) - continue; - if (filter.mdst.family && inet_addr_match(&maddr, &filter.mdst, filter.mdst.bitlen)) - continue; - if (filter.msrc.family && inet_addr_match(&msrc, &filter.msrc, filter.msrc.bitlen)) - continue; + if (filter.af && filter.af != r->rtm_family) + return 0; - snprintf(obuf, sizeof(obuf), "(%s, %s)", - format_host(AF_INET, 4, &msrc.data[0], sbuf, sizeof(sbuf)), - format_host(AF_INET, 4, &maddr.data[0], mbuf, sizeof(mbuf))); + if (tb[RTA_DST] && + filter.mdst.bitlen > 0 && + inet_addr_match(RTA_DATA(tb[RTA_DST]), &filter.mdst, filter.mdst.bitlen)) + return 0; - fprintf(ofp, "%-32s Iif: ", obuf); + if (tb[RTA_SRC] && + filter.msrc.bitlen > 0 && + inet_addr_match(RTA_DATA(tb[RTA_SRC]), &filter.msrc, filter.msrc.bitlen)) + return 0; - if (vifi == -1) - fprintf(ofp, "unresolved "); - else - fprintf(ofp, "%-10s ", viftable[vifi]); + family = r->rtm_family == RTNL_FAMILY_IPMR ? AF_INET : AF_INET6; - if (oiflist[0]) { - char *next = NULL; - char *p = oiflist; - int ovifi, ottl; + if (n->nlmsg_type == RTM_DELROUTE) + fprintf(fp, "Deleted "); - fprintf(ofp, "Oifs: "); + if (tb[RTA_SRC]) + len = snprintf(obuf, sizeof(obuf), + "(%s, ", rt_addr_n2a(family, + RTA_PAYLOAD(tb[RTA_SRC]), + RTA_DATA(tb[RTA_SRC]), + abuf, sizeof(abuf))); + else + len = sprintf(obuf, "(unknown, "); + if (tb[RTA_DST]) + snprintf(obuf + len, sizeof(obuf) - len, + "%s)", rt_addr_n2a(family, RTA_PAYLOAD(tb[RTA_DST]), + RTA_DATA(tb[RTA_DST]), + abuf, sizeof(abuf))); + else + snprintf(obuf + len, sizeof(obuf) - len, "unknown) "); - while (p) { - next = strchr(p, ' '); - if (next) { - *next = 0; - next++; - } - if (sscanf(p, "%d:%d", &ovifi, &ottl)<2) { - p = next; - continue; - } - p = next; + fprintf(fp, "%-32s Iif: ", obuf); + if (iif) + fprintf(fp, "%-10s ", ll_index_to_name(iif)); + else + fprintf(fp, "unresolved "); - fprintf(ofp, "%s", viftable[ovifi]); - if (ottl>1) - fprintf(ofp, "(ttl %d) ", ovifi); - else - fprintf(ofp, " "); + if (tb[RTA_MULTIPATH]) { + struct rtnexthop *nh = RTA_DATA(tb[RTA_MULTIPATH]); + int first = 1; + + len = RTA_PAYLOAD(tb[RTA_MULTIPATH]); + + for (;;) { + if (len < sizeof(*nh)) + break; + if (nh->rtnh_len > len) + break; + + if (first) { + fprintf(fp, "Oifs: "); + first = 0; } + fprintf(fp, "%s", ll_index_to_name(nh->rtnh_ifindex)); + if (nh->rtnh_hops > 1) + fprintf(fp, "(ttl %d) ", nh->rtnh_hops); + else + fprintf(fp, " "); + len -= NLMSG_ALIGN(nh->rtnh_len); + nh = RTNH_NEXT(nh); } - - if (show_stats && b) { - fprintf(ofp, "%s %u packets, %u bytes", _SL_, pkts, b); - if (w) - fprintf(ofp, ", %u arrived on wrong iif.", w); - } - fprintf(ofp, "\n"); } - fclose(fp); + if (show_stats && tb[RTA_MFC_STATS]) { + struct rta_mfc_stats *mfcs = RTA_DATA(tb[RTA_MFC_STATS]); + + fprintf(fp, "%s %"PRIu64" packets, %"PRIu64" bytes", _SL_, + (uint64_t)mfcs->mfcs_packets, + (uint64_t)mfcs->mfcs_bytes); + if (mfcs->mfcs_wrong_if) + fprintf(fp, ", %"PRIu64" arrived on wrong iif.", + (uint64_t)mfcs->mfcs_wrong_if); + } + fprintf(fp, "\n"); + fflush(fp); + return 0; } +void ipmroute_reset_filter(void) +{ + memset(&filter, 0, sizeof(filter)); + filter.mdst.bitlen = -1; + filter.msrc.bitlen = -1; +} static int mroute_list(int argc, char **argv) { + char *id = NULL; + int family; + + ipmroute_reset_filter(); + if (preferred_family == AF_UNSPEC) + family = AF_INET; + else + family = AF_INET6; + if (family == AF_INET) { + filter.af = RTNL_FAMILY_IPMR; + filter.tb = RT_TABLE_DEFAULT; /* for backward compatibility */ + } else + filter.af = RTNL_FAMILY_IP6MR; + while (argc > 0) { - if (strcmp(*argv, "iif") == 0) { + if (matches(*argv, "table") == 0) { + __u32 tid; NEXT_ARG(); - strncpy(filter_dev, *argv, sizeof(filter_dev)-1); + if (rtnl_rttable_a2n(&tid, *argv)) { + if (strcmp(*argv, "all") == 0) { + filter.tb = 0; + } else if (strcmp(*argv, "help") == 0) { + usage(); + } else { + invarg("table id value is invalid\n", *argv); + } + } else + filter.tb = tid; + } else if (strcmp(*argv, "iif") == 0) { + NEXT_ARG(); + id = *argv; } else if (matches(*argv, "from") == 0) { NEXT_ARG(); - get_prefix(&filter.msrc, *argv, AF_INET); + get_prefix(&filter.msrc, *argv, family); } else { if (strcmp(*argv, "to") == 0) { NEXT_ARG(); } if (matches(*argv, "help") == 0) usage(); - get_prefix(&filter.mdst, *argv, AF_INET); + get_prefix(&filter.mdst, *argv, family); } - argv++; argc--; + argc--; argv++; } - read_viftable(); - read_mroute_list(stdout); - return 0; + ll_init_map(&rth); + + if (id) { + int idx; + + if ((idx = ll_name_to_index(id)) == 0) { + fprintf(stderr, "Cannot find device \"%s\"\n", id); + return -1; + } + filter.iif = idx; + } + + if (rtnl_wilddump_request(&rth, filter.af, RTM_GETROUTE) < 0) { + perror("Cannot send dump request"); + return 1; + } + + if (rtnl_dump_filter(&rth, print_mroute, stdout) < 0) { + fprintf(stderr, "Dump terminated\n"); + exit(1); + } + + exit(0); } int do_multiroute(int argc, char **argv) From 602e9d36ba09b34f4ec97bd539a2a6f5247c5b5c Mon Sep 17 00:00:00 2001 From: Zhi Yong Wu Date: Sun, 16 Dec 2012 00:21:08 +0800 Subject: [PATCH 19/60] ip: add the type 'vxlan' in the output of "ip link help" The new type 'vxlan' is added in the output of "ip link help" Signed-off-by: Zhi Yong Wu --- ip/iplink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ip/iplink.c b/ip/iplink.c index d73c705a..5ff8f858 100644 --- a/ip/iplink.c +++ b/ip/iplink.c @@ -84,7 +84,7 @@ void iplink_usage(void) if (iplink_have_newlink()) { fprintf(stderr, "\n"); fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | can |\n"); - fprintf(stderr, " bridge | ipoib | ip6tnl | ipip | sit }\n"); + fprintf(stderr, " bridge | ipoib | ip6tnl | ipip | sit | vxlan }\n"); } exit(-1); } From 743a00a72b18414f18978d886035b3f2aed45457 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Mon, 17 Dec 2012 17:41:26 +0100 Subject: [PATCH 20/60] ip: add man pages for netconf This patch add the documentation about 'ip netconf' command. Signed-off-by: Nicolas Dichtel --- man/man8/Makefile | 2 +- man/man8/ip-netconf.8 | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 man/man8/ip-netconf.8 diff --git a/man/man8/Makefile b/man/man8/Makefile index 4bad9d63..d208f3b0 100644 --- a/man/man8/Makefile +++ b/man/man8/Makefile @@ -9,7 +9,7 @@ MAN8PAGES = $(TARGETS) ip.8 arpd.8 lnstat.8 routel.8 rtacct.8 rtmon.8 ss.8 \ ip-addrlabel.8 ip-l2tp.8 \ ip-maddress.8 ip-monitor.8 ip-mroute.8 ip-neighbour.8 \ ip-netns.8 ip-ntable.8 ip-rule.8 ip-tunnel.8 ip-xfrm.8 \ - ip-tcp_metrics.8 + ip-tcp_metrics.8 ip-netconf.8 all: $(TARGETS) diff --git a/man/man8/ip-netconf.8 b/man/man8/ip-netconf.8 new file mode 100644 index 00000000..8041ea23 --- /dev/null +++ b/man/man8/ip-netconf.8 @@ -0,0 +1,36 @@ +.TH IP\-NETCONF 8 "13 Dec 2012" "iproute2" "Linux" +.SH "NAME" +ip-netconf \- network configuration monitoring +.SH "SYNOPSIS" +.sp +.ad l +.in +8 +.ti -8 +.BR "ip " " [ ip-OPTIONS ] " "netconf show" " [ " +.B dev +.IR STRING " ]" + +.SH DESCRIPTION +The +.B ip netconf +utility can monitor IPv4 and IPv6 parameters (see +.BR "/proc/sys/net/ipv[4|6]/conf/[all|DEV]/" ")" +like forwarding, rp_filter +or mc_forwarding status. + +If no interface is specified, the entry +.B all +is displayed. + +.SS ip netconf show - display network parameters + +.TP +.BI dev " STRING" +the name of the device to display network parameters. + +.SH SEE ALSO +.br +.BR ip (8) + +.SH AUTHOR +Original Manpage by Nicolas Dichtel From cbe195dc6b151348839f16c7e6d7cdf3d81af485 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Mon, 17 Dec 2012 17:41:27 +0100 Subject: [PATCH 21/60] ip: update man pages and usage() for 'ip monitor' Sync with the current code. Signed-off-by: Nicolas Dichtel --- ip/ipmonitor.c | 5 ++++- man/man8/ip-monitor.8 | 15 +++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/ip/ipmonitor.c b/ip/ipmonitor.c index 09a339cf..a9ff1e85 100644 --- a/ip/ipmonitor.c +++ b/ip/ipmonitor.c @@ -29,7 +29,10 @@ int prefix_banner; static void usage(void) { - fprintf(stderr, "Usage: ip monitor [ all | LISTofOBJECTS ]\n"); + fprintf(stderr, "Usage: ip monitor [ all | LISTofOBJECTS ] [ FILE ]\n"); + fprintf(stderr, "LISTofOBJECTS := link | address | route | mroute | prefix |\n"); + fprintf(stderr, " neigh | netconf\n"); + fprintf(stderr, "FILE := file FILENAME\n"); exit(-1); } diff --git a/man/man8/ip-monitor.8 b/man/man8/ip-monitor.8 index 351a7444..b07cb0e2 100644 --- a/man/man8/ip-monitor.8 +++ b/man/man8/ip-monitor.8 @@ -1,4 +1,4 @@ -.TH IP\-MONITOR 8 "20 Dec 2011" "iproute2" "Linux" +.TH IP\-MONITOR 8 "13 Dec 2012" "iproute2" "Linux" .SH "NAME" ip-monitor, rtmon \- state monitoring .SH "SYNOPSIS" @@ -6,8 +6,8 @@ ip-monitor, rtmon \- state monitoring .ad l .in +8 .ti -8 -.BR "ip monitor" " [ " all " |" -.IR LISTofOBJECTS " ]" +.BR "ip " " [ ip-OPTIONS ] " "monitor" " [ " all " |" +.IR LISTofOBJECTS " ] [ file " FILENAME " ] .sp .SH DESCRIPTION @@ -20,12 +20,13 @@ Namely, the command is the first in the command line and then the object list follows: .BR "ip monitor" " [ " all " |" -.IR LISTofOBJECTS " ]" +.IR LISTofOBJECTS " ] [ file " FILENAME " ] .I OBJECT-LIST is the list of object types that we want to monitor. It may contain -.BR link ", " address " and " route "." +.BR link ", " address ", " route ", " mroute ", " prefix ", " +.BR neigh " and " netconf "." If no .B file argument is given, @@ -34,7 +35,9 @@ opens RTNETLINK, listens on it and dumps state changes in the format described in previous sections. .P -If a file name is given, it does not listen on RTNETLINK, +If a +.I FILENAME +is given, it does not listen on RTNETLINK, but opens the file containing RTNETLINK messages saved in binary format and dumps them. Such a history file can be generated with the .B rtmon From 601f60e5527abba9332806fab2b04f2a82e9459e Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sun, 16 Dec 2012 17:09:15 -0500 Subject: [PATCH 22/60] configure: move toolchain init to a function The layout of this file uses functions to update Config. Move the toolchain logic to the same style to fix setting the vars in Config. Signed-off-by: Mike Frysinger --- configure | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/configure b/configure index 99121144..ea1038df 100755 --- a/configure +++ b/configure @@ -2,14 +2,19 @@ # This is not an autconf generated configure # INCLUDE=${1:-"$PWD/include"} -: ${PKG_CONFIG:=pkg-config} -: ${CC=gcc} -echo "PKG_CONFIG:=${PKG_CONFIG}" >>Config # Make a temp directory in build tree. TMPDIR=$(mktemp -d config.XXXXXX) trap 'status=$?; rm -rf $TMPDIR; exit $status' EXIT HUP INT QUIT TERM +check_toolchain() +{ +: ${PKG_CONFIG:=pkg-config} +: ${CC=gcc} +echo "CC:=${CC}" >>Config +echo "PKG_CONFIG:=${PKG_CONFIG}" >>Config +} + check_atm() { cat >$TMPDIR/atmtest.c <Config +check_toolchain echo "TC schedulers" From 691c8a65677e8371da2c18c97ec5e7501dec8d18 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sun, 16 Dec 2012 17:09:16 -0500 Subject: [PATCH 23/60] lib: include the Config file too The lib makefile doesn't include Config which means it misses setting up toolchain vars that it includes. Signed-off-by: Mike Frysinger --- lib/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/Makefile b/lib/Makefile index bfbe6725..a42b8859 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -1,3 +1,5 @@ +include ../Config + CFLAGS += -fPIC UTILOBJ=utils.o rt_names.o ll_types.o ll_proto.o ll_addr.o inet_proto.o From 95d9d665d9dc5bdb0be84d2caa405e9487bd88ad Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sun, 16 Dec 2012 17:09:17 -0500 Subject: [PATCH 24/60] configure: pull AR from the env too This matches the existing CC behavior. Signed-off-by: Mike Frysinger --- configure | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure b/configure index ea1038df..7c2db9be 100755 --- a/configure +++ b/configure @@ -10,7 +10,9 @@ trap 'status=$?; rm -rf $TMPDIR; exit $status' EXIT HUP INT QUIT TERM check_toolchain() { : ${PKG_CONFIG:=pkg-config} +: ${AR=ar} : ${CC=gcc} +echo "AR:=${AR}" >>Config echo "CC:=${CC}" >>Config echo "PKG_CONFIG:=${PKG_CONFIG}" >>Config } From d29feaaa35f6ad3b2a4aa79d8b540b6bfd3e94bd Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Tue, 18 Dec 2012 09:18:45 -0800 Subject: [PATCH 25/60] build: unbreak linakge of m_xt.so Commit v3.7.0~10 caused the variable new PKG_CONFIG variable never to be present at the time of calling make, leading to tc/m_xt.so not linked with -lxtables (result from pkg-config xtables --libs), that in turn leading to tc: symbol lookup error: /usr/lib64/tc//m_xt.so: undefined symbol: xtables_init_all Fixing that. Signed-off-by: Jan Engelhardt --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 7c2db9be..f0540c3c 100755 --- a/configure +++ b/configure @@ -14,7 +14,6 @@ check_toolchain() : ${CC=gcc} echo "AR:=${AR}" >>Config echo "CC:=${CC}" >>Config -echo "PKG_CONFIG:=${PKG_CONFIG}" >>Config } check_atm() @@ -231,6 +230,7 @@ rm -f $TMPDIR/ipsettest.c $TMPDIR/ipsettest } echo "# Generated config based on" $INCLUDE >Config +echo "PKG_CONFIG:=${PKG_CONFIG}" >>Config check_toolchain echo "TC schedulers" From 07a6f5eca27c11110f4aaec2dcc07ca12021c924 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 18 Dec 2012 09:20:13 -0800 Subject: [PATCH 26/60] build: indent shell functions in configure Script has lots of shell functions but never indented properly. --- configure | 121 +++++++++++++++++++++++++++--------------------------- 1 file changed, 61 insertions(+), 60 deletions(-) diff --git a/configure b/configure index f0540c3c..511b3439 100755 --- a/configure +++ b/configure @@ -1,5 +1,5 @@ #! /bin/bash -# This is not an autconf generated configure +# This is not an autoconf generated configure # INCLUDE=${1:-"$PWD/include"} @@ -9,16 +9,16 @@ trap 'status=$?; rm -rf $TMPDIR; exit $status' EXIT HUP INT QUIT TERM check_toolchain() { -: ${PKG_CONFIG:=pkg-config} -: ${AR=ar} -: ${CC=gcc} -echo "AR:=${AR}" >>Config -echo "CC:=${CC}" >>Config + : ${PKG_CONFIG:=pkg-config} + : ${AR=ar} + : ${CC=gcc} + echo "AR:=${AR}" >>Config + echo "CC:=${CC}" >>Config } check_atm() { -cat >$TMPDIR/atmtest.c <$TMPDIR/atmtest.c < int main(int argc, char **argv) { struct atm_qos qos; @@ -26,21 +26,22 @@ int main(int argc, char **argv) { return 0; } EOF -$CC -I$INCLUDE -o $TMPDIR/atmtest $TMPDIR/atmtest.c -latm >/dev/null 2>&1 -if [ $? -eq 0 ] -then - echo "TC_CONFIG_ATM:=y" >>Config - echo yes -else - echo no -fi -rm -f $TMPDIR/atmtest.c $TMPDIR/atmtest + + $CC -I$INCLUDE -o $TMPDIR/atmtest $TMPDIR/atmtest.c -latm >/dev/null 2>&1 + if [ $? -eq 0 ] + then + echo "TC_CONFIG_ATM:=y" >>Config + echo yes + else + echo no + fi + rm -f $TMPDIR/atmtest.c $TMPDIR/atmtest } check_xt() { -#check if we have xtables from iptables >= 1.4.5. -cat >$TMPDIR/ipttest.c <= 1.4.5. + cat >$TMPDIR/ipttest.c < #include static struct xtables_globals test_globals = { @@ -57,27 +58,27 @@ int main(int argc, char **argv) xtables_init_all(&test_globals, NFPROTO_IPV4); return 0; } - EOF -if $CC -I$INCLUDE $IPTC -o $TMPDIR/ipttest $TMPDIR/ipttest.c $IPTL $(${PKG_CONFIG} xtables --cflags --libs) -ldl >/dev/null 2>&1 -then + if $CC -I$INCLUDE $IPTC -o $TMPDIR/ipttest $TMPDIR/ipttest.c $IPTL \ + $(${PKG_CONFIG} xtables --cflags --libs) -ldl >/dev/null 2>&1 + then echo "TC_CONFIG_XT:=y" >>Config echo "using xtables" -fi -rm -f $TMPDIR/ipttest.c $TMPDIR/ipttest + fi + rm -f $TMPDIR/ipttest.c $TMPDIR/ipttest } check_xt_old() { -# bail if previous XT checks has already succeded. -if grep TC_CONFIG_XT Config > /dev/null -then + # bail if previous XT checks has already succeded. + if grep -q TC_CONFIG_XT Config + then return -fi + fi -#check if we dont need our internal header .. -cat >$TMPDIR/ipttest.c <$TMPDIR/ipttest.c < char *lib_dir; unsigned int global_option_offset = 0; @@ -97,26 +98,26 @@ int main(int argc, char **argv) { } EOF -$CC -I$INCLUDE $IPTC -o $TMPDIR/ipttest $TMPDIR/ipttest.c $IPTL -ldl >/dev/null 2>&1 -if [ $? -eq 0 ] -then + $CC -I$INCLUDE $IPTC -o $TMPDIR/ipttest $TMPDIR/ipttest.c $IPTL -ldl >/dev/null 2>&1 + if [ $? -eq 0 ] + then echo "TC_CONFIG_XT_OLD:=y" >>Config echo "using old xtables (no need for xt-internal.h)" -fi -rm -f $TMPDIR/ipttest.c $TMPDIR/ipttest + fi + rm -f $TMPDIR/ipttest.c $TMPDIR/ipttest } check_xt_old_internal_h() { -# bail if previous XT checks has already succeded. -if grep TC_CONFIG_XT Config > /dev/null -then + # bail if previous XT checks has already succeded. + if grep -q TC_CONFIG_XT Config + then return -fi + fi -#check if we need our own internal.h -cat >$TMPDIR/ipttest.c <$TMPDIR/ipttest.c < #include "xt-internal.h" char *lib_dir; @@ -137,14 +138,14 @@ int main(int argc, char **argv) { } EOF -$CC -I$INCLUDE $IPTC -o $TMPDIR/ipttest $TMPDIR/ipttest.c $IPTL -ldl >/dev/null 2>&1 + $CC -I$INCLUDE $IPTC -o $TMPDIR/ipttest $TMPDIR/ipttest.c $IPTL -ldl >/dev/null 2>&1 -if [ $? -eq 0 ] -then - echo "using old xtables with xt-internal.h" - echo "TC_CONFIG_XT_OLD_H:=y" >>Config -fi -rm -f $TMPDIR/ipttest.c $TMPDIR/ipttest + if [ $? -eq 0 ] + then + echo "using old xtables with xt-internal.h" + echo "TC_CONFIG_XT_OLD_H:=y" >>Config + fi + rm -f $TMPDIR/ipttest.c $TMPDIR/ipttest } check_ipt() @@ -179,7 +180,7 @@ check_ipt_lib_dir() check_setns() { -cat >$TMPDIR/setnstest.c <$TMPDIR/setnstest.c < int main(int argc, char **argv) { @@ -187,20 +188,20 @@ int main(int argc, char **argv) return 0; } EOF -$CC -I$INCLUDE -o $TMPDIR/setnstest $TMPDIR/setnstest.c >/dev/null 2>&1 -if [ $? -eq 0 ] -then + $CC -I$INCLUDE -o $TMPDIR/setnstest $TMPDIR/setnstest.c >/dev/null 2>&1 + if [ $? -eq 0 ] + then echo "IP_CONFIG_SETNS:=y" >>Config echo "yes" -else + else echo "no" -fi -rm -f $TMPDIR/setnstest.c $TMPDIR/setnstest + fi + rm -f $TMPDIR/setnstest.c $TMPDIR/setnstest } check_ipset() { -cat >$TMPDIR/ipsettest.c <$TMPDIR/ipsettest.c < #ifndef IP_SET_INVALID #define IPSET_DIM_MAX 3 @@ -219,14 +220,14 @@ int main(void) #endif EOF -if $CC -I$INCLUDE -o $TMPDIR/ipsettest $TMPDIR/ipsettest.c >/dev/null 2>&1 -then + if $CC -I$INCLUDE -o $TMPDIR/ipsettest $TMPDIR/ipsettest.c >/dev/null 2>&1 + then echo "TC_CONFIG_IPSET:=y" >>Config echo "yes" -else + else echo "no" -fi -rm -f $TMPDIR/ipsettest.c $TMPDIR/ipsettest + fi + rm -f $TMPDIR/ipsettest.c $TMPDIR/ipsettest } echo "# Generated config based on" $INCLUDE >Config From ae7b9a0d5c69ee21a8d01de228777109a071d8f7 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 19 Dec 2012 16:01:39 -0800 Subject: [PATCH 27/60] configure: restore old behaviour Previous change wasn't needed, since merge of configure: move toolchain init to a function --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 511b3439..da01c19b 100755 --- a/configure +++ b/configure @@ -12,6 +12,7 @@ check_toolchain() : ${PKG_CONFIG:=pkg-config} : ${AR=ar} : ${CC=gcc} + echo "PKG_CONFIG:=${PKG_CONFIG}" >>Config echo "AR:=${AR}" >>Config echo "CC:=${CC}" >>Config } @@ -231,7 +232,6 @@ EOF } echo "# Generated config based on" $INCLUDE >Config -echo "PKG_CONFIG:=${PKG_CONFIG}" >>Config check_toolchain echo "TC schedulers" From 75e003c23ed347592d650616f4ba971448ff44c4 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 20 Dec 2012 08:24:05 -0800 Subject: [PATCH 28/60] bridge: update kernel headers --- include/linux/if_bridge.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h index b3b6a67e..aac8b8c0 100644 --- a/include/linux/if_bridge.h +++ b/include/linux/if_bridge.h @@ -163,6 +163,9 @@ struct br_port_msg { struct br_mdb_entry { __u32 ifindex; +#define MDB_TEMPORARY 0 +#define MDB_PERMANENT 1 + __u8 state; struct { union { __be32 ip4; From d8b75d1ad22b3bc6e07b9547599baf9adc0d7cf4 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Thu, 20 Dec 2012 10:54:19 -0800 Subject: [PATCH 29/60] bridge: distinguish permanent and temporary mdb entries This patch adds a flag to mdb entries so that we can distinguish permanent entries with temporary ones. Signed-off-by: Cong Wang --- bridge/mdb.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/bridge/mdb.c b/bridge/mdb.c index 121ce9c2..6217c5ff 100644 --- a/bridge/mdb.c +++ b/bridge/mdb.c @@ -28,7 +28,7 @@ int filter_index; static void usage(void) { - fprintf(stderr, "Usage: bridge mdb { add | del } dev DEV port PORT grp GROUP\n"); + fprintf(stderr, "Usage: bridge mdb { add | del } dev DEV port PORT grp GROUP [permanent | temp]\n"); fprintf(stderr, " bridge mdb {show} [ dev DEV ]\n"); exit(-1); } @@ -53,13 +53,15 @@ static void print_mdb_entry(FILE *f, int ifindex, struct br_mdb_entry *e) SPRINT_BUF(abuf); if (e->addr.proto == htons(ETH_P_IP)) - fprintf(f, "bridge %s port %s group %s\n", ll_index_to_name(ifindex), + fprintf(f, "bridge %s port %s group %s %s\n", ll_index_to_name(ifindex), ll_index_to_name(e->ifindex), - inet_ntop(AF_INET, &e->addr.u.ip4, abuf, sizeof(abuf))); + inet_ntop(AF_INET, &e->addr.u.ip4, abuf, sizeof(abuf)), + (e->state & MDB_PERMANENT) ? "permanent" : "temp"); else - fprintf(f, "bridge %s port %s group %s\n", ll_index_to_name(ifindex), + fprintf(f, "bridge %s port %s group %s %s\n", ll_index_to_name(ifindex), ll_index_to_name(e->ifindex), - inet_ntop(AF_INET6, &e->addr.u.ip6, abuf, sizeof(abuf))); + inet_ntop(AF_INET6, &e->addr.u.ip6, abuf, sizeof(abuf)), + (e->state & MDB_PERMANENT) ? "permanent" : "temp"); } static void br_print_mdb_entry(FILE *f, int ifindex, struct rtattr *attr) @@ -179,11 +181,15 @@ static int mdb_modify(int cmd, int flags, int argc, char **argv) } else if (strcmp(*argv, "grp") == 0) { NEXT_ARG(); grp = *argv; + } else if (strcmp(*argv, "port") == 0) { + NEXT_ARG(); + p = *argv; + } else if (strcmp(*argv, "permanent") == 0) { + if (cmd == RTM_NEWMDB) + entry.state |= MDB_PERMANENT; + } else if (strcmp(*argv, "temp") == 0) { + ;/* nothing */ } else { - if (strcmp(*argv, "port") == 0) { - NEXT_ARG(); - p = *argv; - } if (matches(*argv, "help") == 0) usage(); } From 0ff8f578ed58c13de33a32016a6995e4c7d941a1 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Thu, 20 Dec 2012 22:31:55 +0800 Subject: [PATCH 30/60] bridge: make `bridge mdb` output consistent with input bridge -> dev group -> grp Signed-off-by: Cong Wang --- bridge/mdb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bridge/mdb.c b/bridge/mdb.c index 6217c5ff..81d479b9 100644 --- a/bridge/mdb.c +++ b/bridge/mdb.c @@ -53,12 +53,12 @@ static void print_mdb_entry(FILE *f, int ifindex, struct br_mdb_entry *e) SPRINT_BUF(abuf); if (e->addr.proto == htons(ETH_P_IP)) - fprintf(f, "bridge %s port %s group %s %s\n", ll_index_to_name(ifindex), + fprintf(f, "dev %s port %s grp %s %s\n", ll_index_to_name(ifindex), ll_index_to_name(e->ifindex), inet_ntop(AF_INET, &e->addr.u.ip4, abuf, sizeof(abuf)), (e->state & MDB_PERMANENT) ? "permanent" : "temp"); else - fprintf(f, "bridge %s port %s group %s %s\n", ll_index_to_name(ifindex), + fprintf(f, "dev %s port %s grp %s %s\n", ll_index_to_name(ifindex), ll_index_to_name(e->ifindex), inet_ntop(AF_INET6, &e->addr.u.ip6, abuf, sizeof(abuf)), (e->state & MDB_PERMANENT) ? "permanent" : "temp"); From e29d8cc6168e97677a5fff475c9871ddc7ae4e32 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Thu, 20 Dec 2012 22:31:54 +0800 Subject: [PATCH 31/60] bridge: update help Signed-off-by: Cong Wang --- bridge/bridge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bridge/bridge.c b/bridge/bridge.c index 1fcd365a..1d59a1e1 100644 --- a/bridge/bridge.c +++ b/bridge/bridge.c @@ -27,7 +27,7 @@ static void usage(void) { fprintf(stderr, "Usage: bridge [ OPTIONS ] OBJECT { COMMAND | help }\n" -"where OBJECT := { fdb | monitor }\n" +"where OBJECT := { fdb | mdb | monitor }\n" " OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails]\n" ); exit(-1); } From 5bd9dd49aecb66cae5e6d34197ab0487d946cc1d Mon Sep 17 00:00:00 2001 From: Strake Date: Sun, 23 Dec 2012 08:46:04 -0500 Subject: [PATCH 32/60] include needed files Needed to build iproute2 with musl --- include/libnetlink.h | 1 + include/utils.h | 1 + ip/ipaddress.c | 2 +- ip/ipntable.c | 1 + ip/ipprefix.c | 1 + lib/ipx_ntop.c | 1 + lib/ipx_pton.c | 1 + lib/utils.c | 2 ++ tc/m_ematch.h | 1 + 9 files changed, 10 insertions(+), 1 deletion(-) diff --git a/include/libnetlink.h b/include/libnetlink.h index 4a6b8789..41e6ed1a 100644 --- a/include/libnetlink.h +++ b/include/libnetlink.h @@ -1,6 +1,7 @@ #ifndef __LIBNETLINK_H__ #define __LIBNETLINK_H__ 1 +#include #include #include #include diff --git a/include/utils.h b/include/utils.h index 496db68e..2bd8c623 100644 --- a/include/utils.h +++ b/include/utils.h @@ -1,6 +1,7 @@ #ifndef __UTILS_H__ #define __UTILS_H__ 1 +#include #include #include #include diff --git a/ip/ipaddress.c b/ip/ipaddress.c index 5498f468..16f92d91 100644 --- a/ip/ipaddress.c +++ b/ip/ipaddress.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/ip/ipntable.c b/ip/ipntable.c index 639f512c..5751114e 100644 --- a/ip/ipntable.c +++ b/ip/ipntable.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include "utils.h" diff --git a/ip/ipprefix.c b/ip/ipprefix.c index d8327beb..ee276b3e 100644 --- a/ip/ipprefix.c +++ b/ip/ipprefix.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include "utils.h" diff --git a/lib/ipx_ntop.c b/lib/ipx_ntop.c index 7b6d728d..1e46bc21 100644 --- a/lib/ipx_ntop.c +++ b/lib/ipx_ntop.c @@ -1,5 +1,6 @@ #include #include +#include #include #include "utils.h" diff --git a/lib/ipx_pton.c b/lib/ipx_pton.c index 1a52b7f1..3dca2713 100644 --- a/lib/ipx_pton.c +++ b/lib/ipx_pton.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include "utils.h" diff --git a/lib/utils.c b/lib/utils.c index 7ecaab3c..5bcdbcfb 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -22,6 +23,7 @@ #include #include #include +#include #include #include #include diff --git a/tc/m_ematch.h b/tc/m_ematch.h index 5036e9b6..81456aac 100644 --- a/tc/m_ematch.h +++ b/tc/m_ematch.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "utils.h" #include "tc_util.h" From 5746307300eea81e9534698fd52163e737651c48 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 11 Jan 2013 06:56:28 +0000 Subject: [PATCH 33/60] add man7 to subdirs list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The man dir misses the man7 as a subdir which means none of the pages get installed. URL: https://bugs.gentoo.org/451166 Reported-by: Marcin Mirosław Signed-off-by: Mike Frysinger --- man/Makefile | 2 +- man/man7/Makefile | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 man/man7/Makefile diff --git a/man/Makefile b/man/Makefile index 67fea056..9a60fa7c 100644 --- a/man/Makefile +++ b/man/Makefile @@ -2,7 +2,7 @@ INSTALL=install INSTALLDIR=install -m 0755 -d INSTALLMAN=install -m 0644 -SUBDIRS = man3 man8 +SUBDIRS = man3 man7 man8 all: @for subdir in $(SUBDIRS); do $(MAKE) -C $$subdir; done diff --git a/man/man7/Makefile b/man/man7/Makefile new file mode 100644 index 00000000..ccfd8398 --- /dev/null +++ b/man/man7/Makefile @@ -0,0 +1,13 @@ +MAN7PAGES = tc-hfsc.7 + +all: + +distclean: clean + +clean: + +install: + $(INSTALLDIR) $(DESTDIR)$(MANDIR)/man7 + $(INSTALLMAN) $(MAN7PAGES) $(DESTDIR)$(MANDIR)/man7 + +.PHONY: install clean distclean From 55eaaeb57ac6c4ea3fca70715a64dc379ef32ed6 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 11 Jan 2013 06:56:29 +0000 Subject: [PATCH 34/60] do not ignore errors in man subdirs If an error occurs in a man subdir, make sure we propagate it back up. While we're here, merge the duplicate rules into one. Signed-off-by: Mike Frysinger --- man/Makefile | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/man/Makefile b/man/Makefile index 9a60fa7c..749faa11 100644 --- a/man/Makefile +++ b/man/Makefile @@ -4,17 +4,11 @@ INSTALLMAN=install -m 0644 SUBDIRS = man3 man7 man8 -all: - @for subdir in $(SUBDIRS); do $(MAKE) -C $$subdir; done +all clean install: + @for subdir in $(SUBDIRS); do $(MAKE) -C $$subdir $@ || exit $$?; done distclean: clean -clean: - @for subdir in $(SUBDIRS); do $(MAKE) -C $$subdir clean; done - -install: - @for subdir in $(SUBDIRS); do $(MAKE) -C $$subdir install; done - .PHONY: install clean distclean .EXPORT_ALL_VARIABLES: From 852d51222dda9b024b652752014175310f0d3340 Mon Sep 17 00:00:00 2001 From: Jamal Hadi Salim Date: Sun, 16 Dec 2012 10:41:39 +0000 Subject: [PATCH 35/60] iproute2: act_ipt fix xtables breakage Fixes breakage with xtables API starting with version 1.4.10 Signed-off-by: Hasan Chowdhury Signed-off-by: Jamal Hadi Salim --- tc/m_xt.c | 63 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 18 deletions(-) diff --git a/tc/m_xt.c b/tc/m_xt.c index bcc4d751..21dca000 100644 --- a/tc/m_xt.c +++ b/tc/m_xt.c @@ -118,6 +118,7 @@ static int parse_ipt(struct action_util *a,int *argc_p, struct xtables_target *m = NULL; struct ipt_entry fw; struct rtattr *tail; + int c; int rargc = *argc_p; char **argv = *argv_p; @@ -126,6 +127,7 @@ static int parse_ipt(struct action_util *a,int *argc_p, int size = 0; int iok = 0, ok = 0; __u32 hook = 0, index = 0; + struct option *opts = NULL; xtables_init_all(&tcipt_globals, NFPROTO_IPV4); set_lib_dir(); @@ -158,14 +160,22 @@ static int parse_ipt(struct action_util *a,int *argc_p, printf(" %s error \n", m->name); return -1; } - tcipt_globals.opts = - xtables_merge_options( #if (XTABLES_VERSION_CODE >= 6) - tcipt_globals.orig_opts, + opts = xtables_options_xfrm(tcipt_globals.orig_opts, + tcipt_globals.opts, + m->x6_options, + &m->option_offset); +#else + opts = xtables_merge_options(tcipt_globals.orig_opts, + tcipt_globals.opts, + m->extra_opts, + &m->option_offset); #endif - tcipt_globals.opts, - m->extra_opts, - &m->option_offset); + if (opts == NULL) { + fprintf(stderr, " failed to find aditional options for target %s\n\n", optarg); + return -1; + } else + tcipt_globals.opts = opts; } else { fprintf(stderr," failed to find target %s\n\n", optarg); return -1; @@ -175,17 +185,21 @@ static int parse_ipt(struct action_util *a,int *argc_p, default: memset(&fw, 0, sizeof (fw)); - if (m) { - m->parse(c - m->option_offset, argv, 0, - &m->tflags, NULL, &m->t); +#if (XTABLES_VERSION_CODE >= 6) + if (m != NULL && m->x6_parse != NULL ) { + xtables_option_tpcall(c, argv, 0 , m, NULL); +#else + if (m != NULL && m->parse != NULL ) { + m->parse(c - m->option_offset, argv, 0, &m->tflags, + NULL, &m->t); +#endif } else { - fprintf(stderr," failed to find target %s\n\n", optarg); + fprintf(stderr,"failed to find target %s\n\n", optarg); return -1; } ok++; break; - } } @@ -208,8 +222,13 @@ static int parse_ipt(struct action_util *a,int *argc_p, } /* check that we passed the correct parameters to the target */ +#if (XTABLES_VERSION_CODE >= 6) + if (m) + xtables_option_tfcall(m); +#else if (m && m->final_check) m->final_check(m->tflags); +#endif { struct tcmsg *t = NLMSG_DATA(n); @@ -271,6 +290,7 @@ print_ipt(struct action_util *au,FILE * f, struct rtattr *arg) { struct rtattr *tb[TCA_IPT_MAX + 1]; struct xt_entry_target *t = NULL; + struct option *opts = NULL; if (arg == NULL) return -1; @@ -309,14 +329,22 @@ print_ipt(struct action_util *au,FILE * f, struct rtattr *arg) return -1; } - tcipt_globals.opts = - xtables_merge_options( #if (XTABLES_VERSION_CODE >= 6) - tcipt_globals.orig_opts, + opts = xtables_options_xfrm(tcipt_globals.orig_opts, + tcipt_globals.opts, + m->x6_options, + &m->option_offset); +#else + opts = xtables_merge_options(tcipt_globals.orig_opts, + tcipt_globals.opts, + m->extra_opts, + &m->option_offset); #endif - tcipt_globals.opts, - m->extra_opts, - &m->option_offset); + if (opts == NULL) { + fprintf(stderr, " failed to find aditional options for target %s\n\n", optarg); + return -1; + } else + tcipt_globals.opts = opts; } else { fprintf(stderr, " failed to find target %s\n\n", t->u.user.name); @@ -355,4 +383,3 @@ struct action_util xt_action_util = { .parse_aopt = parse_ipt, .print_aopt = print_ipt, }; - From 048bff6e0206bca33ee70516521f3048e7714752 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Thu, 17 Jan 2013 18:00:50 +0000 Subject: [PATCH 36/60] ipxfrm: use alloca to allocate stack space Clang doesn't support the gcc extension for embeddeding flexible arrays inside of structures. Use the slightly more portable alloca(). Signed-off-by: Mike Frysinger --- ip/ipxfrm.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/ip/ipxfrm.c b/ip/ipxfrm.c index c7b34206..dda4a7a1 100644 --- a/ip/ipxfrm.c +++ b/ip/ipxfrm.c @@ -25,6 +25,7 @@ * Masahide NAKAMURA @USAGI */ +#include #include #include #include @@ -555,16 +556,13 @@ static inline void xfrm_algo_print(struct xfrm_algo *algo, int type, int len, static void xfrm_aead_print(struct xfrm_algo_aead *algo, int len, FILE *fp, const char *prefix) { - struct { - struct xfrm_algo algo; - char key[algo->alg_key_len / 8]; - } base; + struct xfrm_algo *base_algo = alloca(sizeof(*base_algo) + algo->alg_key_len / 8); - memcpy(base.algo.alg_name, algo->alg_name, sizeof(base.algo.alg_name)); - base.algo.alg_key_len = algo->alg_key_len; - memcpy(base.algo.alg_key, algo->alg_key, algo->alg_key_len / 8); + memcpy(base_algo->alg_name, algo->alg_name, sizeof(base_algo->alg_name)); + base_algo->alg_key_len = algo->alg_key_len; + memcpy(base_algo->alg_key, algo->alg_key, algo->alg_key_len / 8); - __xfrm_algo_print(&base.algo, XFRMA_ALG_AEAD, len, fp, prefix, 0); + __xfrm_algo_print(base_algo, XFRMA_ALG_AEAD, len, fp, prefix, 0); fprintf(fp, " %d", algo->alg_icv_len); @@ -574,16 +572,13 @@ static void xfrm_aead_print(struct xfrm_algo_aead *algo, int len, static void xfrm_auth_trunc_print(struct xfrm_algo_auth *algo, int len, FILE *fp, const char *prefix) { - struct { - struct xfrm_algo algo; - char key[algo->alg_key_len / 8]; - } base; + struct xfrm_algo *base_algo = alloca(sizeof(*base_algo) + algo->alg_key_len / 8); - memcpy(base.algo.alg_name, algo->alg_name, sizeof(base.algo.alg_name)); - base.algo.alg_key_len = algo->alg_key_len; - memcpy(base.algo.alg_key, algo->alg_key, algo->alg_key_len / 8); + memcpy(base_algo->alg_name, algo->alg_name, sizeof(base_algo->alg_name)); + base_algo->alg_key_len = algo->alg_key_len; + memcpy(base_algo->alg_key, algo->alg_key, algo->alg_key_len / 8); - __xfrm_algo_print(&base.algo, XFRMA_ALG_AUTH_TRUNC, len, fp, prefix, 0); + __xfrm_algo_print(base_algo, XFRMA_ALG_AUTH_TRUNC, len, fp, prefix, 0); fprintf(fp, " %d", algo->alg_trunc_len); From 003f76f0263cca5aeb27939f9d79525c86fad0c5 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 18 Jan 2013 09:54:58 -0800 Subject: [PATCH 37/60] README: update mail address and download location --- README | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README b/README index 99d1aeb4..c7a5118d 100644 --- a/README +++ b/README @@ -4,7 +4,7 @@ Information: http://www.linuxfoundation.org/collaborate/workgroups/networking/iproute2 Download: - http://devresources.linuxfoundation.org/dev/iproute2/download + http://www.kernel.org/pub/linux/utils/net/iproute2/ Repository: git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git @@ -37,7 +37,7 @@ contains whether or not ATM is available, etc. kernel include files. Stephen Hemminger -shemminger@linux-foundation.org +stephen@networkplumber.org Alexey Kuznetsov kuznet@ms2.inr.ac.ru From 144e6ce1679a768e987230efb4afa402a5ab58ac Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 17 Jan 2013 14:45:33 +0000 Subject: [PATCH 38/60] iproute2: Don't propogate mounts out of ip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some systems are now following the advice in linux/Documentation/sharedsubtrees.txt and running with all mount points shared between all mount namespaces by default. After creating the mount namespace call mount on / with MS_SLAVE|MS_REC to modify all mounts in the new mount namespace to slave mounts if they are shared or private mounts otherwise. Guarnateeing that changes to the mount namespace created with "ip netns exec" don't propgate to other namespaces. Reported-by: Petr Šabata Tested-by: Petr Šabata Signed-off-by: "Eric W. Biederman" --- ip/ipnetns.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ip/ipnetns.c b/ip/ipnetns.c index e41a598a..f2c42ba4 100644 --- a/ip/ipnetns.c +++ b/ip/ipnetns.c @@ -152,6 +152,12 @@ static int netns_exec(int argc, char **argv) fprintf(stderr, "unshare failed: %s\n", strerror(errno)); return -1; } + /* Don't let any mounts propogate back to the parent */ + if (mount("", "/", "none", MS_SLAVE | MS_REC, NULL)) { + fprintf(stderr, "mount --make-rslave / failed: %s\n", + strerror(errno)); + return -1; + } /* Mount a version of /sys that describes the network namespace */ if (umount2("/sys", MNT_DETACH) < 0) { fprintf(stderr, "umount of /sys failed: %s\n", strerror(errno)); From 8e2d47dce288d5a60d8c67f537860a3683d36df6 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 17 Jan 2013 14:46:09 +0000 Subject: [PATCH 39/60] iproute2: Normalize return codes in "ip netns" Ben Hutchings pointed out that the return value of do_netns is passed to exit and the current convention of returning -1 for failure is inconsitent with that reality. Return EXIT_FAILURE instead of -1 and EXIT_SUCCESS instead of 0. To make it clear that the return codes are expected to be passed to exit. Signed-off-by: "Eric W. Biederman" --- ip/ipnetns.c | 56 ++++++++++++++++++++++++---------------------------- 1 file changed, 26 insertions(+), 30 deletions(-) diff --git a/ip/ipnetns.c b/ip/ipnetns.c index f2c42ba4..ae550902 100644 --- a/ip/ipnetns.c +++ b/ip/ipnetns.c @@ -40,17 +40,14 @@ static int setns(int fd, int nstype) } #endif /* HAVE_SETNS */ - -static void usage(void) __attribute__((noreturn)); - -static void usage(void) +static int usage(void) { fprintf(stderr, "Usage: ip netns list\n"); fprintf(stderr, " ip netns add NAME\n"); fprintf(stderr, " ip netns delete NAME\n"); fprintf(stderr, " ip netns exec NAME cmd ...\n"); fprintf(stderr, " ip netns monitor\n"); - exit(-1); + return EXIT_FAILURE; } int get_netns_fd(const char *name) @@ -75,7 +72,7 @@ static int netns_list(int argc, char **argv) dir = opendir(NETNS_RUN_DIR); if (!dir) - return 0; + return EXIT_SUCCESS; while ((entry = readdir(dir)) != NULL) { if (strcmp(entry->d_name, ".") == 0) @@ -85,7 +82,7 @@ static int netns_list(int argc, char **argv) printf("%s\n", entry->d_name); } closedir(dir); - return 0; + return EXIT_SUCCESS; } static void bind_etc(const char *name) @@ -127,11 +124,11 @@ static int netns_exec(int argc, char **argv) if (argc < 1) { fprintf(stderr, "No netns name specified\n"); - return -1; + return EXIT_FAILURE; } if (argc < 2) { fprintf(stderr, "No cmd specified\n"); - return -1; + return EXIT_FAILURE; } name = argv[0]; cmd = argv[1]; @@ -140,32 +137,32 @@ static int netns_exec(int argc, char **argv) if (netns < 0) { fprintf(stderr, "Cannot open network namespace: %s\n", strerror(errno)); - return -1; + return EXIT_FAILURE; } if (setns(netns, CLONE_NEWNET) < 0) { fprintf(stderr, "seting the network namespace failed: %s\n", strerror(errno)); - return -1; + return EXIT_FAILURE; } if (unshare(CLONE_NEWNS) < 0) { fprintf(stderr, "unshare failed: %s\n", strerror(errno)); - return -1; + return EXIT_FAILURE; } /* Don't let any mounts propogate back to the parent */ if (mount("", "/", "none", MS_SLAVE | MS_REC, NULL)) { fprintf(stderr, "mount --make-rslave / failed: %s\n", strerror(errno)); - return -1; + return EXIT_FAILURE; } /* Mount a version of /sys that describes the network namespace */ if (umount2("/sys", MNT_DETACH) < 0) { fprintf(stderr, "umount of /sys failed: %s\n", strerror(errno)); - return -1; + return EXIT_FAILURE; } if (mount(name, "/sys", "sysfs", 0, NULL) < 0) { fprintf(stderr, "mount of /sys failed: %s\n",strerror(errno)); - return -1; + return EXIT_FAILURE; } /* Setup bind mounts for config files in /etc */ @@ -174,7 +171,7 @@ static int netns_exec(int argc, char **argv) if (execvp(cmd, argv + 1) < 0) fprintf(stderr, "exec of %s failed: %s\n", cmd, strerror(errno)); - exit(-1); + return EXIT_FAILURE; } static int netns_delete(int argc, char **argv) @@ -184,7 +181,7 @@ static int netns_delete(int argc, char **argv) if (argc < 1) { fprintf(stderr, "No netns name specified\n"); - return -1; + return EXIT_FAILURE; } name = argv[0]; @@ -193,9 +190,9 @@ static int netns_delete(int argc, char **argv) if (unlink(netns_path) < 0) { fprintf(stderr, "Cannot remove %s: %s\n", netns_path, strerror(errno)); - return -1; + return EXIT_FAILURE; } - return 0; + return EXIT_SUCCESS; } static int netns_add(int argc, char **argv) @@ -214,7 +211,7 @@ static int netns_add(int argc, char **argv) if (argc < 1) { fprintf(stderr, "No netns name specified\n"); - return -1; + return EXIT_FAILURE; } name = argv[0]; @@ -228,7 +225,7 @@ static int netns_add(int argc, char **argv) if (fd < 0) { fprintf(stderr, "Could not create %s: %s\n", netns_path, strerror(errno)); - return -1; + return EXIT_FAILURE; } close(fd); if (unshare(CLONE_NEWNET) < 0) { @@ -243,11 +240,10 @@ static int netns_add(int argc, char **argv) netns_path, strerror(errno)); goto out_delete; } - return 0; + return EXIT_SUCCESS; out_delete: netns_delete(argc, argv); - exit(-1); - return -1; + return EXIT_FAILURE; } @@ -260,19 +256,19 @@ static int netns_monitor(int argc, char **argv) if (fd < 0) { fprintf(stderr, "inotify_init failed: %s\n", strerror(errno)); - return -1; + return EXIT_FAILURE; } if (inotify_add_watch(fd, NETNS_RUN_DIR, IN_CREATE | IN_DELETE) < 0) { fprintf(stderr, "inotify_add_watch failed: %s\n", strerror(errno)); - return -1; + return EXIT_FAILURE; } for(;;) { ssize_t len = read(fd, buf, sizeof(buf)); if (len < 0) { fprintf(stderr, "read failed: %s\n", strerror(errno)); - return -1; + return EXIT_FAILURE; } for (event = (struct inotify_event *)buf; (char *)event < &buf[len]; @@ -283,7 +279,7 @@ static int netns_monitor(int argc, char **argv) printf("delete %s\n", event->name); } } - return 0; + return EXIT_SUCCESS; } int do_netns(int argc, char **argv) @@ -296,7 +292,7 @@ int do_netns(int argc, char **argv) return netns_list(argc-1, argv+1); if (matches(*argv, "help") == 0) - usage(); + return usage(); if (matches(*argv, "add") == 0) return netns_add(argc-1, argv+1); @@ -311,5 +307,5 @@ int do_netns(int argc, char **argv) return netns_monitor(argc-1, argv+1); fprintf(stderr, "Command \"%s\" is unknown, try \"ip netns help\".\n", *argv); - exit(-1); + return EXIT_FAILURE; } From 4395d48c78a77a99c5a8618403211032356fe552 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 17 Jan 2013 14:46:43 +0000 Subject: [PATCH 40/60] iproute2: Improve "ip netns add" failure error message Report the name of the network namespace that could not be added. Signed-off-by: "Eric W. Biederman" --- ip/ipnetns.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ip/ipnetns.c b/ip/ipnetns.c index ae550902..4fce379a 100644 --- a/ip/ipnetns.c +++ b/ip/ipnetns.c @@ -135,8 +135,8 @@ static int netns_exec(int argc, char **argv) snprintf(net_path, sizeof(net_path), "%s/%s", NETNS_RUN_DIR, name); netns = open(net_path, O_RDONLY); if (netns < 0) { - fprintf(stderr, "Cannot open network namespace: %s\n", - strerror(errno)); + fprintf(stderr, "Cannot open network namespace %s: %s\n", + name, strerror(errno)); return EXIT_FAILURE; } if (setns(netns, CLONE_NEWNET) < 0) { From 58a3e8270fe72f8ed92687d3a3132c2a708582dd Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 17 Jan 2013 14:47:18 +0000 Subject: [PATCH 41/60] iproute2: Make "ip netns delete" more likely to succeed Sometimes "ip netns delete" fails because it can not delete the file a network namespace was mounted on. If this only happened when a network namespace was really in use this would be fine, but today it is possible to pin all network namespaces by simply having a long running process started with "ip netns exec". Every mount is copied when a network namespace is created so it is impossible to prevent the mounts from getting into other mount namespaces. Modify all mounts in the files and subdirectories of /var/run/netns to be shared mount points so that unmount events can propogate, making it unlikely that "ip netns delete" will fail because a directory is mounted in another mount namespace. Signed-off-by: "Eric W. Biederman" --- ip/ipnetns.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/ip/ipnetns.c b/ip/ipnetns.c index 4fce379a..33765b58 100644 --- a/ip/ipnetns.c +++ b/ip/ipnetns.c @@ -208,6 +208,7 @@ static int netns_add(int argc, char **argv) char netns_path[MAXPATHLEN]; const char *name; int fd; + int made_netns_run_dir_mount = 0; if (argc < 1) { fprintf(stderr, "No netns name specified\n"); @@ -220,6 +221,29 @@ static int netns_add(int argc, char **argv) /* Create the base netns directory if it doesn't exist */ mkdir(NETNS_RUN_DIR, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); + /* Make it possible for network namespace mounts to propogate between + * mount namespaces. This makes it likely that a unmounting a network + * namespace file in one namespace will unmount the network namespace + * file in all namespaces allowing the network namespace to be freed + * sooner. + */ + while (mount("", NETNS_RUN_DIR, "none", MS_SHARED | MS_REC, NULL)) { + /* Fail unless we need to make the mount point */ + if (errno != EINVAL || made_netns_run_dir_mount) { + fprintf(stderr, "mount --make-shared %s failed: %s\n", + NETNS_RUN_DIR, strerror(errno)); + return EXIT_FAILURE; + } + + /* Upgrade NETNS_RUN_DIR to a mount point */ + if (mount(NETNS_RUN_DIR, NETNS_RUN_DIR, "none", MS_BIND, NULL)) { + fprintf(stderr, "mount --bind %s %s failed: %s\n", + NETNS_RUN_DIR, NETNS_RUN_DIR, strerror(errno)); + return EXIT_FAILURE; + } + made_netns_run_dir_mount = 1; + } + /* Create the filesystem state */ fd = open(netns_path, O_RDONLY|O_CREAT|O_EXCL, 0); if (fd < 0) { From 1e9014a7a684dbb3d54f5e061dbbb77cf115efe2 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 17 Jan 2013 14:47:47 +0000 Subject: [PATCH 42/60] iproute2: Fill in the ip-netns.8 manpage Document ip netns monitor. Add a few senteces describing each command. The manpage was looking very scrawny. Signed-off-by: "Eric W. Biederman" --- man/man8/ip-netns.8 | 46 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/man/man8/ip-netns.8 b/man/man8/ip-netns.8 index 349ee7e6..ff08232a 100644 --- a/man/man8/ip-netns.8 +++ b/man/man8/ip-netns.8 @@ -1,4 +1,4 @@ -.TH IP\-NETNS 8 "20 Dec 2011" "iproute2" "Linux" +.TH IP\-NETNS 8 "16 Jan 2013" "iproute2" "Linux" .SH NAME ip-netns \- process network namespace management .SH SYNOPSIS @@ -23,6 +23,9 @@ ip-netns \- process network namespace management .BR "ip netns exec " .I NETNSNAME command ... +.ti -8 +.BR "ip netns monitor" + .SH DESCRIPTION A network namespace is logically another copy of the network stack, with its own routes, firewall rules, and network devices. @@ -54,11 +57,52 @@ bind mounting all of the per network namespace configure files into their traditional location in /etc. .SS ip netns list - show all of the named network namespaces + +This command displays all of the network namespaces in /var/run/netns + .SS ip netns add NAME - create a new named network namespace + +If NAME is available in /var/run/netns/ this command creates a new +network namespace and assigns NAME. + .SS ip netns delete NAME - delete the name of a network namespace + +If NAME is present in /var/run/netns it is umounted and the mount +point is removed. If this is the last user of the network namespace the +network namespace will be freed, otherwise the network namespace +persists until it has no more users. ip netns delete may fail if +the mount point is in use in another mount namespace. + .SS ip netns exec NAME cmd ... - Run cmd in the named network namespace +This command allows applications that are network namespace unaware +to be run in something other than the default network namespace with +all of the configuration for the specified network namespace appearing +in the customary global locations. A network namespace and bind mounts +are used to move files from their network namespace specific location +to their default locations without affecting other processes. + +.SS ip netns monitor - Report as network namespace names are added and deleted + +This command watches network namespace name addition and deletion events +and prints a line for each event it sees. + .SH EXAMPLES +.PP +ip netns list +.RS +Shows the list of current named network namespaces +.RE +.PP +ip netns add vpn +.RS +Creates a network namespace and names it vpn +.RE +.PP +ip netns exec vpn ip link set lo up +.RS +Bring up the loopback interface in the vpn network namespace. +.RE .SH SEE ALSO .br From 9a7b3d91b69ea9c3c128d973c4bda2324da1a795 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 17 Jan 2013 14:48:15 +0000 Subject: [PATCH 43/60] iproute2: Add "ip netns pids" and "ip netns identify" Add command that go between network namespace names and process identifiers. The code builds and runs agains older kernels but only works on Linux 3.8+ kernels where I have fixed stat to work properly. Signed-off-by: "Eric W. Biederman" --- ip/ipnetns.c | 148 ++++++++++++++++++++++++++++++++++++++++++++ man/man8/ip-netns.8 | 18 ++++++ 2 files changed, 166 insertions(+) diff --git a/ip/ipnetns.c b/ip/ipnetns.c index 33765b58..51b1c5e7 100644 --- a/ip/ipnetns.c +++ b/ip/ipnetns.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "utils.h" #include "ip_common.h" @@ -45,6 +46,8 @@ static int usage(void) fprintf(stderr, "Usage: ip netns list\n"); fprintf(stderr, " ip netns add NAME\n"); fprintf(stderr, " ip netns delete NAME\n"); + fprintf(stderr, " ip netns identify PID\n"); + fprintf(stderr, " ip netns pids NAME\n"); fprintf(stderr, " ip netns exec NAME cmd ...\n"); fprintf(stderr, " ip netns monitor\n"); return EXIT_FAILURE; @@ -174,6 +177,145 @@ static int netns_exec(int argc, char **argv) return EXIT_FAILURE; } +static int is_pid(const char *str) +{ + int ch; + for (; (ch = *str); str++) { + if (!isdigit(ch)) + return 0; + } + return 1; +} + +static int netns_pids(int argc, char **argv) +{ + const char *name; + char net_path[MAXPATHLEN]; + int netns; + struct stat netst; + DIR *dir; + struct dirent *entry; + + if (argc < 1) { + fprintf(stderr, "No netns name specified\n"); + return EXIT_FAILURE; + } + if (argc > 1) { + fprintf(stderr, "extra arguments specified\n"); + return EXIT_FAILURE; + } + + name = argv[0]; + snprintf(net_path, sizeof(net_path), "%s/%s", NETNS_RUN_DIR, name); + netns = open(net_path, O_RDONLY); + if (netns < 0) { + fprintf(stderr, "Cannot open network namespace: %s\n", + strerror(errno)); + return EXIT_FAILURE; + } + if (fstat(netns, &netst) < 0) { + fprintf(stderr, "Stat of netns failed: %s\n", + strerror(errno)); + return EXIT_FAILURE; + } + dir = opendir("/proc/"); + if (!dir) { + fprintf(stderr, "Open of /proc failed: %s\n", + strerror(errno)); + return EXIT_FAILURE; + } + while((entry = readdir(dir))) { + char pid_net_path[MAXPATHLEN]; + struct stat st; + if (!is_pid(entry->d_name)) + continue; + snprintf(pid_net_path, sizeof(pid_net_path), "/proc/%s/ns/net", + entry->d_name); + if (stat(pid_net_path, &st) != 0) + continue; + if ((st.st_dev == netst.st_dev) && + (st.st_ino == netst.st_ino)) { + printf("%s\n", entry->d_name); + } + } + closedir(dir); + return EXIT_SUCCESS; + +} + +static int netns_identify(int argc, char **argv) +{ + const char *pidstr; + char net_path[MAXPATHLEN]; + int netns; + struct stat netst; + DIR *dir; + struct dirent *entry; + + if (argc < 1) { + fprintf(stderr, "No pid specified\n"); + return EXIT_FAILURE; + } + if (argc > 1) { + fprintf(stderr, "extra arguments specified\n"); + return EXIT_FAILURE; + } + pidstr = argv[0]; + + if (!is_pid(pidstr)) { + fprintf(stderr, "Specified string '%s' is not a pid\n", + pidstr); + return EXIT_FAILURE; + } + + snprintf(net_path, sizeof(net_path), "/proc/%s/ns/net", pidstr); + netns = open(net_path, O_RDONLY); + if (netns < 0) { + fprintf(stderr, "Cannot open network namespace: %s\n", + strerror(errno)); + return EXIT_FAILURE; + } + if (fstat(netns, &netst) < 0) { + fprintf(stderr, "Stat of netns failed: %s\n", + strerror(errno)); + return EXIT_FAILURE; + } + dir = opendir(NETNS_RUN_DIR); + if (!dir) { + /* Succeed treat a missing directory as an empty directory */ + if (errno == ENOENT) + return EXIT_SUCCESS; + + fprintf(stderr, "Failed to open directory %s:%s\n", + NETNS_RUN_DIR, strerror(errno)); + return EXIT_FAILURE; + } + + while((entry = readdir(dir))) { + char name_path[MAXPATHLEN]; + struct stat st; + + if (strcmp(entry->d_name, ".") == 0) + continue; + if (strcmp(entry->d_name, "..") == 0) + continue; + + snprintf(name_path, sizeof(name_path), "%s/%s", NETNS_RUN_DIR, + entry->d_name); + + if (stat(name_path, &st) != 0) + continue; + + if ((st.st_dev == netst.st_dev) && + (st.st_ino == netst.st_ino)) { + printf("%s\n", entry->d_name); + } + } + closedir(dir); + return EXIT_SUCCESS; + +} + static int netns_delete(int argc, char **argv) { const char *name; @@ -324,6 +466,12 @@ int do_netns(int argc, char **argv) if (matches(*argv, "delete") == 0) return netns_delete(argc-1, argv+1); + if (matches(*argv, "identify") == 0) + return netns_identify(argc-1, argv+1); + + if (matches(*argv, "pids") == 0) + return netns_pids(argc-1, argv+1); + if (matches(*argv, "exec") == 0) return netns_exec(argc-1, argv+1); diff --git a/man/man8/ip-netns.8 b/man/man8/ip-netns.8 index ff08232a..d06ccef1 100644 --- a/man/man8/ip-netns.8 +++ b/man/man8/ip-netns.8 @@ -19,6 +19,14 @@ ip-netns \- process network namespace management .BR "ip netns" " { " add " | " delete " } " .I NETNSNAME +.ti -8 +.BR "ip netns identify" +.I PID + +.ti -8 +.BR "ip netns pids" +.I NETNSNAME + .ti -8 .BR "ip netns exec " .I NETNSNAME command ... @@ -73,6 +81,16 @@ network namespace will be freed, otherwise the network namespace persists until it has no more users. ip netns delete may fail if the mount point is in use in another mount namespace. +.SS ip netns identify PID - Report network namespaces names for process + +This command walks through /var/run/netns and finds all the network +namespace names for network namespace of the specified process. + +.SS ip netns pids NAME - Report processes in the named network namespace + +This command walks through proc and finds all of the process who have +the named network namespace as their primary network namespace. + .SS ip netns exec NAME cmd ... - Run cmd in the named network namespace This command allows applications that are network namespace unaware From 5a650703d47e10aa386406c855eff5a593b2120b Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 4 Feb 2013 08:51:44 -0800 Subject: [PATCH 44/60] Makefile: make warnings into errors Don't let contributions cause warnings. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 46a5ad9b..6ba36e8d 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,7 @@ CC = gcc HOSTCC = gcc DEFINES += -D_GNU_SOURCE CCOPTS = -O2 -WFLAGS = -Wall -Wstrict-prototypes +WFLAGS = -Wall -Wstrict-prototypes -Werror CFLAGS = $(WFLAGS) $(CCOPTS) -I../include $(DEFINES) YACCFLAGS = -d -t -v From 53403c53af6c7cbc9c3f54b5170fdd0cf367b70a Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 4 Feb 2013 08:54:17 -0800 Subject: [PATCH 45/60] libnetlink: add caveat There are much better API's to netlink now. Encourage users to look elsewhere. --- man/man3/libnetlink.3 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/man/man3/libnetlink.3 b/man/man3/libnetlink.3 index 15a478a7..d114169a 100644 --- a/man/man3/libnetlink.3 +++ b/man/man3/libnetlink.3 @@ -183,6 +183,8 @@ Initialize the rtnetlink attribute with a variable length data value. .SH BUGS +This library is meant for internal use, use libmnl for new programs. + The functions sometimes use fprintf and exit when a fatal error occurs. This library should be named librtnetlink. From e59fd3db2ea86b94fb0e5fc277e5b10f09bc2336 Mon Sep 17 00:00:00 2001 From: David Ward Date: Sun, 27 Jan 2013 13:04:59 +0000 Subject: [PATCH 46/60] ip/iptunnel: Extend TOS syntax The 'inherit/STRING' or 'inherit/00..ff' syntax indicates that the TOS field of tunneled packets should be copied from the original IP header, but for non-IP packets the value STRING or 00..ff should be used instead. (This syntax is already used by 'ip tunnel show'.) Also clarify the man page and the command usage text (particularly that the TOS is not specified as a decimal number). Signed-off-by: David Ward --- ip/iptunnel.c | 15 +++++++++++---- man/man8/ip-tunnel.8 | 34 +++++++++++++++++++++------------- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/ip/iptunnel.c b/ip/iptunnel.c index 0cf6cf8e..f8b91ba0 100644 --- a/ip/iptunnel.c +++ b/ip/iptunnel.c @@ -41,7 +41,7 @@ static void usage(void) fprintf(stderr, "\n"); fprintf(stderr, "Where: NAME := STRING\n"); fprintf(stderr, " ADDR := { IP_ADDRESS | any }\n"); - fprintf(stderr, " TOS := { NUMBER | inherit }\n"); + fprintf(stderr, " TOS := { STRING | 00..ff | inherit | inherit/STRING | inherit/00..ff }\n"); fprintf(stderr, " TTL := { 1..255 | inherit }\n"); fprintf(stderr, " KEY := { DOTTED_QUAD | NUMBER }\n"); exit(-1); @@ -188,14 +188,21 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p) } else if (strcmp(*argv, "tos") == 0 || strcmp(*argv, "tclass") == 0 || matches(*argv, "dsfield") == 0) { + char *dsfield; __u32 uval; NEXT_ARG(); + dsfield = *argv; + strsep(&dsfield, "/"); if (strcmp(*argv, "inherit") != 0) { - if (rtnl_dsfield_a2n(&uval, *argv)) - invarg("bad TOS value", *argv); - p->iph.tos = uval; + dsfield = *argv; + p->iph.tos = 0; } else p->iph.tos = 1; + if (dsfield) { + if (rtnl_dsfield_a2n(&uval, dsfield)) + invarg("bad TOS value", *argv); + p->iph.tos |= uval; + } } else { if (strcmp(*argv, "name") == 0) { NEXT_ARG(); diff --git a/man/man8/ip-tunnel.8 b/man/man8/ip-tunnel.8 index 37ba542c..b408517c 100644 --- a/man/man8/ip-tunnel.8 +++ b/man/man8/ip-tunnel.8 @@ -47,7 +47,6 @@ ip-tunnel - tunnel configuration .RB "[ [" no "]" pmtudisc " ]" .RB "[ " dev .IR PHYS_DEV " ]" -.RB "[ " "dscp inherit" " ]" .ti -8 .IR MODE " := " @@ -58,8 +57,12 @@ ip-tunnel - tunnel configuration .BR any " }" .ti -8 -.IR TOS " := { " NUMBER " |" -.BR inherit " }" +.IR TOS " := { " STRING " | " 00 ".." ff " |" +.BR inherit " |" +.BI "inherit/" STRING +.R " |" +.BI "inherit/" 00 ".." ff +.R " }" .ti -8 .IR ELIM " := {" @@ -132,11 +135,21 @@ The default value for IPv6 tunnels is: .BI dsfield " T" .TP .BI tclass " T" -set a fixed TOS (or traffic class in IPv6) -.I T -on tunneled packets. -The default value is: -.BR "inherit" . +set the type of service (IPv4) or traffic class (IPv6) field on +tunneled packets, which can be specified as either a two-digit +hex value (e.g. c0) or a predefined string (e.g. internet). +The value +.B inherit +causes the field to be copied from the original IP header. The +values +.BI "inherit/" STRING +or +.BI "inherit/" 00 ".." ff +will set the field to +.I STRING +or +.IR 00 ".." ff +when tunneling non-IP packets. The default value is 00. .TP .BI dev " NAME" @@ -201,11 +214,6 @@ flag is equivalent to the combination .BR "iseq oseq" . .B It isn't work. Don't use it. -.TP -.BR "dscp inherit" -.RB ( " only IPv6 tunnels " ) -Inherit DS field between inner and outer header. - .TP .BI encaplim " ELIM" .RB ( " only IPv6 tunnels " ) From d36035185ce948f6bf85978b6903cce1293061d7 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Tue, 29 Jan 2013 08:46:42 -0800 Subject: [PATCH 47/60] ipaddr: fix a typo in error msg about SIOCGIFTXQLEN The optname was wrong. Signed-off-by: Nicolas Dichtel --- ip/ipaddress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ip/ipaddress.c b/ip/ipaddress.c index 16f92d91..2eb1a0a6 100644 --- a/ip/ipaddress.c +++ b/ip/ipaddress.c @@ -163,7 +163,7 @@ static void print_queuelen(FILE *f, struct rtattr *tb[IFLA_MAX + 1]) memset(&ifr, 0, sizeof(ifr)); strcpy(ifr.ifr_name, rta_getattr_str(tb[IFLA_IFNAME])); if (ioctl(s, SIOCGIFTXQLEN, &ifr) < 0) { - fprintf(f, "ioctl(SIOCGIFXQLEN) failed: %s\n", strerror(errno)); + fprintf(f, "ioctl(SIOCGIFTXQLEN) failed: %s\n", strerror(errno)); close(s); return; } From e72ca3fbb0aeaa382e6a5a14dada38a56ffab160 Mon Sep 17 00:00:00 2001 From: Johannes Naab Date: Wed, 23 Jan 2013 11:38:19 +0000 Subject: [PATCH 48/60] iproute2: tc netem rate: allow negative packet/cell overhead by fixing the parsing of command-line tokens Signed-off-by: Johannes Naab --- tc/q_netem.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tc/q_netem.c b/tc/q_netem.c index f8489e9a..2583072a 100644 --- a/tc/q_netem.c +++ b/tc/q_netem.c @@ -147,6 +147,8 @@ static int get_distribution(const char *type, __s16 *data, int maxdata) } #define NEXT_IS_NUMBER() (NEXT_ARG_OK() && isdigit(argv[1][0])) +#define NEXT_IS_SIGNED_NUMBER() \ + (NEXT_ARG_OK() && (isdigit(argv[1][0]) || argv[1][0] == '-')) /* Adjust for the fact that psched_ticks aren't always usecs (based on kernel PSCHED_CLOCK configuration */ @@ -393,7 +395,7 @@ static int netem_parse_opt(struct qdisc_util *qu, int argc, char **argv, explain1("rate"); return -1; } - if (NEXT_IS_NUMBER()) { + if (NEXT_IS_SIGNED_NUMBER()) { NEXT_ARG(); if (get_s32(&rate.packet_overhead, *argv, 0)) { explain1("rate"); @@ -407,7 +409,7 @@ static int netem_parse_opt(struct qdisc_util *qu, int argc, char **argv, return -1; } } - if (NEXT_IS_NUMBER()) { + if (NEXT_IS_SIGNED_NUMBER()) { NEXT_ARG(); if (get_s32(&rate.cell_overhead, *argv, 0)) { explain1("rate"); From ede6a3eaf53aed3671a4236d3006de0693ab6246 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Tue, 5 Feb 2013 00:38:34 -0800 Subject: [PATCH 49/60] iplink: display the value of IFLA_PROMISCUITY This is useful to know the 'real' status of an interface (the flag IFF_PROMISC is exported by the kernel only when the user set it explicitly, for example it will not be exported when a tcpdump is running). This information will be displayed when '-details' is provided by the user. Example: $ ip -d l l tun10 6: tun10: mtu 1480 qdisc noqueue state UNKNOWN mode DEFAULT link/sit 10.16.0.249 peer 10.16.0.121 sit remote 10.16.0.121 local 10.16.0.249 ttl inherit pmtudisc 6rd-prefix 2002::/16 promiscuity 2 Signed-off-by: Nicolas Dichtel --- ip/ipaddress.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ip/ipaddress.c b/ip/ipaddress.c index 2eb1a0a6..e8cab409 100644 --- a/ip/ipaddress.c +++ b/ip/ipaddress.c @@ -464,6 +464,10 @@ int print_linkinfo(const struct sockaddr_nl *who, if (do_link && tb[IFLA_LINKINFO] && show_details) print_linktype(fp, tb[IFLA_LINKINFO]); + if (do_link && tb[IFLA_PROMISCUITY] && show_details) + fprintf(fp, "\n promiscuity %u ", + *(int*)RTA_DATA(tb[IFLA_PROMISCUITY])); + if (do_link && tb[IFLA_IFALIAS]) fprintf(fp,"\n alias %s", rta_getattr_str(tb[IFLA_IFALIAS])); From 1cb6a110d676cb261bedf2ba0103209fcbbc4367 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 5 Feb 2013 08:16:28 -0800 Subject: [PATCH 50/60] ip: change format of promiscuity display Don't put it on separate line, keep it on line with link address. --- ip/ipaddress.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ip/ipaddress.c b/ip/ipaddress.c index e8cab409..297506d4 100644 --- a/ip/ipaddress.c +++ b/ip/ipaddress.c @@ -461,13 +461,13 @@ int print_linkinfo(const struct sockaddr_nl *who, } } + if (do_link && tb[IFLA_PROMISCUITY] && show_details) + fprintf(fp, " promiscuity %u ", + *(int*)RTA_DATA(tb[IFLA_PROMISCUITY])); + if (do_link && tb[IFLA_LINKINFO] && show_details) print_linktype(fp, tb[IFLA_LINKINFO]); - if (do_link && tb[IFLA_PROMISCUITY] && show_details) - fprintf(fp, "\n promiscuity %u ", - *(int*)RTA_DATA(tb[IFLA_PROMISCUITY])); - if (do_link && tb[IFLA_IFALIAS]) fprintf(fp,"\n alias %s", rta_getattr_str(tb[IFLA_IFALIAS])); From 5ab3a4de5ec5d6451ad17b781ff25dfa1932587f Mon Sep 17 00:00:00 2001 From: Benjamin Poirier Date: Wed, 6 Feb 2013 11:19:24 +0000 Subject: [PATCH 51/60] Use pkg-config to obtain xtables.h path On openSUSE 12.2 (at least) xtables.h is not installed in the system-wide include dir but in /usr/include/iptables-1.4.16.3/. This results in the following build failure: em_ipset.c:26:21: fatal error: xtables.h: No such file or directory Other includers of xtables.h already call out to pkg-config --- tc/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tc/Makefile b/tc/Makefile index 696f8913..f26e7646 100644 --- a/tc/Makefile +++ b/tc/Makefile @@ -140,6 +140,8 @@ m_xt.so: m_xt.c m_xt_old.so: m_xt_old.c $(CC) $(CFLAGS) $(LDFLAGS) -shared -fpic -o m_xt_old.so m_xt_old.c $$($(PKG_CONFIG) xtables --cflags --libs) +em_ipset.o: CFLAGS += $$($(PKG_CONFIG) xtables --cflags) + %.yacc.c: %.y $(YACC) $(YACCFLAGS) -o $@ $< From 49572501664d08262b0b79e118126b1cf6b15fc2 Mon Sep 17 00:00:00 2001 From: Kees van Reeuwijk Date: Fri, 8 Feb 2013 03:32:36 +0000 Subject: [PATCH 52/60] iproute2: clarification of various man8 pages Rephrasing for clarity. Note that in ip-rule.8 I rephrased a sentence to "The RPDB is scanned in order of decreasing priority." The original version talked about *in*creasing priority, but from the context that didn't make sense. Signed-off-by: Kees van Reeuwijk --- man/man8/arpd.8 | 38 +++++++++++++++++++------------------- man/man8/bridge.8 | 10 +++++----- man/man8/ip-addrlabel.8 | 16 ++++++++-------- man/man8/ip-maddress.8 | 10 +++++----- man/man8/ip-monitor.8 | 25 ++++++++++++++++--------- man/man8/ip-mroute.8 | 4 ++-- man/man8/ip-neighbour.8 | 2 +- man/man8/ip-netconf.8 | 6 +++--- man/man8/ip-netns.8 | 4 ++-- man/man8/ip-rule.8 | 6 +++--- man/man8/ip.8 | 20 ++++++++++---------- man/man8/tc.8 | 6 +++--- 12 files changed, 77 insertions(+), 70 deletions(-) diff --git a/man/man8/arpd.8 b/man/man8/arpd.8 index a14044b4..6b9a43a9 100644 --- a/man/man8/arpd.8 +++ b/man/man8/arpd.8 @@ -4,12 +4,12 @@ arpd \- userspace arp daemon. .SH SYNOPSIS -Usage: arpd [ -lkh? ] [ -a N ] [ -b dbase ] [ -B number ] [ -f file ] [-p interval ] [ -n time ] [ -R rate ] [ interfaces ] +Usage: arpd [ -lkh? ] [ -a N ] [ -b dbase ] [ -B number ] [ -f file ] [-p interval ] [ -n time ] [ -R rate ] [ ] .SH DESCRIPTION The .B arpd -daemon collects gratuitous ARP information, saving it on local disk and feeding it to kernel on demand to avoid redundant broadcasting due to limited size of kernel ARP cache. +daemon collects gratuitous ARP information, saving it on local disk and feeding it to the kernel on demand to avoid redundant broadcasting due to limited size of the kernel ARP cache. .SH OPTIONS .TP @@ -17,41 +17,41 @@ daemon collects gratuitous ARP information, saving it on local disk and feeding Print help .TP -l -Dump arpd database to stdout and exit. Output consists of three columns: interface index, IP address and MAC address. Negative entries for dead hosts are also shown, in this case MAC address is replaced by word FAILED followed by colon and time when the fact that host is dead was proven the last time. +Dump the arpd database to stdout and exit. The output consists of three columns: the interface index, the IP address of the interface, and the MAC address of the interface. Negative entries for dead hosts are also shown, in this case the MAC address is replaced by the word FAILED followed by a colon and the most recent time when the fact that the host is dead was proven. .TP -f -Read and load arpd database from FILE in text format similar dumped by option -l. Exit after load, probably listing resulting database, if option -l is also given. If FILE is -, stdin is read to get ARP table. +Read and load an arpd database from FILE in a text format similar to that dumped by option -l. Exit after load, possibly listing resulting database, if option -l is also given. If FILE is -, stdin is read to get the ARP table. .TP -b -location of database file. Default location is /var/lib/arpd/arpd.db +the location of the database file. The default location is /var/lib/arpd/arpd.db .TP -a -arpd not only passively listens ARP on wire, but also send brodcast queries itself. NUMBER is number of such queries to make before destination is considered as dead. When arpd is started as kernel helper (i.e. with app_solicit enabled in sysctl or even with option -k) without this option and still did not learn enough information, you can observe 1 second gaps in service. Not fatal, but not good. +With this option, arpd not only passively listens for ARP packets on the interface, but also sends brodcast queries itself. NUMBER is the number of such queries to make before a destination is considered dead. When arpd is started as kernel helper (i.e. with app_solicit enabled in sysctl or even with option -k) without this option and still did not learn enough information, you can observe 1 second gaps in service. Not fatal, but not good. .TP -k -Suppress sending broadcast queries by kernel. It takes sense together with option -a. +Suppress sending broadcast queries by the kernel. This option only makes sense together with option -a. .TP -n