1/* 2 * rtmon.c RTnetlink listener. 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 <sys/time.h> 20#include <netinet/in.h> 21#include <string.h> 22 23#include "SNAPSHOT.h" 24 25#include "utils.h" 26#include "libnetlink.h" 27 28int resolve_hosts = 0; 29static int init_phase = 1; 30 31static void write_stamp(FILE *fp) 32{ 33 char buf[128]; 34 struct nlmsghdr *n1 = (void*)buf; 35 struct timeval tv; 36 37 n1->nlmsg_type = NLMSG_TSTAMP; 38 n1->nlmsg_flags = 0; 39 n1->nlmsg_seq = 0; 40 n1->nlmsg_pid = 0; 41 n1->nlmsg_len = NLMSG_LENGTH(4*2); 42 gettimeofday(&tv, NULL); 43 ((__u32*)NLMSG_DATA(n1))[0] = tv.tv_sec; 44 ((__u32*)NLMSG_DATA(n1))[1] = tv.tv_usec; 45 fwrite((void*)n1, 1, NLMSG_ALIGN(n1->nlmsg_len), fp); 46} 47 48static int dump_msg(const struct sockaddr_nl *who, struct rtnl_ctrl_data *ctrl, 49 struct nlmsghdr *n, void *arg) 50{ 51 FILE *fp = (FILE*)arg; 52 if (!init_phase) 53 write_stamp(fp); 54 fwrite((void*)n, 1, NLMSG_ALIGN(n->nlmsg_len), fp); 55 fflush(fp); 56 return 0; 57} 58 59static int dump_msg2(const struct sockaddr_nl *who, 60 struct nlmsghdr *n, void *arg) 61{ 62 return dump_msg(who, NULL, n, arg); 63} 64 65static void usage(void) 66{ 67 fprintf(stderr, "Usage: rtmon file FILE [ all | LISTofOBJECTS]\n"); 68 fprintf(stderr, "LISTofOBJECTS := [ link ] [ address ] [ route ]\n"); 69 exit(-1); 70} 71 72int 73main(int argc, char **argv) 74{ 75 FILE *fp; 76 struct rtnl_handle rth; 77 int family = AF_UNSPEC; 78 unsigned groups = ~0U; 79 int llink = 0; 80 int laddr = 0; 81 int lroute = 0; 82 char *file = NULL; 83 84 while (argc > 1) { 85 if (matches(argv[1], "-family") == 0) { 86 argc--; 87 argv++; 88 if (argc <= 1) 89 usage(); 90 if (strcmp(argv[1], "inet") == 0) 91 family = AF_INET; 92 else if (strcmp(argv[1], "inet6") == 0) 93 family = AF_INET6; 94 else if (strcmp(argv[1], "link") == 0) 95 family = AF_INET6; 96 else if (strcmp(argv[1], "help") == 0) 97 usage(); 98 else { 99 fprintf(stderr, "Protocol ID \"%s\" is unknown, try \"rtmon help\".\n", argv[1]); 100 exit(-1); 101 } 102 } else if (strcmp(argv[1], "-4") == 0) { 103 family = AF_INET; 104 } else if (strcmp(argv[1], "-6") == 0) { 105 family = AF_INET6; 106 } else if (strcmp(argv[1], "-0") == 0) { 107 family = AF_PACKET; 108 } else if (matches(argv[1], "-Version") == 0) { 109 printf("rtmon utility, iproute2-ss%s\n", SNAPSHOT); 110 exit(0); 111 } else if (matches(argv[1], "file") == 0) { 112 argc--; 113 argv++; 114 if (argc <= 1) 115 usage(); 116 file = argv[1]; 117 } else if (matches(argv[1], "link") == 0) { 118 llink=1; 119 groups = 0; 120 } else if (matches(argv[1], "address") == 0) { 121 laddr=1; 122 groups = 0; 123 } else if (matches(argv[1], "route") == 0) { 124 lroute=1; 125 groups = 0; 126 } else if (strcmp(argv[1], "all") == 0) { 127 groups = ~0U; 128 } else if (matches(argv[1], "help") == 0) { 129 usage(); 130 } else { 131 fprintf(stderr, "Argument \"%s\" is unknown, try \"rtmon help\".\n", argv[1]); 132 exit(-1); 133 } 134 argc--; argv++; 135 } 136 137 if (file == NULL) { 138 fprintf(stderr, "Not enough information: argument \"file\" is required\n"); 139 exit(-1); 140 } 141 if (llink) 142 groups |= nl_mgrp(RTNLGRP_LINK); 143 if (laddr) { 144 if (!family || family == AF_INET) 145 groups |= nl_mgrp(RTNLGRP_IPV4_IFADDR); 146 if (!family || family == AF_INET6) 147 groups |= nl_mgrp(RTNLGRP_IPV6_IFADDR); 148 } 149 if (lroute) { 150 if (!family || family == AF_INET) 151 groups |= nl_mgrp(RTNLGRP_IPV4_ROUTE); 152 if (!family || family == AF_INET6) 153 groups |= nl_mgrp(RTNLGRP_IPV6_ROUTE); 154 } 155 156 fp = fopen(file, "w"); 157 if (fp == NULL) { 158 perror("Cannot fopen"); 159 exit(-1); 160 } 161 162 if (rtnl_open(&rth, groups) < 0) 163 exit(1); 164 165 if (rtnl_wilddump_request(&rth, AF_UNSPEC, RTM_GETLINK) < 0) { 166 perror("Cannot send dump request"); 167 exit(1); 168 } 169 170 write_stamp(fp); 171 172 if (rtnl_dump_filter(&rth, dump_msg2, fp) < 0) { 173 fprintf(stderr, "Dump terminated\n"); 174 return 1; 175 } 176 177 init_phase = 0; 178 179 if (rtnl_listen(&rth, dump_msg, (void*)fp) < 0) 180 exit(2); 181 182 exit(0); 183} 184