144d362409d5469aed47d19e7908d19bd194493aThomas Graf/*
244d362409d5469aed47d19e7908d19bd194493aThomas Graf * src/nl-monitor.c     Monitor events
344d362409d5469aed47d19e7908d19bd194493aThomas Graf *
444d362409d5469aed47d19e7908d19bd194493aThomas Graf *	This library is free software; you can redistribute it and/or
544d362409d5469aed47d19e7908d19bd194493aThomas Graf *	modify it under the terms of the GNU Lesser General Public
644d362409d5469aed47d19e7908d19bd194493aThomas Graf *	License as published by the Free Software Foundation version 2.1
744d362409d5469aed47d19e7908d19bd194493aThomas Graf *	of the License.
844d362409d5469aed47d19e7908d19bd194493aThomas Graf *
98808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch>
1044d362409d5469aed47d19e7908d19bd194493aThomas Graf */
1144d362409d5469aed47d19e7908d19bd194493aThomas Graf
128808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf#include <netlink/cli/utils.h>
138808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf#include <netlink/cli/link.h>
1444d362409d5469aed47d19e7908d19bd194493aThomas Graf
1544d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void obj_input(struct nl_object *obj, void *arg)
1644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
1744d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nl_dump_params dp = {
1844d362409d5469aed47d19e7908d19bd194493aThomas Graf		.dp_type = NL_DUMP_STATS,
1944d362409d5469aed47d19e7908d19bd194493aThomas Graf		.dp_fd = stdout,
2044d362409d5469aed47d19e7908d19bd194493aThomas Graf		.dp_dump_msgtype = 1,
2144d362409d5469aed47d19e7908d19bd194493aThomas Graf	};
2244d362409d5469aed47d19e7908d19bd194493aThomas Graf
2344d362409d5469aed47d19e7908d19bd194493aThomas Graf	nl_object_dump(obj, &dp);
2444d362409d5469aed47d19e7908d19bd194493aThomas Graf}
2544d362409d5469aed47d19e7908d19bd194493aThomas Graf
2644d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int event_input(struct nl_msg *msg, void *arg)
2744d362409d5469aed47d19e7908d19bd194493aThomas Graf{
2844d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (nl_msg_parse(msg, &obj_input, NULL) < 0)
2944d362409d5469aed47d19e7908d19bd194493aThomas Graf		fprintf(stderr, "<<EVENT>> Unknown message type\n");
3044d362409d5469aed47d19e7908d19bd194493aThomas Graf
3144d362409d5469aed47d19e7908d19bd194493aThomas Graf	/* Exit nl_recvmsgs_def() and return to the main select() */
3244d362409d5469aed47d19e7908d19bd194493aThomas Graf	return NL_STOP;
3344d362409d5469aed47d19e7908d19bd194493aThomas Graf}
3444d362409d5469aed47d19e7908d19bd194493aThomas Graf
3544d362409d5469aed47d19e7908d19bd194493aThomas Grafint main(int argc, char *argv[])
3644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
3710cf5a586c149fdb7e2639000dbfae5e6f8522a5Thomas Graf	struct nl_sock *sock;
3844d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nl_cache *link_cache;
3944d362409d5469aed47d19e7908d19bd194493aThomas Graf	int err = 1;
4044d362409d5469aed47d19e7908d19bd194493aThomas Graf	int i, idx;
4144d362409d5469aed47d19e7908d19bd194493aThomas Graf
4244d362409d5469aed47d19e7908d19bd194493aThomas Graf	static const struct {
4344d362409d5469aed47d19e7908d19bd194493aThomas Graf		enum rtnetlink_groups gr_id;
4444d362409d5469aed47d19e7908d19bd194493aThomas Graf		const char* gr_name;
4544d362409d5469aed47d19e7908d19bd194493aThomas Graf	} known_groups[] = {
4644d362409d5469aed47d19e7908d19bd194493aThomas Graf		{ RTNLGRP_LINK, "link" },
4744d362409d5469aed47d19e7908d19bd194493aThomas Graf		{ RTNLGRP_NOTIFY, "notify" },
4844d362409d5469aed47d19e7908d19bd194493aThomas Graf		{ RTNLGRP_NEIGH, "neigh" },
4944d362409d5469aed47d19e7908d19bd194493aThomas Graf		{ RTNLGRP_TC, "tc" },
5044d362409d5469aed47d19e7908d19bd194493aThomas Graf		{ RTNLGRP_IPV4_IFADDR, "ipv4-ifaddr" },
5144d362409d5469aed47d19e7908d19bd194493aThomas Graf		{ RTNLGRP_IPV4_MROUTE, "ipv4-mroute" },
5244d362409d5469aed47d19e7908d19bd194493aThomas Graf		{ RTNLGRP_IPV4_ROUTE, "ipv4-route" },
5344d362409d5469aed47d19e7908d19bd194493aThomas Graf		{ RTNLGRP_IPV6_IFADDR, "ipv6-ifaddr" },
5444d362409d5469aed47d19e7908d19bd194493aThomas Graf		{ RTNLGRP_IPV6_MROUTE, "ipv6-mroute" },
5544d362409d5469aed47d19e7908d19bd194493aThomas Graf		{ RTNLGRP_IPV6_ROUTE, "ipv6-route" },
5644d362409d5469aed47d19e7908d19bd194493aThomas Graf		{ RTNLGRP_IPV6_IFINFO, "ipv6-ifinfo" },
5744d362409d5469aed47d19e7908d19bd194493aThomas Graf		{ RTNLGRP_DECnet_IFADDR, "decnet-ifaddr" },
5844d362409d5469aed47d19e7908d19bd194493aThomas Graf		{ RTNLGRP_DECnet_ROUTE, "decnet-route" },
5944d362409d5469aed47d19e7908d19bd194493aThomas Graf		{ RTNLGRP_IPV6_PREFIX, "ipv6-prefix" },
6044d362409d5469aed47d19e7908d19bd194493aThomas Graf		{ RTNLGRP_NONE, NULL }
6144d362409d5469aed47d19e7908d19bd194493aThomas Graf	};
6244d362409d5469aed47d19e7908d19bd194493aThomas Graf
638808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf	sock = nl_cli_alloc_socket();
64f9071054d0f2512dea9e95f99c308e931ed78dbaPatrick McHardy	nl_socket_disable_seq_check(sock);
6510cf5a586c149fdb7e2639000dbfae5e6f8522a5Thomas Graf	nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, event_input, NULL);
6644d362409d5469aed47d19e7908d19bd194493aThomas Graf
6744d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (argc > 1 && !strcasecmp(argv[1], "-h")) {
6844d362409d5469aed47d19e7908d19bd194493aThomas Graf		printf("Usage: nl-monitor [<groups>]\n");
6944d362409d5469aed47d19e7908d19bd194493aThomas Graf
7044d362409d5469aed47d19e7908d19bd194493aThomas Graf		printf("Known groups:");
7144d362409d5469aed47d19e7908d19bd194493aThomas Graf		for (i = 0; known_groups[i].gr_id != RTNLGRP_NONE; i++)
7244d362409d5469aed47d19e7908d19bd194493aThomas Graf			printf(" %s", known_groups[i].gr_name);
7344d362409d5469aed47d19e7908d19bd194493aThomas Graf		printf("\n");
7444d362409d5469aed47d19e7908d19bd194493aThomas Graf		return 2;
7544d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
7644d362409d5469aed47d19e7908d19bd194493aThomas Graf
778808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf	nl_cli_connect(sock, NETLINK_ROUTE);
7844d362409d5469aed47d19e7908d19bd194493aThomas Graf
7944d362409d5469aed47d19e7908d19bd194493aThomas Graf	for (idx = 1; argc > idx; idx++) {
8044d362409d5469aed47d19e7908d19bd194493aThomas Graf		for (i = 0; known_groups[i].gr_id != RTNLGRP_NONE; i++) {
8144d362409d5469aed47d19e7908d19bd194493aThomas Graf			if (!strcmp(argv[idx], known_groups[i].gr_name)) {
8244d362409d5469aed47d19e7908d19bd194493aThomas Graf
8310cf5a586c149fdb7e2639000dbfae5e6f8522a5Thomas Graf				if ((err = nl_socket_add_membership(sock, known_groups[i].gr_id)) < 0) {
848808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf					nl_cli_fatal(err, "%s: %s\n", argv[idx],
858808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf						     nl_geterror(err));
8644d362409d5469aed47d19e7908d19bd194493aThomas Graf				}
8744d362409d5469aed47d19e7908d19bd194493aThomas Graf
8844d362409d5469aed47d19e7908d19bd194493aThomas Graf				break;
8944d362409d5469aed47d19e7908d19bd194493aThomas Graf			}
9044d362409d5469aed47d19e7908d19bd194493aThomas Graf		}
9144d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (known_groups[i].gr_id == RTNLGRP_NONE)
9244d362409d5469aed47d19e7908d19bd194493aThomas Graf			fprintf(stderr, "Warning: Unknown group: %s\n", argv[idx]);
9344d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
9444d362409d5469aed47d19e7908d19bd194493aThomas Graf
958808743839b0f459394ecd00cb0f7c1896c0ab7aThomas Graf	link_cache = nl_cli_link_alloc_cache(sock);
9644d362409d5469aed47d19e7908d19bd194493aThomas Graf
9744d362409d5469aed47d19e7908d19bd194493aThomas Graf	while (1) {
9844d362409d5469aed47d19e7908d19bd194493aThomas Graf		fd_set rfds;
9944d362409d5469aed47d19e7908d19bd194493aThomas Graf		int fd, retval;
10044d362409d5469aed47d19e7908d19bd194493aThomas Graf
10110cf5a586c149fdb7e2639000dbfae5e6f8522a5Thomas Graf		fd = nl_socket_get_fd(sock);
10244d362409d5469aed47d19e7908d19bd194493aThomas Graf
10344d362409d5469aed47d19e7908d19bd194493aThomas Graf		FD_ZERO(&rfds);
10444d362409d5469aed47d19e7908d19bd194493aThomas Graf		FD_SET(fd, &rfds);
10544d362409d5469aed47d19e7908d19bd194493aThomas Graf		/* wait for an incoming message on the netlink socket */
10644d362409d5469aed47d19e7908d19bd194493aThomas Graf		retval = select(fd+1, &rfds, NULL, NULL, NULL);
10744d362409d5469aed47d19e7908d19bd194493aThomas Graf
10844d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (retval) {
10944d362409d5469aed47d19e7908d19bd194493aThomas Graf			/* FD_ISSET(fd, &rfds) will be true */
11010cf5a586c149fdb7e2639000dbfae5e6f8522a5Thomas Graf			nl_recvmsgs_default(sock);
11144d362409d5469aed47d19e7908d19bd194493aThomas Graf		}
11244d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
11344d362409d5469aed47d19e7908d19bd194493aThomas Graf
11410cf5a586c149fdb7e2639000dbfae5e6f8522a5Thomas Graf	return 0;
11544d362409d5469aed47d19e7908d19bd194493aThomas Graf}
116