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@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 27static void usage(void) __attribute__((noreturn)); 28 29static void usage(void) 30{ 31 fprintf(stderr, "Usage: ip monitor [ all | LISTofOBJECTS ]\n"); 32 exit(-1); 33} 34 35 36int accept_msg(const struct sockaddr_nl *who, 37 struct nlmsghdr *n, void *arg) 38{ 39 FILE *fp = (FILE*)arg; 40 41 if (timestamp) 42 print_timestamp(fp); 43 44 if (n->nlmsg_type == RTM_NEWROUTE || n->nlmsg_type == RTM_DELROUTE) { 45 print_route(who, n, arg); 46 return 0; 47 } 48 if (n->nlmsg_type == RTM_NEWLINK || n->nlmsg_type == RTM_DELLINK) { 49 ll_remember_index(who, n, NULL); 50 print_linkinfo(who, n, arg); 51 return 0; 52 } 53 if (n->nlmsg_type == RTM_NEWADDR || n->nlmsg_type == RTM_DELADDR) { 54 print_addrinfo(who, n, arg); 55 return 0; 56 } 57 if (n->nlmsg_type == RTM_NEWNEIGH || n->nlmsg_type == RTM_DELNEIGH) { 58 print_neigh(who, n, arg); 59 return 0; 60 } 61 if (n->nlmsg_type == RTM_NEWPREFIX) { 62 print_prefix(who, n, arg); 63 return 0; 64 } 65 if (n->nlmsg_type == 15) { 66 char *tstr; 67 time_t secs = ((__u32*)NLMSG_DATA(n))[0]; 68 long usecs = ((__u32*)NLMSG_DATA(n))[1]; 69 tstr = asctime(localtime(&secs)); 70 tstr[strlen(tstr)-1] = 0; 71 fprintf(fp, "Timestamp: %s %lu us\n", tstr, usecs); 72 return 0; 73 } 74 if (n->nlmsg_type == RTM_NEWQDISC || 75 n->nlmsg_type == RTM_DELQDISC || 76 n->nlmsg_type == RTM_NEWTCLASS || 77 n->nlmsg_type == RTM_DELTCLASS || 78 n->nlmsg_type == RTM_NEWTFILTER || 79 n->nlmsg_type == RTM_DELTFILTER) 80 return 0; 81 if (n->nlmsg_type != NLMSG_ERROR && n->nlmsg_type != NLMSG_NOOP && 82 n->nlmsg_type != NLMSG_DONE) { 83 fprintf(fp, "Unknown message: %08x %08x %08x\n", 84 n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); 85 } 86 return 0; 87} 88 89int do_ipmonitor(int argc, char **argv) 90{ 91 char *file = NULL; 92 unsigned groups = ~RTMGRP_TC; 93 int llink=0; 94 int laddr=0; 95 int lroute=0; 96 int lprefix=0; 97 98 rtnl_close(&rth); 99 ipaddr_reset_filter(1); 100 iproute_reset_filter(); 101 ipneigh_reset_filter(); 102 103 while (argc > 0) { 104 if (matches(*argv, "file") == 0) { 105 NEXT_ARG(); 106 file = *argv; 107 } else if (matches(*argv, "link") == 0) { 108 llink=1; 109 groups = 0; 110 } else if (matches(*argv, "address") == 0) { 111 laddr=1; 112 groups = 0; 113 } else if (matches(*argv, "route") == 0) { 114 lroute=1; 115 groups = 0; 116 } else if (matches(*argv, "prefix") == 0) { 117 lprefix=1; 118 groups = 0; 119 } else if (strcmp(*argv, "all") == 0) { 120 groups = ~RTMGRP_TC; 121 } else if (matches(*argv, "help") == 0) { 122 usage(); 123 } else { 124 fprintf(stderr, "Argument \"%s\" is unknown, try \"ip monitor help\".\n", *argv); 125 exit(-1); 126 } 127 argc--; argv++; 128 } 129 130 if (llink) 131 groups |= RTMGRP_LINK; 132 if (laddr) { 133 if (!preferred_family || preferred_family == AF_INET) 134 groups |= RTMGRP_IPV4_IFADDR; 135 if (!preferred_family || preferred_family == AF_INET6) 136 groups |= RTMGRP_IPV6_IFADDR; 137 } 138 if (lroute) { 139 if (!preferred_family || preferred_family == AF_INET) 140 groups |= RTMGRP_IPV4_ROUTE; 141 if (!preferred_family || preferred_family == AF_INET6) 142 groups |= RTMGRP_IPV6_ROUTE; 143 } 144 if (lprefix) { 145 if (!preferred_family || preferred_family == AF_INET6) 146 groups |= RTMGRP_IPV6_PREFIX; 147 } 148 149 if (file) { 150 FILE *fp; 151 fp = fopen(file, "r"); 152 if (fp == NULL) { 153 perror("Cannot fopen"); 154 exit(-1); 155 } 156 return rtnl_from_file(fp, accept_msg, stdout); 157 } 158 159 if (rtnl_open(&rth, groups) < 0) 160 exit(1); 161 ll_init_map(&rth); 162 163 if (rtnl_listen(&rth, accept_msg, stdout) < 0) 164 exit(2); 165 166 return 0; 167} 168