diff --git a/ChangeLog b/ChangeLog index 08f4981c..88d66dbf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2005-09-01 Stephen Hemminger + + * Integrate support for DCCP into 'ss' (from acme) + * Add -batch option to ip. + * Update to 2.6.14 headers + 2005-09-01 Eric Dumazet * Fix lnstat : First column should not be summed diff --git a/include/SNAPSHOT.h b/include/SNAPSHOT.h index 1228d7e7..13ad8c71 100644 --- a/include/SNAPSHOT.h +++ b/include/SNAPSHOT.h @@ -1 +1 @@ -static char SNAPSHOT[] = "050816"; +static char SNAPSHOT[] = "050901"; diff --git a/include/linux/inet_diag.h b/include/linux/inet_diag.h new file mode 100644 index 00000000..85d456db --- /dev/null +++ b/include/linux/inet_diag.h @@ -0,0 +1,122 @@ +#ifndef _INET_DIAG_H_ +#define _INET_DIAG_H_ 1 + +/* Just some random number */ +#define TCPDIAG_GETSOCK 18 +#define DCCPDIAG_GETSOCK 19 + +#define INET_DIAG_GETSOCK_MAX 24 + +/* Socket identity */ +struct inet_diag_sockid { + __u16 idiag_sport; + __u16 idiag_dport; + __u32 idiag_src[4]; + __u32 idiag_dst[4]; + __u32 idiag_if; + __u32 idiag_cookie[2]; +#define INET_DIAG_NOCOOKIE (~0U) +}; + +/* Request structure */ + +struct inet_diag_req { + __u8 idiag_family; /* Family of addresses. */ + __u8 idiag_src_len; + __u8 idiag_dst_len; + __u8 idiag_ext; /* Query extended information */ + + struct inet_diag_sockid id; + + __u32 idiag_states; /* States to dump */ + __u32 idiag_dbs; /* Tables to dump (NI) */ +}; + +enum { + INET_DIAG_REQ_NONE, + INET_DIAG_REQ_BYTECODE, +}; + +#define INET_DIAG_REQ_MAX INET_DIAG_REQ_BYTECODE + +/* Bytecode is sequence of 4 byte commands followed by variable arguments. + * All the commands identified by "code" are conditional jumps forward: + * to offset cc+"yes" or to offset cc+"no". "yes" is supposed to be + * length of the command and its arguments. + */ + +struct inet_diag_bc_op { + unsigned char code; + unsigned char yes; + unsigned short no; +}; + +enum { + INET_DIAG_BC_NOP, + INET_DIAG_BC_JMP, + INET_DIAG_BC_S_GE, + INET_DIAG_BC_S_LE, + INET_DIAG_BC_D_GE, + INET_DIAG_BC_D_LE, + INET_DIAG_BC_AUTO, + INET_DIAG_BC_S_COND, + INET_DIAG_BC_D_COND, +}; + +struct inet_diag_hostcond { + __u8 family; + __u8 prefix_len; + int port; + __u32 addr[0]; +}; + +/* Base info structure. It contains socket identity (addrs/ports/cookie) + * and, alas, the information shown by netstat. */ +struct inet_diag_msg { + __u8 idiag_family; + __u8 idiag_state; + __u8 idiag_timer; + __u8 idiag_retrans; + + struct inet_diag_sockid id; + + __u32 idiag_expires; + __u32 idiag_rqueue; + __u32 idiag_wqueue; + __u32 idiag_uid; + __u32 idiag_inode; +}; + +/* Extensions */ + +enum { + INET_DIAG_NONE, + INET_DIAG_MEMINFO, + INET_DIAG_INFO, + INET_DIAG_VEGASINFO, + INET_DIAG_CONG, +}; + +#define INET_DIAG_MAX INET_DIAG_CONG + + +/* INET_DIAG_MEM */ + +struct inet_diag_meminfo { + __u32 idiag_rmem; + __u32 idiag_wmem; + __u32 idiag_fmem; + __u32 idiag_tmem; +}; + +/* INET_DIAG_VEGASINFO */ + +struct tcpvegas_info { + __u32 tcpv_enabled; + __u32 tcpv_rttcnt; + __u32 tcpv_rtt; + __u32 tcpv_minrtt; +}; + + +#endif /* _INET_DIAG_H_ */ diff --git a/include/linux/netlink.h b/include/linux/netlink.h index 90be210c..e433979b 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -8,19 +8,17 @@ #define NETLINK_W1 1 /* 1-wire subsystem */ #define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */ #define NETLINK_FIREWALL 3 /* Firewalling hook */ -#define NETLINK_TCPDIAG 4 /* TCP socket monitoring */ +#define NETLINK_INET_DIAG 4 /* INET socket monitoring */ #define NETLINK_NFLOG 5 /* netfilter/iptables ULOG */ #define NETLINK_XFRM 6 /* ipsec */ #define NETLINK_SELINUX 7 /* SELinux event notifications */ -#define NETLINK_ARPD 8 +#define NETLINK_ISCSI 8 /* Open-iSCSI */ #define NETLINK_AUDIT 9 /* auditing */ #define NETLINK_FIB_LOOKUP 10 -#define NETLINK_ROUTE6 11 /* af_inet6 route comm channel */ #define NETLINK_NETFILTER 12 /* netfilter subsystem */ #define NETLINK_IP6_FW 13 #define NETLINK_DNRTMSG 14 /* DECnet routing messages */ #define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */ -#define NETLINK_TAPBASE 16 /* 16 to 31 are ethertap */ #define MAX_LINKS 32 @@ -92,6 +90,15 @@ struct nlmsgerr struct nlmsghdr msg; }; +#define NETLINK_ADD_MEMBERSHIP 1 +#define NETLINK_DROP_MEMBERSHIP 2 +#define NETLINK_PKTINFO 3 + +struct nl_pktinfo +{ + __u32 group; +}; + #define NET_MAJOR 36 /* Major 36 is reserved for networking */ enum { diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index 25b35498..46a30f04 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -826,9 +826,7 @@ enum #define TCA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct tcmsg)))) #define TCA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct tcmsg)) - -/* RTnetlink multicast groups */ - +/* RTnetlink multicast groups - backwards compatibility for userspace */ #define RTMGRP_LINK 1 #define RTMGRP_NOTIFY 2 #define RTMGRP_NEIGH 4 @@ -848,6 +846,42 @@ enum #define RTMGRP_IPV6_PREFIX 0x20000 +/* RTnetlink multicast groups */ +enum rtnetlink_groups { + RTNLGRP_NONE, +#define RTNLGRP_NONE RTNLGRP_NONE + RTNLGRP_LINK, +#define RTNLGRP_LINK RTNLGRP_LINK + RTNLGRP_NOTIFY, +#define RTNLGRP_NOTIFY RTNLGRP_NOTIFY + RTNLGRP_NEIGH, +#define RTNLGRP_NEIGH RTNLGRP_NEIGH + RTNLGRP_TC, +#define RTNLGRP_TC RTNLGRP_TC + RTNLGRP_IPV4_IFADDR, +#define RTNLGRP_IPV4_IFADDR RTNLGRP_IPV4_IFADDR + RTNLGRP_IPV4_MROUTE, +#define RTNLGRP_IPV4_MROUTE RTNLGRP_IPV4_MROUTE + RTNLGRP_IPV4_ROUTE, +#define RTNLGRP_IPV4_ROUTE RTNLGRP_IPV4_ROUTE + RTNLGRP_IPV6_IFADDR, +#define RTNLGRP_IPV6_IFADDR RTNLGRP_IPV6_IFADDR + RTNLGRP_IPV6_MROUTE, +#define RTNLGRP_IPV6_MROUTE RTNLGRP_IPV6_MROUTE + RTNLGRP_IPV6_ROUTE, +#define RTNLGRP_IPV6_ROUTE RTNLGRP_IPV6_ROUTE + RTNLGRP_IPV6_IFINFO, +#define RTNLGRP_IPV6_IFINFO RTNLGRP_IPV6_IFINFO + RTNLGRP_DECnet_IFADDR, +#define RTNLGRP_DECnet_IFADDR RTNLGRP_DECnet_IFADDR + RTNLGRP_DECnet_ROUTE, +#define RTNLGRP_DECnet_ROUTE RTNLGRP_DECnet_ROUTE + RTNLGRP_IPV6_PREFIX, +#define RTNLGRP_IPV6_PREFIX RTNLGRP_IPV6_PREFIX + __RTNLGRP_MAX +}; +#define RTNLGRP_MAX (__RTNLGRP_MAX - 1) + /* TC action piece */ struct tcamsg { diff --git a/include/linux/tc_act/tc_defact.h b/include/linux/tc_act/tc_defact.h new file mode 100644 index 00000000..964f473a --- /dev/null +++ b/include/linux/tc_act/tc_defact.h @@ -0,0 +1,21 @@ +#ifndef __LINUX_TC_DEF_H +#define __LINUX_TC_DEF_H + +#include + +struct tc_defact +{ + tc_gen; +}; + +enum +{ + TCA_DEF_UNSPEC, + TCA_DEF_TM, + TCA_DEF_PARMS, + TCA_DEF_DATA, + __TCA_DEF_MAX +}; +#define TCA_DEF_MAX (__TCA_DEF_MAX - 1) + +#endif diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 66763799..01600740 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -55,24 +55,6 @@ struct tcphdr { __u16 urg_ptr; }; - -enum { - TCP_ESTABLISHED = 1, - TCP_SYN_SENT, - TCP_SYN_RECV, - TCP_FIN_WAIT1, - TCP_FIN_WAIT2, - TCP_TIME_WAIT, - TCP_CLOSE, - TCP_CLOSE_WAIT, - TCP_LAST_ACK, - TCP_LISTEN, - TCP_CLOSING, /* now a valid state */ - - TCP_MAX_STATES /* Leave at the end! */ -}; - -#define TCP_STATE_MASK 0xF #define TCP_ACTION_FIN (1 << 7) enum { diff --git a/include/linux/tcp_diag.h b/include/linux/tcp_diag.h deleted file mode 100644 index 7a599674..00000000 --- a/include/linux/tcp_diag.h +++ /dev/null @@ -1,127 +0,0 @@ -#ifndef _TCP_DIAG_H_ -#define _TCP_DIAG_H_ 1 - -/* Just some random number */ -#define TCPDIAG_GETSOCK 18 - -/* Socket identity */ -struct tcpdiag_sockid -{ - __u16 tcpdiag_sport; - __u16 tcpdiag_dport; - __u32 tcpdiag_src[4]; - __u32 tcpdiag_dst[4]; - __u32 tcpdiag_if; - __u32 tcpdiag_cookie[2]; -#define TCPDIAG_NOCOOKIE (~0U) -}; - -/* Request structure */ - -struct tcpdiagreq -{ - __u8 tcpdiag_family; /* Family of addresses. */ - __u8 tcpdiag_src_len; - __u8 tcpdiag_dst_len; - __u8 tcpdiag_ext; /* Query extended information */ - - struct tcpdiag_sockid id; - - __u32 tcpdiag_states; /* States to dump */ - __u32 tcpdiag_dbs; /* Tables to dump (NI) */ -}; - -enum -{ - TCPDIAG_REQ_NONE, - TCPDIAG_REQ_BYTECODE, -}; - -#define TCPDIAG_REQ_MAX TCPDIAG_REQ_BYTECODE - -/* Bytecode is sequence of 4 byte commands followed by variable arguments. - * All the commands identified by "code" are conditional jumps forward: - * to offset cc+"yes" or to offset cc+"no". "yes" is supposed to be - * length of the command and its arguments. - */ - -struct tcpdiag_bc_op -{ - unsigned char code; - unsigned char yes; - unsigned short no; -}; - -enum -{ - TCPDIAG_BC_NOP, - TCPDIAG_BC_JMP, - TCPDIAG_BC_S_GE, - TCPDIAG_BC_S_LE, - TCPDIAG_BC_D_GE, - TCPDIAG_BC_D_LE, - TCPDIAG_BC_AUTO, - TCPDIAG_BC_S_COND, - TCPDIAG_BC_D_COND, -}; - -struct tcpdiag_hostcond -{ - __u8 family; - __u8 prefix_len; - int port; - __u32 addr[0]; -}; - -/* Base info structure. It contains socket identity (addrs/ports/cookie) - * and, alas, the information shown by netstat. */ -struct tcpdiagmsg -{ - __u8 tcpdiag_family; - __u8 tcpdiag_state; - __u8 tcpdiag_timer; - __u8 tcpdiag_retrans; - - struct tcpdiag_sockid id; - - __u32 tcpdiag_expires; - __u32 tcpdiag_rqueue; - __u32 tcpdiag_wqueue; - __u32 tcpdiag_uid; - __u32 tcpdiag_inode; -}; - -/* Extensions */ - -enum -{ - TCPDIAG_NONE, - TCPDIAG_MEMINFO, - TCPDIAG_INFO, - TCPDIAG_VEGASINFO, - TCPDIAG_CONG, -}; - -#define TCPDIAG_MAX TCPDIAG_CONG - - -/* TCPDIAG_MEM */ - -struct tcpdiag_meminfo -{ - __u32 tcpdiag_rmem; - __u32 tcpdiag_wmem; - __u32 tcpdiag_fmem; - __u32 tcpdiag_tmem; -}; - -/* TCPDIAG_VEGASINFO */ - -struct tcpvegas_info { - __u32 tcpv_enabled; - __u32 tcpv_rttcnt; - __u32 tcpv_rtt; - __u32 tcpv_minrtt; -}; - -#endif /* _TCP_DIAG_H_ */ diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h index f0d42330..8a4051d8 100644 --- a/include/linux/xfrm.h +++ b/include/linux/xfrm.h @@ -258,9 +258,25 @@ struct xfrm_usersa_flush { __u8 proto; }; +/* backwards compatibility for userspace */ #define XFRMGRP_ACQUIRE 1 #define XFRMGRP_EXPIRE 2 #define XFRMGRP_SA 4 #define XFRMGRP_POLICY 8 +enum xfrm_nlgroups { + XFRMNLGRP_NONE, +#define XFRMNLGRP_NONE XFRMNLGRP_NONE + XFRMNLGRP_ACQUIRE, +#define XFRMNLGRP_ACQUIRE XFRMNLGRP_ACQUIRE + XFRMNLGRP_EXPIRE, +#define XFRMNLGRP_EXPIRE XFRMNLGRP_EXPIRE + XFRMNLGRP_SA, +#define XFRMNLGRP_SA XFRMNLGRP_SA + XFRMNLGRP_POLICY, +#define XFRMNLGRP_POLICY XFRMNLGRP_POLICY + __XFRMNLGRP_MAX +}; +#define XFRMNLGRP_MAX (__XFRMNLGRP_MAX - 1) + #endif /* _LINUX_XFRM_H */ diff --git a/include/net/tcp_states.h b/include/net/tcp_states.h new file mode 100644 index 00000000..b9d4176b --- /dev/null +++ b/include/net/tcp_states.h @@ -0,0 +1,34 @@ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * Definitions for the TCP protocol sk_state field. + * + * 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_TCP_STATES_H +#define _LINUX_TCP_STATES_H + +enum { + TCP_ESTABLISHED = 1, + TCP_SYN_SENT, + TCP_SYN_RECV, + TCP_FIN_WAIT1, + TCP_FIN_WAIT2, + TCP_TIME_WAIT, + TCP_CLOSE, + TCP_CLOSE_WAIT, + TCP_LAST_ACK, + TCP_LISTEN, + TCP_CLOSING, /* Now a valid state */ + + TCP_MAX_STATES /* Leave at the end! */ +}; + +#define TCP_STATE_MASK 0xF + +#endif /* _LINUX_TCP_STATES_H */ diff --git a/include/utils.h b/include/utils.h index a78ae03a..0f1d1f61 100644 --- a/include/utils.h +++ b/include/utils.h @@ -131,4 +131,8 @@ int print_timestamp(FILE *fp); #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +extern int cmdlineno; +extern size_t getcmdline(char **line, size_t *len, FILE *in); +extern int makeargs(char *line, char *argv[], int maxargs); + #endif /* __UTILS_H__ */ diff --git a/ip/ip.c b/ip/ip.c index 3d632ef1..af348d8e 100644 --- a/ip/ip.c +++ b/ip/ip.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "SNAPSHOT.h" #include "utils.h" @@ -33,6 +34,9 @@ int resolve_hosts = 0; int oneline = 0; int timestamp = 0; char * _SL_ = NULL; +char *batch_file = NULL; +int force = 0; +struct rtnl_handle rth; static void usage(void) __attribute__((noreturn)); @@ -48,6 +52,75 @@ static void usage(void) exit(-1); } +static const struct cmd { + const char *cmd; + int (*func)(int argc, char **argv); +} cmds[] = { + { "addr", do_ipaddr }, + { "maddr", do_multiaddr }, + { "route", do_iproute }, + { "rule", do_iprule }, + { "neigh", do_ipneigh }, + { "link", do_iplink }, + { "tunnel", do_iptunnel }, + { "monitor", do_ipmonitor }, + { "xfrm", do_xfrm }, + { 0 } +}; + +static int do_cmd(const char *argv0, int argc, char **argv) +{ + const struct cmd *c; + + for (c = cmds; c->cmd; ++c) + if (strcmp(c->cmd, argv0) == 0) + return c->func(argc-1, argv+1); + + fprintf(stderr, "Object \"%s\" is unknown, try \"ip help\".\n", argv0); + exit(-1); +} + +static int batch(const char *name) +{ + char *line = NULL; + size_t len = 0; + int ret = 0; + int lineno = 0; + + if (name && strcmp(name, "-") != 0) { + if (freopen(name, "r", stdin) == NULL) { + fprintf(stderr, "Cannot open file \"%s\" for reading: %s=n", + name, strerror(errno)); + return -1; + } + } + + if (rtnl_open(&rth, 0) < 0) { + fprintf(stderr, "Cannot open rtnetlink\n"); + return -1; + } + + while (getcmdline(&line, &len, stdin) != -1) { + char *largv[100]; + int largc; + + largc = makeargs(line, largv, 100); + if (largc == 0) + continue; /* blank line */ + + if (do_cmd(largv[0], largc, largv)) { + fprintf(stderr, "Command failed %s:%d\n", name, lineno); + ret = 1; + if (!force) + break; + } + } + + rtnl_close(&rth); + return ret; +} + + int main(int argc, char **argv) { char *basename; @@ -113,6 +186,14 @@ int main(int argc, char **argv) } else if (matches(opt, "-Version") == 0) { printf("ip utility, iproute2-ss%s\n", SNAPSHOT); exit(0); + } else if (matches(opt, "-force") == 0) { + ++force; + } else if (matches(opt, "-batch") == 0) { + argc--; + argv++; + if (argc <= 1) + usage(); + batch_file = argv[1]; } else if (matches(opt, "-help") == 0) { usage(); } else { @@ -124,52 +205,18 @@ int main(int argc, char **argv) _SL_ = oneline ? "\\" : "\n" ; - if (strcmp(basename, "ipaddr") == 0) - return do_ipaddr(argc-1, argv+1); - if (strcmp(basename, "ipmaddr") == 0) - return do_multiaddr(argc-1, argv+1); - if (strcmp(basename, "iproute") == 0) - return do_iproute(argc-1, argv+1); - if (strcmp(basename, "iprule") == 0) - return do_iprule(argc-1, argv+1); - if (strcmp(basename, "ipneigh") == 0) - return do_ipneigh(argc-1, argv+1); - if (strcmp(basename, "iplink") == 0) - return do_iplink(argc-1, argv+1); - if (strcmp(basename, "iptunnel") == 0) - return do_iptunnel(argc-1, argv+1); - if (strcmp(basename, "ipmonitor") == 0) - return do_ipmonitor(argc-1, argv+1); - if (strcmp(basename, "ipxfrm") == 0) - return do_xfrm(argc-1, argv+1); + if (batch_file) + return batch(batch_file); + + if (rtnl_open(&rth, 0) < 0) + exit(1); - if (argc > 1) { - if (matches(argv[1], "address") == 0) - return do_ipaddr(argc-2, argv+2); - if (matches(argv[1], "maddress") == 0) - return do_multiaddr(argc-2, argv+2); - if (matches(argv[1], "route") == 0) - return do_iproute(argc-2, argv+2); - if (matches(argv[1], "rule") == 0) - return do_iprule(argc-2, argv+2); - if (matches(argv[1], "mroute") == 0) - return do_multiroute(argc-2, argv+2); - if (matches(argv[1], "neighbor") == 0 || - matches(argv[1], "neighbour") == 0) - return do_ipneigh(argc-2, argv+2); - if (matches(argv[1], "link") == 0) - return do_iplink(argc-2, argv+2); - if (matches(argv[1], "tunnel") == 0 || - strcmp(argv[1], "tunl") == 0) - return do_iptunnel(argc-2, argv+2); - if (matches(argv[1], "monitor") == 0) - return do_ipmonitor(argc-2, argv+2); - if (matches(argv[1], "xfrm") == 0) - return do_xfrm(argc-2, argv+2); - if (matches(argv[1], "help") == 0) - usage(); - fprintf(stderr, "Object \"%s\" is unknown, try \"ip help\".\n", argv[1]); - exit(-1); - } + if (strlen(basename) > 2) + return do_cmd(basename+2, argc, argv); + + if (argc > 1) + return do_cmd(argv[1], argc-1, argv+1); + + rtnl_close(&rth); usage(); } diff --git a/ip/ip_common.h b/ip/ip_common.h index 688d384c..b502f6ca 100644 --- a/ip/ip_common.h +++ b/ip/ip_common.h @@ -27,3 +27,5 @@ extern int do_ipmonitor(int argc, char **argv); extern int do_multiaddr(int argc, char **argv); extern int do_multiroute(int argc, char **argv); extern int do_xfrm(int argc, char **argv); + +extern struct rtnl_handle rth; diff --git a/ip/ipaddress.c b/ip/ipaddress.c index 8e90c701..30d60ec4 100644 --- a/ip/ipaddress.c +++ b/ip/ipaddress.c @@ -49,7 +49,6 @@ static struct char *flushb; int flushp; int flushe; - struct rtnl_handle *rth; } filter; static int do_link; @@ -269,7 +268,7 @@ int print_linkinfo(const struct sockaddr_nl *who, static int flush_update(void) { - if (rtnl_send(filter.rth, filter.flushb, filter.flushp) < 0) { + if (rtnl_send(&rth, filter.flushb, filter.flushp) < 0) { perror("Failed to send flush request\n"); return -1; } @@ -345,7 +344,7 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, memcpy(fn, n, n->nlmsg_len); fn->nlmsg_type = RTM_DELADDR; fn->nlmsg_flags = NLM_F_REQUEST; - fn->nlmsg_seq = ++filter.rth->seq; + fn->nlmsg_seq = ++rth.seq; filter.flushp = (((char*)fn) + n->nlmsg_len) - filter.flushb; filter.flushed++; if (show_stats < 2) @@ -496,7 +495,6 @@ int ipaddr_list_or_flush(int argc, char **argv, int flush) struct nlmsg_list *linfo = NULL; struct nlmsg_list *ainfo = NULL; struct nlmsg_list *l; - struct rtnl_handle rth; char *filter_dev = NULL; int no_link = 0; @@ -570,9 +568,6 @@ int ipaddr_list_or_flush(int argc, char **argv, int flush) argv++; argc--; } - if (rtnl_open(&rth, 0) < 0) - exit(1); - if (rtnl_wilddump_request(&rth, preferred_family, RTM_GETLINK) < 0) { perror("Cannot send dump request"); exit(1); @@ -598,7 +593,6 @@ int ipaddr_list_or_flush(int argc, char **argv, int flush) filter.flushb = flushb; filter.flushp = 0; filter.flushe = sizeof(flushb); - filter.rth = &rth; for (;;) { if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) { @@ -620,7 +614,8 @@ int ipaddr_list_or_flush(int argc, char **argv, int flush) } round++; if (flush_update() < 0) - exit(1); + return 1; + if (show_stats) { printf("\n*** Round %d, deleting %d addresses ***\n", round, filter.flushed); fflush(stdout); @@ -709,7 +704,7 @@ int ipaddr_list_or_flush(int argc, char **argv, int flush) fflush(stdout); } - exit(0); + return 0; } int ipaddr_list_link(int argc, char **argv) @@ -736,7 +731,6 @@ int default_scope(inet_prefix *lcl) int ipaddr_modify(int cmd, int argc, char **argv) { - struct rtnl_handle rth; struct { struct nlmsghdr n; struct ifaddrmsg ifa; @@ -877,9 +871,6 @@ int ipaddr_modify(int cmd, int argc, char **argv) if (!scoped && cmd != RTM_DELADDR) req.ifa.ifa_scope = default_scope(&lcl); - if (rtnl_open(&rth, 0) < 0) - exit(1); - ll_init_map(&rth); if ((req.ifa.ifa_index = ll_name_to_index(d)) == 0) { @@ -890,7 +881,7 @@ int ipaddr_modify(int cmd, int argc, char **argv) if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) exit(2); - exit(0); + return 0; } int do_ipaddr(int argc, char **argv) diff --git a/ip/ipmonitor.c b/ip/ipmonitor.c index 819f9f6a..9f725637 100644 --- a/ip/ipmonitor.c +++ b/ip/ipmonitor.c @@ -88,7 +88,6 @@ int accept_msg(const struct sockaddr_nl *who, int do_ipmonitor(int argc, char **argv) { - struct rtnl_handle rth; char *file = NULL; unsigned groups = ~RTMGRP_TC; int llink=0; @@ -156,13 +155,10 @@ int do_ipmonitor(int argc, char **argv) return rtnl_from_file(fp, accept_msg, (void*)stdout); } - if (rtnl_open(&rth, groups) < 0) - exit(1); - ll_init_map(&rth); if (rtnl_listen(&rth, accept_msg, (void*)stdout) < 0) exit(2); - exit(0); + return 0; } diff --git a/ip/ipneigh.c b/ip/ipneigh.c index 1ba13ac3..9e12befc 100644 --- a/ip/ipneigh.c +++ b/ip/ipneigh.c @@ -44,7 +44,6 @@ static struct char *flushb; int flushp; int flushe; - struct rtnl_handle *rth; } filter; static void usage(void) __attribute__((noreturn)); @@ -89,7 +88,7 @@ int nud_state_a2n(unsigned *state, char *arg) static int flush_update(void) { - if (rtnl_send(filter.rth, filter.flushb, filter.flushp) < 0) { + if (rtnl_send(&rth, filter.flushb, filter.flushp) < 0) { perror("Failed to send flush request\n"); return -1; } @@ -100,7 +99,6 @@ static int flush_update(void) static int ipneigh_modify(int cmd, int flags, int argc, char **argv) { - struct rtnl_handle rth; struct { struct nlmsghdr n; struct ndmsg ndm; @@ -174,9 +172,6 @@ static int ipneigh_modify(int cmd, int flags, int argc, char **argv) addattr_l(&req.n, sizeof(req), NDA_LLADDR, llabuf, l); } - if (rtnl_open(&rth, 0) < 0) - exit(1); - ll_init_map(&rth); if ((req.ndm.ndm_ifindex = ll_name_to_index(d)) == 0) { @@ -187,7 +182,7 @@ static int ipneigh_modify(int cmd, int flags, int argc, char **argv) if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) exit(2); - exit(0); + return 0; } @@ -251,7 +246,7 @@ int print_neigh(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) memcpy(fn, n, n->nlmsg_len); fn->nlmsg_type = RTM_DELNEIGH; fn->nlmsg_flags = NLM_F_REQUEST; - fn->nlmsg_seq = ++filter.rth->seq; + fn->nlmsg_seq = ++rth.seq; filter.flushp = (((char*)fn) + n->nlmsg_len) - filter.flushb; filter.flushed++; if (show_stats < 2) @@ -326,7 +321,6 @@ void ipneigh_reset_filter() int do_show_or_flush(int argc, char **argv, int flush) { char *filter_dev = NULL; - struct rtnl_handle rth; int state_given = 0; ipneigh_reset_filter(); @@ -381,9 +375,6 @@ int do_show_or_flush(int argc, char **argv, int flush) argc--; argv++; } - if (rtnl_open(&rth, 0) < 0) - exit(1); - ll_init_map(&rth); if (filter_dev) { @@ -400,7 +391,6 @@ int do_show_or_flush(int argc, char **argv, int flush) filter.flushb = flushb; filter.flushp = 0; filter.flushe = sizeof(flushb); - filter.rth = &rth; filter.state &= ~NUD_FAILED; while (round < MAX_ROUNDS) { diff --git a/ip/iproute.c b/ip/iproute.c index 26298424..c8c32873 100644 --- a/ip/iproute.c +++ b/ip/iproute.c @@ -80,7 +80,6 @@ static struct char *flushb; int flushp; int flushe; - struct rtnl_handle *rth; int protocol, protocolmask; int scope, scopemask; int type, typemask; @@ -106,7 +105,7 @@ static char *mp_alg_names[IP_MP_ALG_MAX+1] = { static int flush_update(void) { - if (rtnl_send(filter.rth, filter.flushb, filter.flushp) < 0) { + if (rtnl_send(&rth, filter.flushb, filter.flushp) < 0) { perror("Failed to send flush request\n"); return -1; } @@ -281,7 +280,7 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) memcpy(fn, n, n->nlmsg_len); fn->nlmsg_type = RTM_DELROUTE; fn->nlmsg_flags = NLM_F_REQUEST; - fn->nlmsg_seq = ++filter.rth->seq; + fn->nlmsg_seq = ++rth.seq; filter.flushp = (((char*)fn) + n->nlmsg_len) - filter.flushb; filter.flushed++; if (show_stats < 2) @@ -649,7 +648,6 @@ int parse_nexthops(struct nlmsghdr *n, struct rtmsg *r, int argc, char **argv) int iproute_modify(int cmd, unsigned flags, int argc, char **argv) { - struct rtnl_handle rth; struct { struct nlmsghdr n; struct rtmsg r; @@ -889,9 +887,6 @@ int iproute_modify(int cmd, unsigned flags, int argc, char **argv) argc--; argv++; } - if (rtnl_open(&rth, 0) < 0) - exit(1); - if (d || nhs_ok) { int idx; @@ -998,7 +993,6 @@ static int iproute_flush_cache(void) static int iproute_list_or_flush(int argc, char **argv, int flush) { int do_ipv6 = preferred_family; - struct rtnl_handle rth; char *id = NULL; char *od = NULL; @@ -1132,9 +1126,6 @@ static int iproute_list_or_flush(int argc, char **argv, int flush) if (do_ipv6 == AF_UNSPEC && filter.tb) do_ipv6 = AF_INET; - if (rtnl_open(&rth, 0) < 0) - exit(1); - ll_init_map(&rth); if (id || od) { @@ -1176,7 +1167,6 @@ static int iproute_list_or_flush(int argc, char **argv, int flush) filter.flushb = flushb; filter.flushp = 0; filter.flushe = sizeof(flushb); - filter.rth = &rth; for (;;) { if (rtnl_wilddump_request(&rth, do_ipv6, RTM_GETROUTE) < 0) { @@ -1237,7 +1227,6 @@ static int iproute_list_or_flush(int argc, char **argv, int flush) int iproute_get(int argc, char **argv) { - struct rtnl_handle rth; struct { struct nlmsghdr n; struct rtmsg r; @@ -1317,9 +1306,6 @@ int iproute_get(int argc, char **argv) exit(1); } - if (rtnl_open(&rth, 0) < 0) - exit(1); - ll_init_map(&rth); if (idev || odev) { diff --git a/ip/iprule.c b/ip/iprule.c index 9c43011d..cfe252a2 100644 --- a/ip/iprule.c +++ b/ip/iprule.c @@ -28,6 +28,8 @@ #include "rt_names.h" #include "utils.h" +extern struct rtnl_handle rth; + static void usage(void) __attribute__((noreturn)); static void usage(void) @@ -161,7 +163,6 @@ static int print_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, static int iprule_list(int argc, char **argv) { - struct rtnl_handle rth; int af = preferred_family; if (af == AF_UNSPEC) @@ -172,9 +173,6 @@ static int iprule_list(int argc, char **argv) return -1; } - if (rtnl_open(&rth, 0) < 0) - return 1; - if (rtnl_wilddump_request(&rth, af, RTM_GETRULE) < 0) { perror("Cannot send dump request"); return 1; @@ -192,7 +190,6 @@ static int iprule_list(int argc, char **argv) static int iprule_modify(int cmd, int argc, char **argv) { int table_ok = 0; - struct rtnl_handle rth; struct { struct nlmsghdr n; struct rtmsg r; @@ -294,9 +291,6 @@ static int iprule_modify(int cmd, int argc, char **argv) if (!table_ok && cmd == RTM_NEWRULE) req.r.rtm_table = RT_TABLE_MAIN; - if (rtnl_open(&rth, 0) < 0) - return 1; - if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) return 2; @@ -306,7 +300,6 @@ static int iprule_modify(int cmd, int argc, char **argv) static int flush_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { - struct rtnl_handle rth; struct rtmsg *r = NLMSG_DATA(n); int len = n->nlmsg_len; struct rtattr * tb[RTA_MAX+1]; @@ -321,9 +314,6 @@ static int flush_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *a n->nlmsg_type = RTM_DELRULE; n->nlmsg_flags = NLM_F_REQUEST; - if (rtnl_open(&rth, 0) < 0) - return -1; - if (rtnl_talk(&rth, n, 0, 0, NULL, NULL, NULL) < 0) return -2; } @@ -333,7 +323,6 @@ static int flush_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *a static int iprule_flush(int argc, char **argv) { - struct rtnl_handle rth; int af = preferred_family; if (af == AF_UNSPEC) @@ -344,9 +333,6 @@ static int iprule_flush(int argc, char **argv) return -1; } - if (rtnl_open(&rth, 0) < 0) - return 1; - if (rtnl_wilddump_request(&rth, af, RTM_GETRULE) < 0) { perror("Cannot send dump request"); return 1; diff --git a/ip/xfrm_monitor.c b/ip/xfrm_monitor.c index 7edb21f4..e5ccbf7c 100644 --- a/ip/xfrm_monitor.c +++ b/ip/xfrm_monitor.c @@ -186,13 +186,10 @@ int do_xfrm_monitor(int argc, char **argv) return rtnl_from_file(fp, xfrm_accept_msg, (void*)stdout); } - if (rtnl_open_byproto(&rth, groups, NETLINK_XFRM) < 0) - exit(1); - //ll_init_map(&rth); if (rtnl_listen(&rth, xfrm_accept_msg, (void*)stdout) < 0) exit(2); - exit(0); + return 0; } diff --git a/lib/utils.c b/lib/utils.c index 7d336eb7..4bdda712 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -574,3 +574,67 @@ int print_timestamp(FILE *fp) fprintf(fp, "Timestamp: %s %lu usec\n", tstr, tv.tv_usec); return 0; } + +int cmdlineno; + +/* Like glibc getline but handle continuation lines and comments */ +size_t getcmdline(char **linep, size_t *lenp, FILE *in) +{ + size_t cc; + char *cp; + + if ((cc = getline(linep, lenp, in)) < 0) + return cc; /* eof or error */ + ++cmdlineno; + + cp = strchr(*linep, '#'); + if (cp) + *cp = '\0'; + + while ((cp = strstr(*linep, "\\\n")) != NULL) { + char *line1 = NULL; + size_t len1 = 0; + size_t cc1; + + if ((cc1 = getline(&line1, &len1, in)) < 0) { + fprintf(stderr, "Missing continuation line\n"); + return cc1; + } + + ++cmdlineno; + *cp = 0; + + cp = strchr(line1, '#'); + if (cp) + *cp = '\0'; + + *linep = realloc(*linep, strlen(*linep) + strlen(line1) + 1); + if (!*linep) { + fprintf(stderr, "Out of memory\n"); + return -1; + } + cc += cc1 - 2; + strcat(*linep, line1); + free(line1); + } + return cc; +} + +/* split command line into argument vector */ +int makeargs(char *line, char *argv[], int maxargs) +{ + static const char ws[] = " \t\r\n"; + char *cp; + int argc = 0; + + for (cp = strtok(line, ws); cp; cp = strtok(NULL, ws)) { + if (argc >= (maxargs - 1)) { + fprintf(stderr, "Too many arguments to command\n"); + exit(1); + } + argv[argc++] = cp; + } + argv[argc] = NULL; + + return argc; +} diff --git a/misc/ss.c b/misc/ss.c index 67fe6278..f902560a 100644 --- a/misc/ss.c +++ b/misc/ss.c @@ -33,8 +33,9 @@ #include "libnetlink.h" #include "SNAPSHOT.h" +#include #include -#include +#include int resolve_hosts = 0; int resolve_services = 1; @@ -60,6 +61,7 @@ static const char *dg_proto = NULL; enum { TCP_DB, + DCCP_DB, UDP_DB, RAW_DB, UNIX_DG_DB, @@ -730,7 +732,7 @@ int run_ssfilter(struct ssfilter *f, struct tcpstat *s) static void ssfilter_patch(char *a, int len, int reloc) { while (len > 0) { - struct tcpdiag_bc_op *op = (struct tcpdiag_bc_op*)a; + struct inet_diag_bc_op *op = (struct inet_diag_bc_op*)a; if (op->no == len+4) op->no += reloc; len -= op->yes; @@ -746,7 +748,7 @@ static int ssfilter_bytecompile(struct ssfilter *f, char **bytecode) case SSF_S_AUTO: { if (!(*bytecode=malloc(4))) abort(); - ((struct tcpdiag_bc_op*)*bytecode)[0] = (struct tcpdiag_bc_op){ TCPDIAG_BC_AUTO, 4, 8 }; + ((struct inet_diag_bc_op*)*bytecode)[0] = (struct inet_diag_bc_op){ INET_DIAG_BC_AUTO, 4, 8 }; return 8; } case SSF_DCOND: @@ -755,11 +757,11 @@ static int ssfilter_bytecompile(struct ssfilter *f, char **bytecode) struct aafilter *a = (void*)f->pred; struct aafilter *b; char *ptr; - int code = (f->type == SSF_DCOND ? TCPDIAG_BC_D_COND : TCPDIAG_BC_S_COND); + int code = (f->type == SSF_DCOND ? INET_DIAG_BC_D_COND : INET_DIAG_BC_S_COND); int len = 0; for (b=a; b; b=b->next) { - len += 4 + sizeof(struct tcpdiag_hostcond); + len += 4 + sizeof(struct inet_diag_hostcond); if (a->addr.family == AF_INET6) len += 16; else @@ -770,20 +772,20 @@ static int ssfilter_bytecompile(struct ssfilter *f, char **bytecode) if (!(ptr = malloc(len))) abort(); *bytecode = ptr; for (b=a; b; b=b->next) { - struct tcpdiag_bc_op *op = (struct tcpdiag_bc_op *)ptr; + struct inet_diag_bc_op *op = (struct inet_diag_bc_op *)ptr; int alen = (a->addr.family == AF_INET6 ? 16 : 4); - int oplen = alen + 4 + sizeof(struct tcpdiag_hostcond); - struct tcpdiag_hostcond *cond = (struct tcpdiag_hostcond*)(ptr+4); + int oplen = alen + 4 + sizeof(struct inet_diag_hostcond); + struct inet_diag_hostcond *cond = (struct inet_diag_hostcond*)(ptr+4); - *op = (struct tcpdiag_bc_op){ code, oplen, oplen+4 }; + *op = (struct inet_diag_bc_op){ code, oplen, oplen+4 }; cond->family = a->addr.family; cond->port = a->port; cond->prefix_len = a->addr.bitlen; memcpy(cond->addr, a->addr.data, alen); ptr += oplen; if (b->next) { - op = (struct tcpdiag_bc_op *)ptr; - *op = (struct tcpdiag_bc_op){ TCPDIAG_BC_JMP, 4, len - (ptr-*bytecode)}; + op = (struct inet_diag_bc_op *)ptr; + *op = (struct inet_diag_bc_op){ INET_DIAG_BC_JMP, 4, len - (ptr-*bytecode)}; ptr += 4; } } @@ -793,32 +795,32 @@ static int ssfilter_bytecompile(struct ssfilter *f, char **bytecode) { struct aafilter *x = (void*)f->pred; if (!(*bytecode=malloc(8))) abort(); - ((struct tcpdiag_bc_op*)*bytecode)[0] = (struct tcpdiag_bc_op){ TCPDIAG_BC_D_GE, 8, 12 }; - ((struct tcpdiag_bc_op*)*bytecode)[1] = (struct tcpdiag_bc_op){ 0, 0, x->port }; + ((struct inet_diag_bc_op*)*bytecode)[0] = (struct inet_diag_bc_op){ INET_DIAG_BC_D_GE, 8, 12 }; + ((struct inet_diag_bc_op*)*bytecode)[1] = (struct inet_diag_bc_op){ 0, 0, x->port }; return 8; } case SSF_D_LE: { struct aafilter *x = (void*)f->pred; if (!(*bytecode=malloc(8))) abort(); - ((struct tcpdiag_bc_op*)*bytecode)[0] = (struct tcpdiag_bc_op){ TCPDIAG_BC_D_LE, 8, 12 }; - ((struct tcpdiag_bc_op*)*bytecode)[1] = (struct tcpdiag_bc_op){ 0, 0, x->port }; + ((struct inet_diag_bc_op*)*bytecode)[0] = (struct inet_diag_bc_op){ INET_DIAG_BC_D_LE, 8, 12 }; + ((struct inet_diag_bc_op*)*bytecode)[1] = (struct inet_diag_bc_op){ 0, 0, x->port }; return 8; } case SSF_S_GE: { struct aafilter *x = (void*)f->pred; if (!(*bytecode=malloc(8))) abort(); - ((struct tcpdiag_bc_op*)*bytecode)[0] = (struct tcpdiag_bc_op){ TCPDIAG_BC_S_GE, 8, 12 }; - ((struct tcpdiag_bc_op*)*bytecode)[1] = (struct tcpdiag_bc_op){ 0, 0, x->port }; + ((struct inet_diag_bc_op*)*bytecode)[0] = (struct inet_diag_bc_op){ INET_DIAG_BC_S_GE, 8, 12 }; + ((struct inet_diag_bc_op*)*bytecode)[1] = (struct inet_diag_bc_op){ 0, 0, x->port }; return 8; } case SSF_S_LE: { struct aafilter *x = (void*)f->pred; if (!(*bytecode=malloc(8))) abort(); - ((struct tcpdiag_bc_op*)*bytecode)[0] = (struct tcpdiag_bc_op){ TCPDIAG_BC_S_LE, 8, 12 }; - ((struct tcpdiag_bc_op*)*bytecode)[1] = (struct tcpdiag_bc_op){ 0, 0, x->port }; + ((struct inet_diag_bc_op*)*bytecode)[0] = (struct inet_diag_bc_op){ INET_DIAG_BC_S_LE, 8, 12 }; + ((struct inet_diag_bc_op*)*bytecode)[1] = (struct inet_diag_bc_op){ 0, 0, x->port }; return 8; } @@ -844,7 +846,7 @@ static int ssfilter_bytecompile(struct ssfilter *f, char **bytecode) memcpy(a, a1, l1); memcpy(a+l1+4, a2, l2); free(a1); free(a2); - *(struct tcpdiag_bc_op*)(a+l1) = (struct tcpdiag_bc_op){ TCPDIAG_BC_JMP, 4, l2+4 }; + *(struct inet_diag_bc_op*)(a+l1) = (struct inet_diag_bc_op){ INET_DIAG_BC_JMP, 4, l2+4 }; *bytecode = a; return l1+l2+4; } @@ -855,7 +857,7 @@ static int ssfilter_bytecompile(struct ssfilter *f, char **bytecode) if (!(a = malloc(l1+4))) abort(); memcpy(a, a1, l1); free(a1); - *(struct tcpdiag_bc_op*)(a+l1) = (struct tcpdiag_bc_op){ TCPDIAG_BC_JMP, 4, 8 }; + *(struct inet_diag_bc_op*)(a+l1) = (struct inet_diag_bc_op){ INET_DIAG_BC_JMP, 4, 8 }; *bytecode = a; return l1+4; } @@ -1299,36 +1301,36 @@ static char *sprint_bw(char *buf, double bw) return buf; } -static void tcp_show_info(const struct nlmsghdr *nlh, struct tcpdiagmsg *r) +static void tcp_show_info(const struct nlmsghdr *nlh, struct inet_diag_msg *r) { - struct rtattr * tb[TCPDIAG_MAX+1]; + struct rtattr * tb[INET_DIAG_MAX+1]; char b1[64]; double rtt = 0; - parse_rtattr(tb, TCPDIAG_MAX, (struct rtattr*)(r+1), + parse_rtattr(tb, INET_DIAG_MAX, (struct rtattr*)(r+1), nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*r))); - if (tb[TCPDIAG_MEMINFO]) { - const struct tcpdiag_meminfo *minfo - = RTA_DATA(tb[TCPDIAG_MEMINFO]); + if (tb[INET_DIAG_MEMINFO]) { + const struct inet_diag_meminfo *minfo + = RTA_DATA(tb[INET_DIAG_MEMINFO]); printf(" mem:(r%u,w%u,f%u,t%u)", - minfo->tcpdiag_rmem, - minfo->tcpdiag_wmem, - minfo->tcpdiag_fmem, - minfo->tcpdiag_tmem); + minfo->idiag_rmem, + minfo->idiag_wmem, + minfo->idiag_fmem, + minfo->idiag_tmem); } - if (tb[TCPDIAG_INFO]) { + if (tb[INET_DIAG_INFO]) { struct tcp_info *info; - int len = RTA_PAYLOAD(tb[TCPDIAG_INFO]); + int len = RTA_PAYLOAD(tb[INET_DIAG_INFO]); /* workaround for older kernels with less fields */ if (len < sizeof(*info)) { info = alloca(sizeof(*info)); memset(info, 0, sizeof(*info)); - memcpy(info, RTA_DATA(tb[TCPDIAG_INFO]), len); + memcpy(info, RTA_DATA(tb[INET_DIAG_INFO]), len); } else - info = RTA_DATA(tb[TCPDIAG_INFO]); + info = RTA_DATA(tb[INET_DIAG_INFO]); if (show_options) { if (info->tcpi_options & TCPI_OPT_TIMESTAMPS) @@ -1339,8 +1341,8 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct tcpdiagmsg *r) printf(" ecn"); } - if (tb[TCPDIAG_CONG]) - printf("%s", (char *) RTA_DATA(tb[TCPDIAG_CONG])); + if (tb[INET_DIAG_CONG]) + printf("%s", (char *) RTA_DATA(tb[INET_DIAG_CONG])); if (info->tcpi_options & TCPI_OPT_WSCALE) printf(" wscale:%d,%d", info->tcpi_snd_wscale, @@ -1358,9 +1360,9 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct tcpdiagmsg *r) printf(" ssthresh:%d", info->tcpi_snd_ssthresh); rtt = (double) info->tcpi_rtt; - if (tb[TCPDIAG_VEGASINFO]) { + if (tb[INET_DIAG_VEGASINFO]) { const struct tcpvegas_info *vinfo - = RTA_DATA(tb[TCPDIAG_VEGASINFO]); + = RTA_DATA(tb[INET_DIAG_VEGASINFO]); if (vinfo->tcpv_enabled && vinfo->tcpv_rtt && vinfo->tcpv_rtt != 0x7fffffff) @@ -1384,20 +1386,20 @@ static void tcp_show_info(const struct nlmsghdr *nlh, struct tcpdiagmsg *r) int tcp_show_sock(struct nlmsghdr *nlh, struct filter *f) { - struct tcpdiagmsg *r = NLMSG_DATA(nlh); + struct inet_diag_msg *r = NLMSG_DATA(nlh); struct tcpstat s; - s.state = r->tcpdiag_state; - s.local.family = s.remote.family = r->tcpdiag_family; - s.lport = ntohs(r->id.tcpdiag_sport); - s.rport = ntohs(r->id.tcpdiag_dport); + s.state = r->idiag_state; + s.local.family = s.remote.family = r->idiag_family; + s.lport = ntohs(r->id.idiag_sport); + s.rport = ntohs(r->id.idiag_dport); if (s.local.family == AF_INET) { s.local.bytelen = s.remote.bytelen = 4; } else { s.local.bytelen = s.remote.bytelen = 16; } - memcpy(s.local.data, r->id.tcpdiag_src, s.local.bytelen); - memcpy(s.remote.data, r->id.tcpdiag_dst, s.local.bytelen); + memcpy(s.local.data, r->id.idiag_src, s.local.bytelen); + memcpy(s.remote.data, r->id.idiag_dst, s.local.bytelen); if (f && f->f && run_ssfilter(f->f, &s) == 0) return 0; @@ -1407,33 +1409,33 @@ int tcp_show_sock(struct nlmsghdr *nlh, struct filter *f) if (state_width) printf("%-*s ", state_width, sstate_name[s.state]); - printf("%-6d %-6d ", r->tcpdiag_rqueue, r->tcpdiag_wqueue); + printf("%-6d %-6d ", r->idiag_rqueue, r->idiag_wqueue); formatted_print(&s.local, s.lport); formatted_print(&s.remote, s.rport); if (show_options) { - if (r->tcpdiag_timer) { - if (r->tcpdiag_timer > 4) - r->tcpdiag_timer = 5; + if (r->idiag_timer) { + if (r->idiag_timer > 4) + r->idiag_timer = 5; printf(" timer:(%s,%s,%d)", - tmr_name[r->tcpdiag_timer], - print_ms_timer(r->tcpdiag_expires), - r->tcpdiag_retrans); + tmr_name[r->idiag_timer], + print_ms_timer(r->idiag_expires), + r->idiag_retrans); } } if (show_users) { char ubuf[4096]; - if (find_users(r->tcpdiag_inode, ubuf, sizeof(ubuf)) > 0) + if (find_users(r->idiag_inode, ubuf, sizeof(ubuf)) > 0) printf(" users:(%s)", ubuf); } if (show_details) { - if (r->tcpdiag_uid) - printf(" uid:%u", (unsigned)r->tcpdiag_uid); - printf(" ino:%u", (unsigned)r->tcpdiag_inode); - printf(" sk:%08x", r->id.tcpdiag_cookie[0]); - if (r->id.tcpdiag_cookie[1] != 0) - printf("%08x", r->id.tcpdiag_cookie[1]); + if (r->idiag_uid) + printf(" uid:%u", (unsigned)r->idiag_uid); + printf(" ino:%u", (unsigned)r->idiag_inode); + printf(" sk:%08x", r->id.idiag_cookie[0]); + if (r->id.idiag_cookie[1] != 0) + printf("%08x", r->id.idiag_cookie[1]); } if (show_mem || show_tcpinfo) { printf("\n\t"); @@ -1445,13 +1447,13 @@ int tcp_show_sock(struct nlmsghdr *nlh, struct filter *f) return 0; } -int tcp_show_netlink(struct filter *f, FILE *dump_fp) +int tcp_show_netlink(struct filter *f, FILE *dump_fp, int socktype) { int fd; struct sockaddr_nl nladdr; struct { struct nlmsghdr nlh; - struct tcpdiagreq r; + struct inet_diag_req r; } req; char *bc = NULL; int bclen; @@ -1460,27 +1462,27 @@ int tcp_show_netlink(struct filter *f, FILE *dump_fp) char buf[8192]; struct iovec iov[3]; - if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_TCPDIAG)) < 0) + if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG)) < 0) return -1; memset(&nladdr, 0, sizeof(nladdr)); nladdr.nl_family = AF_NETLINK; req.nlh.nlmsg_len = sizeof(req); - req.nlh.nlmsg_type = TCPDIAG_GETSOCK; + req.nlh.nlmsg_type = socktype; req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST; req.nlh.nlmsg_pid = 0; req.nlh.nlmsg_seq = 123456; memset(&req.r, 0, sizeof(req.r)); - req.r.tcpdiag_family = AF_INET; - req.r.tcpdiag_states = f->states; + req.r.idiag_family = AF_INET; + req.r.idiag_states = f->states; if (show_mem) - req.r.tcpdiag_ext |= (1<<(TCPDIAG_MEMINFO-1)); + req.r.idiag_ext |= (1<<(INET_DIAG_MEMINFO-1)); if (show_tcpinfo) { - req.r.tcpdiag_ext |= (1<<(TCPDIAG_INFO-1)); - req.r.tcpdiag_ext |= (1<<(TCPDIAG_VEGASINFO-1)); - req.r.tcpdiag_ext |= (1<<(TCPDIAG_CONG-1)); + req.r.idiag_ext |= (1<<(INET_DIAG_INFO-1)); + req.r.idiag_ext |= (1<<(INET_DIAG_VEGASINFO-1)); + req.r.idiag_ext |= (1<<(INET_DIAG_CONG-1)); } iov[0] = (struct iovec){ @@ -1489,7 +1491,7 @@ int tcp_show_netlink(struct filter *f, FILE *dump_fp) }; if (f->f) { bclen = ssfilter_bytecompile(f->f, &bc); - rta.rta_type = TCPDIAG_REQ_BYTECODE; + rta.rta_type = INET_DIAG_REQ_BYTECODE; rta.rta_len = RTA_LENGTH(bclen); iov[1] = (struct iovec){ &rta, sizeof(rta) }; iov[2] = (struct iovec){ bc, bclen }; @@ -1635,7 +1637,7 @@ int tcp_show_netlink_file(struct filter *f) } } -int tcp_show(struct filter *f) +int tcp_show(struct filter *f, int socktype) { int fd = -1; char *buf = NULL; @@ -1647,7 +1649,7 @@ int tcp_show(struct filter *f) return tcp_show_netlink_file(f); if (!getenv("PROC_NET_TCP") && !getenv("PROC_ROOT") - && tcp_show_netlink(f, NULL) == 0) + && tcp_show_netlink(f, NULL, socktype) == 0) return 0; /* Sigh... We have to parse /proc/net/tcp... */ @@ -2389,6 +2391,7 @@ static void usage(void) " -0, --packet display PACKET sockets\n" " -t, --tcp display only TCP sockets\n" " -u, --udp display only UDP sockets\n" +" -d, --dccp display only DCCP sockets\n" " -w, --raw display only RAW sockets\n" " -x, --unix display only Unix domain sockets\n" " -f, --family=FAMILY display sockets of type FAMILY\n" @@ -2438,6 +2441,7 @@ static const struct option long_opts[] = { { "memory", 0, 0, 'm' }, { "info", 0, 0, 'i' }, { "processes", 0, 0, 'p' }, + { "dccp", 0, 0, 'd' }, { "tcp", 0, 0, 't' }, { "udp", 0, 0, 'u' }, { "raw", 0, 0, 'w' }, @@ -2472,7 +2476,7 @@ int main(int argc, char *argv[]) current_filter.states = default_filter.states; - while ((ch = getopt_long(argc, argv, "haletuwxnro460spf:miA:D:F:vV", + while ((ch = getopt_long(argc, argv, "dhaletuwxnro460spf:miA:D:F:vV", long_opts, NULL)) != EOF) { switch(ch) { case 'n': @@ -2497,6 +2501,10 @@ int main(int argc, char *argv[]) case 'p': show_users++; break; + case 'd': + current_filter.dbs |= (1<= (maxargs - 1)) { - fprintf(stderr, "Too many arguments to command\n"); - exit(1); - } - argv[argc++] = cp; - } - argv[argc] = NULL; - - return argc; -} - -static int lineno; -/* Like glibc getline but handle continuation lines and comments */ -static size_t getcmdline(char **linep, size_t *lenp, FILE *in) -{ - size_t cc; - char *cp; - - if ((cc = getline(linep, lenp, in)) < 0) - return cc; /* eof or error */ - ++lineno; - - cp = strchr(*linep, '#'); - if (cp) - *cp = '\0'; - - while ((cp = strstr(*linep, "\\\n")) != NULL) { - char *line1 = NULL; - size_t len1 = 0; - size_t cc1; - - if ((cc1 = getline(&line1, &len1, in)) < 0) { - fprintf(stderr, "Missing continuation line\n"); - return cc1; - } - - ++lineno; - *cp = 0; - - cp = strchr(line1, '#'); - if (cp) - *cp = '\0'; - - *linep = realloc(*linep, strlen(*linep) + strlen(line1) + 1); - if (!*linep) { - fprintf(stderr, "Out of memory\n"); - return -1; - } - cc += cc1 - 2; - strcat(*linep, line1); - free(line1); - } - return cc; -} - static int batch(const char *name) { char *line = NULL; @@ -292,7 +229,7 @@ static int batch(const char *name) return -1; } - lineno = 0; + cmdlineno = 0; while (getcmdline(&line, &len, stdin) != -1) { char *largv[100]; int largc; @@ -302,7 +239,7 @@ static int batch(const char *name) continue; /* blank line */ if (do_cmd(largc, largv)) { - fprintf(stderr, "Command failed %s:%d\n", name, lineno); + fprintf(stderr, "Command failed %s:%d\n", name, cmdlineno); ret = 1; if (!force) break;