1 /* 2 * brmonitor.c "bridge 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: Stephen Hemminger <shemminger (at) vyatta.com> 10 * 11 */ 12 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <unistd.h> 16 #include <time.h> 17 #include <sys/socket.h> 18 #include <sys/time.h> 19 #include <net/if.h> 20 #include <netinet/in.h> 21 #include <linux/if_bridge.h> 22 #include <linux/neighbour.h> 23 #include <string.h> 24 25 #include "utils.h" 26 #include "br_common.h" 27 28 29 static void usage(void) __attribute__((noreturn)); 30 int prefix_banner; 31 32 static void usage(void) 33 { 34 fprintf(stderr, "Usage: bridge monitor [file | link | fdb | mdb | all]\n"); 35 exit(-1); 36 } 37 38 static int accept_msg(const struct sockaddr_nl *who, 39 struct rtnl_ctrl_data *ctrl, 40 struct nlmsghdr *n, void *arg) 41 { 42 FILE *fp = arg; 43 44 if (timestamp) 45 print_timestamp(fp); 46 47 switch (n->nlmsg_type) { 48 case RTM_NEWLINK: 49 case RTM_DELLINK: 50 if (prefix_banner) 51 fprintf(fp, "[LINK]"); 52 53 return print_linkinfo(who, n, arg); 54 55 case RTM_NEWNEIGH: 56 case RTM_DELNEIGH: 57 if (prefix_banner) 58 fprintf(fp, "[NEIGH]"); 59 return print_fdb(who, n, arg); 60 61 case RTM_NEWMDB: 62 case RTM_DELMDB: 63 if (prefix_banner) 64 fprintf(fp, "[MDB]"); 65 return print_mdb(who, n, arg); 66 67 case NLMSG_TSTAMP: 68 print_nlmsg_timestamp(fp, n); 69 return 0; 70 71 default: 72 return 0; 73 } 74 } 75 76 int do_monitor(int argc, char **argv) 77 { 78 char *file = NULL; 79 unsigned groups = ~RTMGRP_TC; 80 int llink=0; 81 int lneigh=0; 82 int lmdb=0; 83 84 rtnl_close(&rth); 85 86 while (argc > 0) { 87 if (matches(*argv, "file") == 0) { 88 NEXT_ARG(); 89 file = *argv; 90 } else if (matches(*argv, "link") == 0) { 91 llink=1; 92 groups = 0; 93 } else if (matches(*argv, "fdb") == 0) { 94 lneigh = 1; 95 groups = 0; 96 } else if (matches(*argv, "mdb") == 0) { 97 lmdb = 1; 98 groups = 0; 99 } else if (strcmp(*argv, "all") == 0) { 100 groups = ~RTMGRP_TC; 101 prefix_banner=1; 102 } else if (matches(*argv, "help") == 0) { 103 usage(); 104 } else { 105 fprintf(stderr, "Argument \"%s\" is unknown, try \"bridge monitor help\".\n", *argv); 106 exit(-1); 107 } 108 argc--; argv++; 109 } 110 111 if (llink) 112 groups |= nl_mgrp(RTNLGRP_LINK); 113 114 if (lneigh) { 115 groups |= nl_mgrp(RTNLGRP_NEIGH); 116 } 117 118 if (lmdb) { 119 groups |= nl_mgrp(RTNLGRP_MDB); 120 } 121 122 if (file) { 123 FILE *fp; 124 int err; 125 fp = fopen(file, "r"); 126 if (fp == NULL) { 127 perror("Cannot fopen"); 128 exit(-1); 129 } 130 err = rtnl_from_file(fp, accept_msg, stdout); 131 fclose(fp); 132 return err; 133 } 134 135 if (rtnl_open(&rth, groups) < 0) 136 exit(1); 137 ll_init_map(&rth); 138 139 if (rtnl_listen(&rth, accept_msg, stdout) < 0) 140 exit(2); 141 142 return 0; 143 } 144 145