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