iproute2/ip/ipmonitor.c
<<
>>
Prefs
   1/*
   2 * ipmonitor.c          "ip monitor".
   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 <netinet/in.h>
  19#include <arpa/inet.h>
  20#include <string.h>
  21#include <time.h>
  22
  23#include "utils.h"
  24#include "ip_common.h"
  25
  26static void usage(void) __attribute__((noreturn));
  27static int prefix_banner;
  28int listen_all_nsid;
  29
  30static void usage(void)
  31{
  32        fprintf(stderr,
  33                "Usage: ip monitor [ all | LISTofOBJECTS ] [ FILE ] [ label ] [all-nsid] [dev DEVICE]\n"
  34                "LISTofOBJECTS := link | address | route | mroute | prefix |\n"
  35                "                neigh | netconf | rule | nsid\n"
  36                "FILE := file FILENAME\n");
  37        exit(-1);
  38}
  39
  40static void print_headers(FILE *fp, char *label, struct rtnl_ctrl_data *ctrl)
  41{
  42        if (timestamp)
  43                print_timestamp(fp);
  44
  45        if (listen_all_nsid) {
  46                if (ctrl == NULL || ctrl->nsid < 0)
  47                        fprintf(fp, "[nsid current]");
  48                else
  49                        fprintf(fp, "[nsid %d]", ctrl->nsid);
  50        }
  51
  52        if (prefix_banner)
  53                fprintf(fp, "%s", label);
  54}
  55
  56static int accept_msg(struct rtnl_ctrl_data *ctrl,
  57                      struct nlmsghdr *n, void *arg)
  58{
  59        FILE *fp = (FILE *)arg;
  60
  61        switch (n->nlmsg_type) {
  62        case RTM_NEWROUTE:
  63        case RTM_DELROUTE: {
  64                struct rtmsg *r = NLMSG_DATA(n);
  65                int len = n->nlmsg_len - NLMSG_LENGTH(sizeof(*r));
  66
  67                if (len < 0) {
  68                        fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
  69                        return -1;
  70                }
  71
  72                if (r->rtm_flags & RTM_F_CLONED)
  73                        return 0;
  74
  75                if (r->rtm_family == RTNL_FAMILY_IPMR ||
  76                    r->rtm_family == RTNL_FAMILY_IP6MR) {
  77                        print_headers(fp, "[MROUTE]", ctrl);
  78                        print_mroute(n, arg);
  79                        return 0;
  80                } else {
  81                        print_headers(fp, "[ROUTE]", ctrl);
  82                        print_route(n, arg);
  83                        return 0;
  84                }
  85        }
  86
  87        case RTM_NEWNEXTHOP:
  88        case RTM_DELNEXTHOP:
  89                print_headers(fp, "[NEXTHOP]", ctrl);
  90                print_nexthop(n, arg);
  91                return 0;
  92
  93        case RTM_NEWLINK:
  94        case RTM_DELLINK:
  95                ll_remember_index(n, NULL);
  96                print_headers(fp, "[LINK]", ctrl);
  97                print_linkinfo(n, arg);
  98                return 0;
  99
 100        case RTM_NEWADDR:
 101        case RTM_DELADDR:
 102                print_headers(fp, "[ADDR]", ctrl);
 103                print_addrinfo(n, arg);
 104                return 0;
 105
 106        case RTM_NEWADDRLABEL:
 107        case RTM_DELADDRLABEL:
 108                print_headers(fp, "[ADDRLABEL]", ctrl);
 109                print_addrlabel(n, arg);
 110                return 0;
 111
 112        case RTM_NEWNEIGH:
 113        case RTM_DELNEIGH:
 114        case RTM_GETNEIGH:
 115                if (preferred_family) {
 116                        struct ndmsg *r = NLMSG_DATA(n);
 117
 118                        if (r->ndm_family != preferred_family)
 119                                return 0;
 120                }
 121
 122                print_headers(fp, "[NEIGH]", ctrl);
 123                print_neigh(n, arg);
 124                return 0;
 125
 126        case RTM_NEWPREFIX:
 127                print_headers(fp, "[PREFIX]", ctrl);
 128                print_prefix(n, arg);
 129                return 0;
 130
 131        case RTM_NEWRULE:
 132        case RTM_DELRULE:
 133                print_headers(fp, "[RULE]", ctrl);
 134                print_rule(n, arg);
 135                return 0;
 136
 137        case NLMSG_TSTAMP:
 138                print_nlmsg_timestamp(fp, n);
 139                return 0;
 140
 141        case RTM_NEWNETCONF:
 142        case RTM_DELNETCONF:
 143                print_headers(fp, "[NETCONF]", ctrl);
 144                print_netconf(ctrl, n, arg);
 145                return 0;
 146
 147        case RTM_DELNSID:
 148        case RTM_NEWNSID:
 149                print_headers(fp, "[NSID]", ctrl);
 150                print_nsid(n, arg);
 151                return 0;
 152
 153        case NLMSG_ERROR:
 154        case NLMSG_NOOP:
 155        case NLMSG_DONE:
 156                break;  /* ignore */
 157
 158        default:
 159                fprintf(stderr,
 160                        "Unknown message: type=0x%08x(%d) flags=0x%08x(%d) len=0x%08x(%d)\n",
 161                        n->nlmsg_type, n->nlmsg_type,
 162                        n->nlmsg_flags, n->nlmsg_flags, n->nlmsg_len,
 163                        n->nlmsg_len);
 164        }
 165        return 0;
 166}
 167
 168int do_ipmonitor(int argc, char **argv)
 169{
 170        int lnexthop = 0, nh_set = 1;
 171        char *file = NULL;
 172        unsigned int groups = 0;
 173        int llink = 0;
 174        int laddr = 0;
 175        int lroute = 0;
 176        int lmroute = 0;
 177        int lprefix = 0;
 178        int lneigh = 0;
 179        int lnetconf = 0;
 180        int lrule = 0;
 181        int lnsid = 0;
 182        int ifindex = 0;
 183
 184        groups |= nl_mgrp(RTNLGRP_LINK);
 185        groups |= nl_mgrp(RTNLGRP_IPV4_IFADDR);
 186        groups |= nl_mgrp(RTNLGRP_IPV6_IFADDR);
 187        groups |= nl_mgrp(RTNLGRP_IPV4_ROUTE);
 188        groups |= nl_mgrp(RTNLGRP_IPV6_ROUTE);
 189        groups |= nl_mgrp(RTNLGRP_MPLS_ROUTE);
 190        groups |= nl_mgrp(RTNLGRP_IPV4_MROUTE);
 191        groups |= nl_mgrp(RTNLGRP_IPV6_MROUTE);
 192        groups |= nl_mgrp(RTNLGRP_IPV6_PREFIX);
 193        groups |= nl_mgrp(RTNLGRP_NEIGH);
 194        groups |= nl_mgrp(RTNLGRP_IPV4_NETCONF);
 195        groups |= nl_mgrp(RTNLGRP_IPV6_NETCONF);
 196        groups |= nl_mgrp(RTNLGRP_IPV4_RULE);
 197        groups |= nl_mgrp(RTNLGRP_IPV6_RULE);
 198        groups |= nl_mgrp(RTNLGRP_NSID);
 199        groups |= nl_mgrp(RTNLGRP_MPLS_NETCONF);
 200
 201        rtnl_close(&rth);
 202
 203        while (argc > 0) {
 204                if (matches(*argv, "file") == 0) {
 205                        NEXT_ARG();
 206                        file = *argv;
 207                } else if (matches(*argv, "label") == 0) {
 208                        prefix_banner = 1;
 209                } else if (matches(*argv, "link") == 0) {
 210                        llink = 1;
 211                        groups = 0;
 212                        nh_set = 0;
 213                } else if (matches(*argv, "address") == 0) {
 214                        laddr = 1;
 215                        groups = 0;
 216                        nh_set = 0;
 217                } else if (matches(*argv, "route") == 0) {
 218                        lroute = 1;
 219                        groups = 0;
 220                        nh_set = 0;
 221                } else if (matches(*argv, "mroute") == 0) {
 222                        lmroute = 1;
 223                        groups = 0;
 224                        nh_set = 0;
 225                } else if (matches(*argv, "prefix") == 0) {
 226                        lprefix = 1;
 227                        groups = 0;
 228                        nh_set = 0;
 229                } else if (matches(*argv, "neigh") == 0) {
 230                        lneigh = 1;
 231                        groups = 0;
 232                        nh_set = 0;
 233                } else if (matches(*argv, "netconf") == 0) {
 234                        lnetconf = 1;
 235                        groups = 0;
 236                        nh_set = 0;
 237                } else if (matches(*argv, "rule") == 0) {
 238                        lrule = 1;
 239                        groups = 0;
 240                        nh_set = 0;
 241                } else if (matches(*argv, "nsid") == 0) {
 242                        lnsid = 1;
 243                        groups = 0;
 244                        nh_set = 0;
 245                } else if (matches(*argv, "nexthop") == 0) {
 246                        lnexthop = 1;
 247                        groups = 0;
 248                } else if (strcmp(*argv, "all") == 0) {
 249                        prefix_banner = 1;
 250                } else if (matches(*argv, "all-nsid") == 0) {
 251                        listen_all_nsid = 1;
 252                } else if (matches(*argv, "help") == 0) {
 253                        usage();
 254                } else if (strcmp(*argv, "dev") == 0) {
 255                        NEXT_ARG();
 256
 257                        ifindex = ll_name_to_index(*argv);
 258                        if (!ifindex)
 259                                invarg("Device does not exist\n", *argv);
 260                } else {
 261                        fprintf(stderr, "Argument \"%s\" is unknown, try \"ip monitor help\".\n", *argv);
 262                        exit(-1);
 263                }
 264                argc--; argv++;
 265        }
 266
 267        ipaddr_reset_filter(1, ifindex);
 268        iproute_reset_filter(ifindex);
 269        ipmroute_reset_filter(ifindex);
 270        ipneigh_reset_filter(ifindex);
 271        ipnetconf_reset_filter(ifindex);
 272
 273        if (llink)
 274                groups |= nl_mgrp(RTNLGRP_LINK);
 275        if (laddr) {
 276                if (!preferred_family || preferred_family == AF_INET)
 277                        groups |= nl_mgrp(RTNLGRP_IPV4_IFADDR);
 278                if (!preferred_family || preferred_family == AF_INET6)
 279                        groups |= nl_mgrp(RTNLGRP_IPV6_IFADDR);
 280        }
 281        if (lroute) {
 282                if (!preferred_family || preferred_family == AF_INET)
 283                        groups |= nl_mgrp(RTNLGRP_IPV4_ROUTE);
 284                if (!preferred_family || preferred_family == AF_INET6)
 285                        groups |= nl_mgrp(RTNLGRP_IPV6_ROUTE);
 286                if (!preferred_family || preferred_family == AF_MPLS)
 287                        groups |= nl_mgrp(RTNLGRP_MPLS_ROUTE);
 288        }
 289        if (lmroute) {
 290                if (!preferred_family || preferred_family == AF_INET)
 291                        groups |= nl_mgrp(RTNLGRP_IPV4_MROUTE);
 292                if (!preferred_family || preferred_family == AF_INET6)
 293                        groups |= nl_mgrp(RTNLGRP_IPV6_MROUTE);
 294        }
 295        if (lprefix) {
 296                if (!preferred_family || preferred_family == AF_INET6)
 297                        groups |= nl_mgrp(RTNLGRP_IPV6_PREFIX);
 298        }
 299        if (lneigh) {
 300                groups |= nl_mgrp(RTNLGRP_NEIGH);
 301        }
 302        if (lnetconf) {
 303                if (!preferred_family || preferred_family == AF_INET)
 304                        groups |= nl_mgrp(RTNLGRP_IPV4_NETCONF);
 305                if (!preferred_family || preferred_family == AF_INET6)
 306                        groups |= nl_mgrp(RTNLGRP_IPV6_NETCONF);
 307                if (!preferred_family || preferred_family == AF_MPLS)
 308                        groups |= nl_mgrp(RTNLGRP_MPLS_NETCONF);
 309        }
 310        if (lrule) {
 311                if (!preferred_family || preferred_family == AF_INET)
 312                        groups |= nl_mgrp(RTNLGRP_IPV4_RULE);
 313                if (!preferred_family || preferred_family == AF_INET6)
 314                        groups |= nl_mgrp(RTNLGRP_IPV6_RULE);
 315        }
 316        if (lnsid) {
 317                groups |= nl_mgrp(RTNLGRP_NSID);
 318        }
 319        if (nh_set)
 320                lnexthop = 1;
 321
 322        if (file) {
 323                FILE *fp;
 324                int err;
 325
 326                fp = fopen(file, "r");
 327                if (fp == NULL) {
 328                        perror("Cannot fopen");
 329                        exit(-1);
 330                }
 331                err = rtnl_from_file(fp, accept_msg, stdout);
 332                fclose(fp);
 333                return err;
 334        }
 335
 336        if (rtnl_open(&rth, groups) < 0)
 337                exit(1);
 338
 339        if (lnexthop && rtnl_add_nl_group(&rth, RTNLGRP_NEXTHOP) < 0) {
 340                fprintf(stderr, "Failed to add nexthop group to list\n");
 341                exit(1);
 342        }
 343
 344        if (listen_all_nsid && rtnl_listen_all_nsid(&rth) < 0)
 345                exit(1);
 346
 347        ll_init_map(&rth);
 348        netns_nsid_socket_init();
 349        netns_map_init();
 350
 351        if (rtnl_listen(&rth, accept_msg, stdout) < 0)
 352                exit(2);
 353
 354        return 0;
 355}
 356