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