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(struct sockaddr_nl *who, 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 59void usage(void) 60{ 61 fprintf(stderr, "Usage: rtmon file FILE [ all | LISTofOBJECTS]\n"); 62 fprintf(stderr, "LISTofOBJECTS := [ link ] [ address ] [ route ]\n"); 63 exit(-1); 64} 65 66int 67main(int argc, char **argv) 68{ 69 FILE *fp; 70 struct rtnl_handle rth; 71 int family = AF_UNSPEC; 72 unsigned groups = ~0U; 73 int llink = 0; 74 int laddr = 0; 75 int lroute = 0; 76 char *file = NULL; 77 78 while (argc > 1) { 79 if (matches(argv[1], "-family") == 0) { 80 argc--; 81 argv++; 82 if (argc <= 1) 83 usage(); 84 if (strcmp(argv[1], "inet") == 0) 85 family = AF_INET; 86 else if (strcmp(argv[1], "inet6") == 0) 87 family = AF_INET6; 88 else if (strcmp(argv[1], "link") == 0) 89 family = AF_INET6; 90 else if (strcmp(argv[1], "help") == 0) 91 usage(); 92 else { 93 fprintf(stderr, "Protocol ID \"%s\" is unknown, try \"rtmon help\".\n", argv[1]); 94 exit(-1); 95 } 96 } else if (strcmp(argv[1], "-4") == 0) { 97 family = AF_INET; 98 } else if (strcmp(argv[1], "-6") == 0) { 99 family = AF_INET6; 100 } else if (strcmp(argv[1], "-0") == 0) { 101 family = AF_PACKET; 102 } else if (matches(argv[1], "-Version") == 0) { 103 printf("rtmon utility, iproute2-ss%s\n", SNAPSHOT); 104 exit(0); 105 } else if (matches(argv[1], "file") == 0) { 106 argc--; 107 argv++; 108 if (argc <= 1) 109 usage(); 110 file = argv[1]; 111 } else if (matches(argv[1], "link") == 0) { 112 llink=1; 113 groups = 0; 114 } else if (matches(argv[1], "address") == 0) { 115 laddr=1; 116 groups = 0; 117 } else if (matches(argv[1], "route") == 0) { 118 lroute=1; 119 groups = 0; 120 } else if (strcmp(argv[1], "all") == 0) { 121 groups = ~0U; 122 } else if (matches(argv[1], "help") == 0) { 123 usage(); 124 } else { 125 fprintf(stderr, "Argument \"%s\" is unknown, try \"rtmon help\".\n", argv[1]); 126 exit(-1); 127 } 128 argc--; argv++; 129 } 130 131 if (file == NULL) { 132 fprintf(stderr, "Not enough information: argument \"file\" is required\n"); 133 exit(-1); 134 } 135 if (llink) 136 groups |= RTMGRP_LINK; 137 if (laddr) { 138 if (!family || family == AF_INET) 139 groups |= RTMGRP_IPV4_IFADDR; 140 if (!family || family == AF_INET6) 141 groups |= RTMGRP_IPV6_IFADDR; 142 } 143 if (lroute) { 144 if (!family || family == AF_INET) 145 groups |= RTMGRP_IPV4_ROUTE; 146 if (!family || family == AF_INET6) 147 groups |= RTMGRP_IPV6_ROUTE; 148 } 149 150 fp = fopen(file, "w"); 151 if (fp == NULL) { 152 perror("Cannot fopen"); 153 exit(-1); 154 } 155 156 if (rtnl_open(&rth, groups) < 0) 157 exit(1); 158 159 if (rtnl_wilddump_request(&rth, AF_UNSPEC, RTM_GETLINK) < 0) { 160 perror("Cannot send dump request"); 161 exit(1); 162 } 163 164 write_stamp(fp); 165 166 if (rtnl_dump_filter(&rth, dump_msg, fp, NULL, NULL) < 0) { 167 fprintf(stderr, "Dump terminated\n"); 168 return 1; 169 } 170 171 init_phase = 0; 172 173 if (rtnl_listen(&rth, dump_msg, (void*)fp) < 0) 174 exit(2); 175 176 exit(0); 177} 178