iproute2/bridge/monitor.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-or-later */
   2/*
   3 * brmonitor.c          "bridge monitor"
   4 *
   5 * Authors:     Stephen Hemminger <shemminger@vyatta.com>
   6 */
   7
   8#include <stdio.h>
   9#include <stdlib.h>
  10#include <unistd.h>
  11#include <time.h>
  12#include <sys/socket.h>
  13#include <sys/time.h>
  14#include <net/if.h>
  15#include <netinet/in.h>
  16#include <linux/if_bridge.h>
  17#include <linux/neighbour.h>
  18#include <string.h>
  19
  20#include "utils.h"
  21#include "br_common.h"
  22
  23
  24static void usage(void) __attribute__((noreturn));
  25static int prefix_banner;
  26
  27static void usage(void)
  28{
  29        fprintf(stderr, "Usage: bridge monitor [file | link | fdb | mdb | vlan | vni | all]\n");
  30        exit(-1);
  31}
  32
  33static int accept_msg(struct rtnl_ctrl_data *ctrl,
  34                      struct nlmsghdr *n, void *arg)
  35{
  36        FILE *fp = arg;
  37
  38        switch (n->nlmsg_type) {
  39        case RTM_NEWLINK:
  40        case RTM_DELLINK:
  41                return print_linkinfo(n, arg);
  42
  43        case RTM_NEWNEIGH:
  44        case RTM_DELNEIGH:
  45                return print_fdb(n, arg);
  46
  47        case RTM_NEWMDB:
  48        case RTM_DELMDB:
  49                return print_mdb_mon(n, arg);
  50
  51        case NLMSG_TSTAMP:
  52                print_nlmsg_timestamp(fp, n);
  53                return 0;
  54
  55        case RTM_NEWVLAN:
  56        case RTM_DELVLAN:
  57                return print_vlan_rtm(n, arg, true, false);
  58
  59        case RTM_NEWTUNNEL:
  60        case RTM_DELTUNNEL:
  61                return print_vnifilter_rtm(n, arg);
  62
  63        default:
  64                return 0;
  65        }
  66}
  67
  68void print_headers(FILE *fp, const char *label)
  69{
  70        if (timestamp)
  71                print_timestamp(fp);
  72
  73        if (prefix_banner)
  74                fprintf(fp, "%s", label);
  75}
  76
  77int do_monitor(int argc, char **argv)
  78{
  79        char *file = NULL;
  80        unsigned int groups = ~RTMGRP_TC;
  81        int llink = 0;
  82        int lneigh = 0;
  83        int lmdb = 0;
  84        int lvlan = 0;
  85        int lvni = 0;
  86
  87        rtnl_close(&rth);
  88
  89        while (argc > 0) {
  90                if (matches(*argv, "file") == 0) {
  91                        NEXT_ARG();
  92                        file = *argv;
  93                } else if (matches(*argv, "link") == 0) {
  94                        llink = 1;
  95                        groups = 0;
  96                } else if (matches(*argv, "fdb") == 0) {
  97                        lneigh = 1;
  98                        groups = 0;
  99                } else if (matches(*argv, "mdb") == 0) {
 100                        lmdb = 1;
 101                        groups = 0;
 102                } else if (matches(*argv, "vlan") == 0) {
 103                        lvlan = 1;
 104                        groups = 0;
 105                } else if (strcmp(*argv, "vni") == 0) {
 106                        lvni = 1;
 107                        groups = 0;
 108                } else if (strcmp(*argv, "all") == 0) {
 109                        groups = ~RTMGRP_TC;
 110                        lvlan = 1;
 111                        lvni = 1;
 112                        prefix_banner = 1;
 113                } else if (matches(*argv, "help") == 0) {
 114                        usage();
 115                } else {
 116                        fprintf(stderr, "Argument \"%s\" is unknown, try \"bridge monitor help\".\n", *argv);
 117                        exit(-1);
 118                }
 119                argc--; argv++;
 120        }
 121
 122        if (llink)
 123                groups |= nl_mgrp(RTNLGRP_LINK);
 124
 125        if (lneigh) {
 126                groups |= nl_mgrp(RTNLGRP_NEIGH);
 127        }
 128
 129        if (lmdb) {
 130                groups |= nl_mgrp(RTNLGRP_MDB);
 131        }
 132
 133        if (file) {
 134                FILE *fp;
 135                int err;
 136
 137                fp = fopen(file, "r");
 138                if (fp == NULL) {
 139                        perror("Cannot fopen");
 140                        exit(-1);
 141                }
 142                err = rtnl_from_file(fp, accept_msg, stdout);
 143                fclose(fp);
 144                return err;
 145        }
 146
 147        if (rtnl_open(&rth, groups) < 0)
 148                exit(1);
 149
 150        if (lvlan && rtnl_add_nl_group(&rth, RTNLGRP_BRVLAN) < 0) {
 151                fprintf(stderr, "Failed to add bridge vlan group to list\n");
 152                exit(1);
 153        }
 154
 155        if (lvni && rtnl_add_nl_group(&rth, RTNLGRP_TUNNEL) < 0) {
 156                fprintf(stderr, "Failed to add bridge vni group to list\n");
 157                exit(1);
 158        }
 159
 160        ll_init_map(&rth);
 161
 162        if (rtnl_listen(&rth, accept_msg, stdout) < 0)
 163                exit(2);
 164
 165        return 0;
 166}
 167