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