Home | History | Annotate | Download | only in ip
      1 /*
      2  * ipmonitor.c		"ip monitor".
      3  *
      4  *		This program is free software; you can redistribute it and/or
      5  *		modify it under the terms of the GNU General Public License
      6  *		as published by the Free Software Foundation; either version
      7  *		2 of the License, or (at your option) any later version.
      8  *
      9  * Authors:	Alexey Kuznetsov, <kuznet (at) ms2.inr.ac.ru>
     10  *
     11  */
     12 
     13 #include <stdio.h>
     14 #include <stdlib.h>
     15 #include <unistd.h>
     16 #include <syslog.h>
     17 #include <fcntl.h>
     18 #include <sys/socket.h>
     19 #include <netinet/in.h>
     20 #include <arpa/inet.h>
     21 #include <string.h>
     22 #include <time.h>
     23 
     24 #include "utils.h"
     25 #include "ip_common.h"
     26 
     27 static void usage(void) __attribute__((noreturn));
     28 int prefix_banner;
     29 
     30 static void usage(void)
     31 {
     32 	fprintf(stderr, "Usage: ip monitor [ all | LISTofOBJECTS ]\n");
     33 	exit(-1);
     34 }
     35 
     36 
     37 int accept_msg(const struct sockaddr_nl *who,
     38 	       struct nlmsghdr *n, void *arg)
     39 {
     40 	FILE *fp = (FILE*)arg;
     41 
     42 	if (timestamp)
     43 		print_timestamp(fp);
     44 
     45 	if (n->nlmsg_type == RTM_NEWROUTE || n->nlmsg_type == RTM_DELROUTE) {
     46 		if (prefix_banner)
     47 			fprintf(fp, "[ROUTE]");
     48 		print_route(who, n, arg);
     49 		return 0;
     50 	}
     51 	if (n->nlmsg_type == RTM_NEWLINK || n->nlmsg_type == RTM_DELLINK) {
     52 		ll_remember_index(who, n, NULL);
     53 		if (prefix_banner)
     54 			fprintf(fp, "[LINK]");
     55 		print_linkinfo(who, n, arg);
     56 		return 0;
     57 	}
     58 	if (n->nlmsg_type == RTM_NEWADDR || n->nlmsg_type == RTM_DELADDR) {
     59 		if (prefix_banner)
     60 			fprintf(fp, "[ADDR]");
     61 		print_addrinfo(who, n, arg);
     62 		return 0;
     63 	}
     64 	if (n->nlmsg_type == RTM_NEWADDRLABEL || n->nlmsg_type == RTM_DELADDRLABEL) {
     65 		if (prefix_banner)
     66 			fprintf(fp, "[ADDRLABEL]");
     67 		print_addrlabel(who, n, arg);
     68 		return 0;
     69 	}
     70 	if (n->nlmsg_type == RTM_NEWNEIGH || n->nlmsg_type == RTM_DELNEIGH) {
     71 		if (prefix_banner)
     72 			fprintf(fp, "[NEIGH]");
     73 		print_neigh(who, n, arg);
     74 		return 0;
     75 	}
     76 	if (n->nlmsg_type == RTM_NEWPREFIX) {
     77 		if (prefix_banner)
     78 			fprintf(fp, "[PREFIX]");
     79 		print_prefix(who, n, arg);
     80 		return 0;
     81 	}
     82 	if (n->nlmsg_type == RTM_NEWRULE || n->nlmsg_type == RTM_DELRULE) {
     83 		if (prefix_banner)
     84 			fprintf(fp, "[RULE]");
     85 		print_rule(who, n, arg);
     86 		return 0;
     87 	}
     88 	if (n->nlmsg_type == 15) {
     89 		char *tstr;
     90 		time_t secs = ((__u32*)NLMSG_DATA(n))[0];
     91 		long usecs = ((__u32*)NLMSG_DATA(n))[1];
     92 		tstr = asctime(localtime(&secs));
     93 		tstr[strlen(tstr)-1] = 0;
     94 		fprintf(fp, "Timestamp: %s %lu us\n", tstr, usecs);
     95 		return 0;
     96 	}
     97 	if (n->nlmsg_type == RTM_NEWQDISC ||
     98 	    n->nlmsg_type == RTM_DELQDISC ||
     99 	    n->nlmsg_type == RTM_NEWTCLASS ||
    100 	    n->nlmsg_type == RTM_DELTCLASS ||
    101 	    n->nlmsg_type == RTM_NEWTFILTER ||
    102 	    n->nlmsg_type == RTM_DELTFILTER)
    103 		return 0;
    104 	if (n->nlmsg_type != NLMSG_ERROR && n->nlmsg_type != NLMSG_NOOP &&
    105 	    n->nlmsg_type != NLMSG_DONE) {
    106 		fprintf(fp, "Unknown message: %08x %08x %08x\n",
    107 			n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
    108 	}
    109 	return 0;
    110 }
    111 
    112 int do_ipmonitor(int argc, char **argv)
    113 {
    114 	char *file = NULL;
    115 	unsigned groups = ~RTMGRP_TC;
    116 	int llink=0;
    117 	int laddr=0;
    118 	int lroute=0;
    119 	int lprefix=0;
    120 	int lneigh=0;
    121 
    122 	rtnl_close(&rth);
    123 	ipaddr_reset_filter(1);
    124 	iproute_reset_filter();
    125 	ipneigh_reset_filter();
    126 
    127 	while (argc > 0) {
    128 		if (matches(*argv, "file") == 0) {
    129 			NEXT_ARG();
    130 			file = *argv;
    131 		} else if (matches(*argv, "link") == 0) {
    132 			llink=1;
    133 			groups = 0;
    134 		} else if (matches(*argv, "address") == 0) {
    135 			laddr=1;
    136 			groups = 0;
    137 		} else if (matches(*argv, "route") == 0) {
    138 			lroute=1;
    139 			groups = 0;
    140 		} else if (matches(*argv, "prefix") == 0) {
    141 			lprefix=1;
    142 			groups = 0;
    143 		} else if (matches(*argv, "neigh") == 0) {
    144 			lneigh = 1;
    145 			groups = 0;
    146 		} else if (strcmp(*argv, "all") == 0) {
    147 			groups = ~RTMGRP_TC;
    148 			prefix_banner=1;
    149 		} else if (matches(*argv, "help") == 0) {
    150 			usage();
    151 		} else {
    152 			fprintf(stderr, "Argument \"%s\" is unknown, try \"ip monitor help\".\n", *argv);
    153 			exit(-1);
    154 		}
    155 		argc--;	argv++;
    156 	}
    157 
    158 	if (llink)
    159 		groups |= nl_mgrp(RTNLGRP_LINK);
    160 	if (laddr) {
    161 		if (!preferred_family || preferred_family == AF_INET)
    162 			groups |= nl_mgrp(RTNLGRP_IPV4_IFADDR);
    163 		if (!preferred_family || preferred_family == AF_INET6)
    164 			groups |= nl_mgrp(RTNLGRP_IPV6_IFADDR);
    165 	}
    166 	if (lroute) {
    167 		if (!preferred_family || preferred_family == AF_INET)
    168 			groups |= nl_mgrp(RTNLGRP_IPV4_ROUTE);
    169 		if (!preferred_family || preferred_family == AF_INET6)
    170 			groups |= nl_mgrp(RTNLGRP_IPV6_ROUTE);
    171 	}
    172 	if (lprefix) {
    173 		if (!preferred_family || preferred_family == AF_INET6)
    174 			groups |= nl_mgrp(RTNLGRP_IPV6_PREFIX);
    175 	}
    176 	if (lneigh) {
    177 		groups |= nl_mgrp(RTNLGRP_NEIGH);
    178 	}
    179 	if (file) {
    180 		FILE *fp;
    181 		fp = fopen(file, "r");
    182 		if (fp == NULL) {
    183 			perror("Cannot fopen");
    184 			exit(-1);
    185 		}
    186 		return rtnl_from_file(fp, accept_msg, stdout);
    187 	}
    188 
    189 	if (rtnl_open(&rth, groups) < 0)
    190 		exit(1);
    191 	ll_init_map(&rth);
    192 
    193 	if (rtnl_listen(&rth, accept_msg, stdout) < 0)
    194 		exit(2);
    195 
    196 	return 0;
    197 }
    198