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