1dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat/* 2dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * rtmon.c RTnetlink listener. 3dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * 4dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * This program is free software; you can redistribute it and/or 5dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * modify it under the terms of the GNU General Public License 6dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * as published by the Free Software Foundation; either version 7dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * 2 of the License, or (at your option) any later version. 8dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * 9dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> 10dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * 11dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat */ 12dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 13dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <stdio.h> 14dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <stdlib.h> 15dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <unistd.h> 16dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <syslog.h> 17dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <fcntl.h> 18dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <sys/socket.h> 19dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <sys/time.h> 20dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <netinet/in.h> 21dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <string.h> 22dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 23dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include "SNAPSHOT.h" 24dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 25dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include "utils.h" 26dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include "libnetlink.h" 27dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 28dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint resolve_hosts = 0; 29dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int init_phase = 1; 30dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 31dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic void write_stamp(FILE *fp) 32dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 33dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat char buf[128]; 34dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct nlmsghdr *n1 = (void*)buf; 35dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct timeval tv; 36dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 37dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat n1->nlmsg_type = 15; 38dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat n1->nlmsg_flags = 0; 39dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat n1->nlmsg_seq = 0; 40dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat n1->nlmsg_pid = 0; 41dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat n1->nlmsg_len = NLMSG_LENGTH(4*2); 42dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat gettimeofday(&tv, NULL); 43dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat ((__u32*)NLMSG_DATA(n1))[0] = tv.tv_sec; 44dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat ((__u32*)NLMSG_DATA(n1))[1] = tv.tv_usec; 45dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fwrite((void*)n1, 1, NLMSG_ALIGN(n1->nlmsg_len), fp); 46dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 47dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 48dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int dump_msg(const struct sockaddr_nl *who, struct nlmsghdr *n, 49dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat void *arg) 50dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 51dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat FILE *fp = (FILE*)arg; 52dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (!init_phase) 53dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat write_stamp(fp); 54dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fwrite((void*)n, 1, NLMSG_ALIGN(n->nlmsg_len), fp); 55dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fflush(fp); 56dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 57dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 58dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 59dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatvoid usage(void) 60dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 61dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Usage: rtmon file FILE [ all | LISTofOBJECTS]\n"); 62dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "LISTofOBJECTS := [ link ] [ address ] [ route ]\n"); 63dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat exit(-1); 64dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 65dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 66dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint 67dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatmain(int argc, char **argv) 68dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 69dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat FILE *fp; 70dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct rtnl_handle rth; 71dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int family = AF_UNSPEC; 72dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat unsigned groups = ~0U; 73dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int llink = 0; 74dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int laddr = 0; 75dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int lroute = 0; 76dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat char *file = NULL; 77dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 78dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat while (argc > 1) { 79dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (matches(argv[1], "-family") == 0) { 80dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat argc--; 81dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat argv++; 82dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (argc <= 1) 83dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat usage(); 84dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (strcmp(argv[1], "inet") == 0) 85dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat family = AF_INET; 86dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat else if (strcmp(argv[1], "inet6") == 0) 87dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat family = AF_INET6; 88dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat else if (strcmp(argv[1], "link") == 0) 89dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat family = AF_INET6; 90dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat else if (strcmp(argv[1], "help") == 0) 91dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat usage(); 92dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat else { 93dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Protocol ID \"%s\" is unknown, try \"rtmon help\".\n", argv[1]); 94dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat exit(-1); 95dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 96dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (strcmp(argv[1], "-4") == 0) { 97dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat family = AF_INET; 98dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (strcmp(argv[1], "-6") == 0) { 99dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat family = AF_INET6; 100dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (strcmp(argv[1], "-0") == 0) { 101dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat family = AF_PACKET; 102dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (matches(argv[1], "-Version") == 0) { 103dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat printf("rtmon utility, iproute2-ss%s\n", SNAPSHOT); 104dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat exit(0); 105dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (matches(argv[1], "file") == 0) { 106dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat argc--; 107dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat argv++; 108dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (argc <= 1) 109dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat usage(); 110dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat file = argv[1]; 111dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (matches(argv[1], "link") == 0) { 112dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat llink=1; 113dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat groups = 0; 114dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (matches(argv[1], "address") == 0) { 115dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat laddr=1; 116dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat groups = 0; 117dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (matches(argv[1], "route") == 0) { 118dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat lroute=1; 119dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat groups = 0; 120dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (strcmp(argv[1], "all") == 0) { 121dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat groups = ~0U; 122dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (matches(argv[1], "help") == 0) { 123dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat usage(); 124dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else { 125dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Argument \"%s\" is unknown, try \"rtmon help\".\n", argv[1]); 126dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat exit(-1); 127dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 128dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat argc--; argv++; 129dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 130dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 131dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (file == NULL) { 132dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Not enough information: argument \"file\" is required\n"); 133dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat exit(-1); 134dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 135dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (llink) 136dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat groups |= nl_mgrp(RTNLGRP_LINK); 137dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (laddr) { 138dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (!family || family == AF_INET) 139dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat groups |= nl_mgrp(RTNLGRP_IPV4_IFADDR); 140dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (!family || family == AF_INET6) 141dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat groups |= nl_mgrp(RTNLGRP_IPV6_IFADDR); 142dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 143dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (lroute) { 144dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (!family || family == AF_INET) 145dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat groups |= nl_mgrp(RTNLGRP_IPV4_ROUTE); 146dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (!family || family == AF_INET6) 147dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat groups |= nl_mgrp(RTNLGRP_IPV6_ROUTE); 148dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 149dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 150dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fp = fopen(file, "w"); 151dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (fp == NULL) { 152dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat perror("Cannot fopen"); 153dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat exit(-1); 154dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 155dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 156dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (rtnl_open(&rth, groups) < 0) 157dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat exit(1); 158dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 159dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (rtnl_wilddump_request(&rth, AF_UNSPEC, RTM_GETLINK) < 0) { 160dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat perror("Cannot send dump request"); 161dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat exit(1); 162dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 163dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 164dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat write_stamp(fp); 165dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 166dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (rtnl_dump_filter(&rth, dump_msg, fp, NULL, NULL) < 0) { 167dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Dump terminated\n"); 168dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 1; 169dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 170dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 171dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat init_phase = 0; 172dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 173dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (rtnl_listen(&rth, dump_msg, (void*)fp) < 0) 174dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat exit(2); 175dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 176dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat exit(0); 177dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 178