Home | History | Annotate | Download | only in bridge
      1 
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 #include <unistd.h>
      5 #include <time.h>
      6 #include <sys/socket.h>
      7 #include <sys/time.h>
      8 #include <netinet/in.h>
      9 #include <linux/if.h>
     10 #include <linux/if_bridge.h>
     11 #include <string.h>
     12 #include <stdbool.h>
     13 
     14 #include "libnetlink.h"
     15 #include "utils.h"
     16 #include "br_common.h"
     17 
     18 static unsigned int filter_index;
     19 
     20 static const char *port_states[] = {
     21 	[BR_STATE_DISABLED] = "disabled",
     22 	[BR_STATE_LISTENING] = "listening",
     23 	[BR_STATE_LEARNING] = "learning",
     24 	[BR_STATE_FORWARDING] = "forwarding",
     25 	[BR_STATE_BLOCKING] = "blocking",
     26 };
     27 
     28 extern char *if_indextoname (unsigned int __ifindex, char *__ifname);
     29 
     30 static void print_link_flags(FILE *fp, unsigned flags)
     31 {
     32 	fprintf(fp, "<");
     33 	if (flags & IFF_UP && !(flags & IFF_RUNNING))
     34 		fprintf(fp, "NO-CARRIER%s", flags ? "," : "");
     35 	flags &= ~IFF_RUNNING;
     36 #define _PF(f) if (flags&IFF_##f) { \
     37                   flags &= ~IFF_##f ; \
     38                   fprintf(fp, #f "%s", flags ? "," : ""); }
     39 	_PF(LOOPBACK);
     40 	_PF(BROADCAST);
     41 	_PF(POINTOPOINT);
     42 	_PF(MULTICAST);
     43 	_PF(NOARP);
     44 	_PF(ALLMULTI);
     45 	_PF(PROMISC);
     46 	_PF(MASTER);
     47 	_PF(SLAVE);
     48 	_PF(DEBUG);
     49 	_PF(DYNAMIC);
     50 	_PF(AUTOMEDIA);
     51 	_PF(PORTSEL);
     52 	_PF(NOTRAILERS);
     53 	_PF(UP);
     54 	_PF(LOWER_UP);
     55 	_PF(DORMANT);
     56 	_PF(ECHO);
     57 #undef _PF
     58         if (flags)
     59 		fprintf(fp, "%x", flags);
     60 	fprintf(fp, "> ");
     61 }
     62 
     63 static const char *oper_states[] = {
     64 	"UNKNOWN", "NOTPRESENT", "DOWN", "LOWERLAYERDOWN",
     65 	"TESTING", "DORMANT",	 "UP"
     66 };
     67 
     68 static const char *hw_mode[] = {"VEB", "VEPA"};
     69 
     70 static void print_operstate(FILE *f, __u8 state)
     71 {
     72 	if (state >= sizeof(oper_states)/sizeof(oper_states[0]))
     73 		fprintf(f, "state %#x ", state);
     74 	else
     75 		fprintf(f, "state %s ", oper_states[state]);
     76 }
     77 
     78 static void print_portstate(FILE *f, __u8 state)
     79 {
     80 	if (state <= BR_STATE_BLOCKING)
     81 		fprintf(f, "state %s ", port_states[state]);
     82 	else
     83 		fprintf(f, "state (%d) ", state);
     84 }
     85 
     86 static void print_onoff(FILE *f, char *flag, __u8 val)
     87 {
     88 	fprintf(f, "%s %s ", flag, val ? "on" : "off");
     89 }
     90 
     91 static void print_hwmode(FILE *f, __u16 mode)
     92 {
     93 	if (mode >= sizeof(hw_mode)/sizeof(hw_mode[0]))
     94 		fprintf(f, "hwmode %#hx ", mode);
     95 	else
     96 		fprintf(f, "hwmode %s ", hw_mode[mode]);
     97 }
     98 
     99 int print_linkinfo(const struct sockaddr_nl *who,
    100 		   struct nlmsghdr *n, void *arg)
    101 {
    102 	FILE *fp = arg;
    103 	int len = n->nlmsg_len;
    104 	struct ifinfomsg *ifi = NLMSG_DATA(n);
    105 	struct rtattr * tb[IFLA_MAX+1];
    106 	char b1[IFNAMSIZ];
    107 
    108 	len -= NLMSG_LENGTH(sizeof(*ifi));
    109 	if (len < 0) {
    110 		fprintf(stderr, "Message too short!\n");
    111 		return -1;
    112         }
    113 
    114 	if (!(ifi->ifi_family == AF_BRIDGE || ifi->ifi_family == AF_UNSPEC))
    115 		return 0;
    116 
    117 	if (filter_index && filter_index != ifi->ifi_index)
    118 		return 0;
    119 
    120 	parse_rtattr_flags(tb, IFLA_MAX, IFLA_RTA(ifi), len, NLA_F_NESTED);
    121 
    122 	if (tb[IFLA_IFNAME] == NULL) {
    123 		fprintf(stderr, "BUG: nil ifname\n");
    124 		return -1;
    125 	}
    126 
    127 	if (n->nlmsg_type == RTM_DELLINK)
    128 		fprintf(fp, "Deleted ");
    129 
    130 	fprintf(fp, "%d: %s ", ifi->ifi_index,
    131 		tb[IFLA_IFNAME] ? rta_getattr_str(tb[IFLA_IFNAME]) : "<nil>");
    132 
    133 	if (tb[IFLA_OPERSTATE])
    134 		print_operstate(fp, rta_getattr_u8(tb[IFLA_OPERSTATE]));
    135 
    136 	if (tb[IFLA_LINK]) {
    137 		SPRINT_BUF(b1);
    138 		int iflink = rta_getattr_u32(tb[IFLA_LINK]);
    139 		if (iflink == 0)
    140 			fprintf(fp, "@NONE: ");
    141 		else
    142 			fprintf(fp, "@%s: ",
    143 				if_indextoname(iflink, b1));
    144 	} else
    145 		fprintf(fp, ": ");
    146 
    147 	print_link_flags(fp, ifi->ifi_flags);
    148 
    149 	if (tb[IFLA_MTU])
    150 		fprintf(fp, "mtu %u ", rta_getattr_u32(tb[IFLA_MTU]));
    151 
    152 	if (tb[IFLA_MASTER])
    153 		fprintf(fp, "master %s ",
    154 			if_indextoname(rta_getattr_u32(tb[IFLA_MASTER]), b1));
    155 
    156 	if (tb[IFLA_PROTINFO]) {
    157 		if (tb[IFLA_PROTINFO]->rta_type & NLA_F_NESTED) {
    158 			struct rtattr *prtb[IFLA_BRPORT_MAX+1];
    159 
    160 			parse_rtattr_nested(prtb, IFLA_BRPORT_MAX,
    161 					    tb[IFLA_PROTINFO]);
    162 
    163 			if (prtb[IFLA_BRPORT_STATE])
    164 				print_portstate(fp,
    165 						rta_getattr_u8(prtb[IFLA_BRPORT_STATE]));
    166 			if (prtb[IFLA_BRPORT_PRIORITY])
    167 				fprintf(fp, "priority %hu ",
    168 					rta_getattr_u16(prtb[IFLA_BRPORT_PRIORITY]));
    169 			if (prtb[IFLA_BRPORT_COST])
    170 				fprintf(fp, "cost %u ",
    171 					rta_getattr_u32(prtb[IFLA_BRPORT_COST]));
    172 
    173 			if (show_details) {
    174 				fprintf(fp, "%s    ", _SL_);
    175 
    176 				if (prtb[IFLA_BRPORT_MODE])
    177 					print_onoff(fp, "hairpin",
    178 						    rta_getattr_u8(prtb[IFLA_BRPORT_MODE]));
    179 				if (prtb[IFLA_BRPORT_GUARD])
    180 					print_onoff(fp, "guard",
    181 						    rta_getattr_u8(prtb[IFLA_BRPORT_GUARD]));
    182 				if (prtb[IFLA_BRPORT_PROTECT])
    183 					print_onoff(fp, "root_block",
    184 						    rta_getattr_u8(prtb[IFLA_BRPORT_PROTECT]));
    185 				if (prtb[IFLA_BRPORT_FAST_LEAVE])
    186 					print_onoff(fp, "fastleave",
    187 						    rta_getattr_u8(prtb[IFLA_BRPORT_FAST_LEAVE]));
    188 				if (prtb[IFLA_BRPORT_LEARNING])
    189 					print_onoff(fp, "learning",
    190 						    rta_getattr_u8(prtb[IFLA_BRPORT_LEARNING]));
    191 				if (prtb[IFLA_BRPORT_LEARNING_SYNC])
    192 					print_onoff(fp, "learning_sync",
    193 						    rta_getattr_u8(prtb[IFLA_BRPORT_LEARNING_SYNC]));
    194 				if (prtb[IFLA_BRPORT_UNICAST_FLOOD])
    195 					print_onoff(fp, "flood",
    196 						    rta_getattr_u8(prtb[IFLA_BRPORT_UNICAST_FLOOD]));
    197 			}
    198 		} else
    199 			print_portstate(fp, rta_getattr_u8(tb[IFLA_PROTINFO]));
    200 	}
    201 
    202 	if (tb[IFLA_AF_SPEC]) {
    203 		/* This is reported by HW devices that have some bridging
    204 		 * capabilities.
    205 		 */
    206 		struct rtattr *aftb[IFLA_BRIDGE_MAX+1];
    207 
    208 		parse_rtattr_nested(aftb, IFLA_BRIDGE_MAX, tb[IFLA_AF_SPEC]);
    209 
    210 		if (aftb[IFLA_BRIDGE_MODE])
    211 			print_hwmode(fp, rta_getattr_u16(aftb[IFLA_BRIDGE_MODE]));
    212 	}
    213 
    214 	fprintf(fp, "\n");
    215 	fflush(fp);
    216 	return 0;
    217 }
    218 
    219 static void usage(void)
    220 {
    221 	fprintf(stderr, "Usage: bridge link set dev DEV [ cost COST ] [ priority PRIO ] [ state STATE ]\n");
    222 	fprintf(stderr, "                               [ guard {on | off} ]\n");
    223 	fprintf(stderr, "                               [ hairpin {on | off} ] \n");
    224 	fprintf(stderr, "                               [ fastleave {on | off} ]\n");
    225 	fprintf(stderr,	"                               [ root_block {on | off} ]\n");
    226 	fprintf(stderr,	"                               [ learning {on | off} ]\n");
    227 	fprintf(stderr,	"                               [ learning_sync {on | off} ]\n");
    228 	fprintf(stderr,	"                               [ flood {on | off} ]\n");
    229 	fprintf(stderr, "                               [ hwmode {vepa | veb} ]\n");
    230 	fprintf(stderr, "                               [ self ] [ master ]\n");
    231 	fprintf(stderr, "       bridge link show [dev DEV]\n");
    232 	exit(-1);
    233 }
    234 
    235 static bool on_off(char *arg, __s8 *attr, char *val)
    236 {
    237 	if (strcmp(val, "on") == 0)
    238 		*attr = 1;
    239 	else if (strcmp(val, "off") == 0)
    240 		*attr = 0;
    241 	else {
    242 		fprintf(stderr,
    243 			"Error: argument of \"%s\" must be \"on\" or \"off\"\n",
    244 			arg);
    245 		return false;
    246 	}
    247 
    248 	return true;
    249 }
    250 
    251 static int brlink_modify(int argc, char **argv)
    252 {
    253 	struct {
    254 		struct nlmsghdr  n;
    255 		struct ifinfomsg ifm;
    256 		char             buf[512];
    257 	} req;
    258 	char *d = NULL;
    259 	__s8 learning = -1;
    260 	__s8 learning_sync = -1;
    261 	__s8 flood = -1;
    262 	__s8 hairpin = -1;
    263 	__s8 bpdu_guard = -1;
    264 	__s8 fast_leave = -1;
    265 	__s8 root_block = -1;
    266 	__u32 cost = 0;
    267 	__s16 priority = -1;
    268 	__s8 state = -1;
    269 	__s16 mode = -1;
    270 	__u16 flags = 0;
    271 	struct rtattr *nest;
    272 
    273 	memset(&req, 0, sizeof(req));
    274 
    275 	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
    276 	req.n.nlmsg_flags = NLM_F_REQUEST;
    277 	req.n.nlmsg_type = RTM_SETLINK;
    278 	req.ifm.ifi_family = PF_BRIDGE;
    279 
    280 	while (argc > 0) {
    281 		if (strcmp(*argv, "dev") == 0) {
    282 			NEXT_ARG();
    283 			d = *argv;
    284 		} else if (strcmp(*argv, "guard") == 0) {
    285 			NEXT_ARG();
    286 			if (!on_off("guard", &bpdu_guard, *argv))
    287 				return -1;
    288 		} else if (strcmp(*argv, "hairpin") == 0) {
    289 			NEXT_ARG();
    290 			if (!on_off("hairping", &hairpin, *argv))
    291 				return -1;
    292 		} else if (strcmp(*argv, "fastleave") == 0) {
    293 			NEXT_ARG();
    294 			if (!on_off("fastleave", &fast_leave, *argv))
    295 				return -1;
    296 		} else if (strcmp(*argv, "root_block") == 0) {
    297 			NEXT_ARG();
    298 			if (!on_off("root_block", &root_block, *argv))
    299 				return -1;
    300 		} else if (strcmp(*argv, "learning") == 0) {
    301 			NEXT_ARG();
    302 			if (!on_off("learning", &learning, *argv))
    303 				return -1;
    304 		} else if (strcmp(*argv, "learning_sync") == 0) {
    305 			NEXT_ARG();
    306 			if (!on_off("learning_sync", &learning_sync, *argv))
    307 				return -1;
    308 		} else if (strcmp(*argv, "flood") == 0) {
    309 			NEXT_ARG();
    310 			if (!on_off("flood", &flood, *argv))
    311 				return -1;
    312 		} else if (strcmp(*argv, "cost") == 0) {
    313 			NEXT_ARG();
    314 			cost = atoi(*argv);
    315 		} else if (strcmp(*argv, "priority") == 0) {
    316 			NEXT_ARG();
    317 			priority = atoi(*argv);
    318 		} else if (strcmp(*argv, "state") == 0) {
    319 			NEXT_ARG();
    320 			char *endptr;
    321 			size_t nstates = sizeof(port_states) / sizeof(*port_states);
    322 			state = strtol(*argv, &endptr, 10);
    323 			if (!(**argv != '\0' && *endptr == '\0')) {
    324 				for (state = 0; state < nstates; state++)
    325 					if (strcmp(port_states[state], *argv) == 0)
    326 						break;
    327 				if (state == nstates) {
    328 					fprintf(stderr,
    329 						"Error: invalid STP port state\n");
    330 					return -1;
    331 				}
    332 			}
    333 		} else if (strcmp(*argv, "hwmode") == 0) {
    334 			NEXT_ARG();
    335 			flags = BRIDGE_FLAGS_SELF;
    336 			if (strcmp(*argv, "vepa") == 0)
    337 				mode = BRIDGE_MODE_VEPA;
    338 			else if (strcmp(*argv, "veb") == 0)
    339 				mode = BRIDGE_MODE_VEB;
    340 			else {
    341 				fprintf(stderr,
    342 					"Mode argument must be \"vepa\" or "
    343 					"\"veb\".\n");
    344 				return -1;
    345 			}
    346 		} else if (strcmp(*argv, "self") == 0) {
    347 			flags |= BRIDGE_FLAGS_SELF;
    348 		} else if (strcmp(*argv, "master") == 0) {
    349 			flags |= BRIDGE_FLAGS_MASTER;
    350 		} else {
    351 			usage();
    352 		}
    353 		argc--; argv++;
    354 	}
    355 	if (d == NULL) {
    356 		fprintf(stderr, "Device is a required argument.\n");
    357 		return -1;
    358 	}
    359 
    360 
    361 	req.ifm.ifi_index = ll_name_to_index(d);
    362 	if (req.ifm.ifi_index == 0) {
    363 		fprintf(stderr, "Cannot find bridge device \"%s\"\n", d);
    364 		return -1;
    365 	}
    366 
    367 	/* Nested PROTINFO attribute.  Contains: port flags, cost, priority and
    368 	 * state.
    369 	 */
    370 	nest = addattr_nest(&req.n, sizeof(req),
    371 			    IFLA_PROTINFO | NLA_F_NESTED);
    372 	/* Flags first */
    373 	if (bpdu_guard >= 0)
    374 		addattr8(&req.n, sizeof(req), IFLA_BRPORT_GUARD, bpdu_guard);
    375 	if (hairpin >= 0)
    376 		addattr8(&req.n, sizeof(req), IFLA_BRPORT_MODE, hairpin);
    377 	if (fast_leave >= 0)
    378 		addattr8(&req.n, sizeof(req), IFLA_BRPORT_FAST_LEAVE,
    379 			 fast_leave);
    380 	if (root_block >= 0)
    381 		addattr8(&req.n, sizeof(req), IFLA_BRPORT_PROTECT, root_block);
    382 	if (flood >= 0)
    383 		addattr8(&req.n, sizeof(req), IFLA_BRPORT_UNICAST_FLOOD, flood);
    384 	if (learning >= 0)
    385 		addattr8(&req.n, sizeof(req), IFLA_BRPORT_LEARNING, learning);
    386 	if (learning_sync >= 0)
    387 		addattr8(&req.n, sizeof(req), IFLA_BRPORT_LEARNING_SYNC,
    388 			 learning_sync);
    389 
    390 	if (cost > 0)
    391 		addattr32(&req.n, sizeof(req), IFLA_BRPORT_COST, cost);
    392 
    393 	if (priority >= 0)
    394 		addattr16(&req.n, sizeof(req), IFLA_BRPORT_PRIORITY, priority);
    395 
    396 	if (state >= 0)
    397 		addattr8(&req.n, sizeof(req), IFLA_BRPORT_STATE, state);
    398 
    399 	addattr_nest_end(&req.n, nest);
    400 
    401 	/* IFLA_AF_SPEC nested attribute. Contains IFLA_BRIDGE_FLAGS that
    402 	 * designates master or self operation and IFLA_BRIDGE_MODE
    403 	 * for hw 'vepa' or 'veb' operation modes. The hwmodes are
    404 	 * only valid in 'self' mode on some devices so far.
    405 	 */
    406 	if (mode >= 0 || flags > 0) {
    407 		nest = addattr_nest(&req.n, sizeof(req), IFLA_AF_SPEC);
    408 
    409 		if (flags > 0)
    410 			addattr16(&req.n, sizeof(req), IFLA_BRIDGE_FLAGS, flags);
    411 
    412 		if (mode >= 0)
    413 			addattr16(&req.n, sizeof(req), IFLA_BRIDGE_MODE, mode);
    414 
    415 		addattr_nest_end(&req.n, nest);
    416 	}
    417 
    418 	if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
    419 		return -1;
    420 
    421 	return 0;
    422 }
    423 
    424 static int brlink_show(int argc, char **argv)
    425 {
    426 	char *filter_dev = NULL;
    427 
    428 	while (argc > 0) {
    429 		if (strcmp(*argv, "dev") == 0) {
    430 			NEXT_ARG();
    431 			if (filter_dev)
    432 				duparg("dev", *argv);
    433 			filter_dev = *argv;
    434 		}
    435 		argc--; argv++;
    436 	}
    437 
    438 	if (filter_dev) {
    439 		if ((filter_index = ll_name_to_index(filter_dev)) == 0) {
    440 			fprintf(stderr, "Cannot find device \"%s\"\n",
    441 				filter_dev);
    442 			return -1;
    443 		}
    444 	}
    445 
    446 	if (rtnl_wilddump_request(&rth, PF_BRIDGE, RTM_GETLINK) < 0) {
    447 		perror("Cannon send dump request");
    448 		exit(1);
    449 	}
    450 
    451 	if (rtnl_dump_filter(&rth, print_linkinfo, stdout) < 0) {
    452 		fprintf(stderr, "Dump terminated\n");
    453 		exit(1);
    454 	}
    455 	return 0;
    456 }
    457 
    458 int do_link(int argc, char **argv)
    459 {
    460 	ll_init_map(&rth);
    461 	if (argc > 0) {
    462 		if (matches(*argv, "set") == 0 ||
    463 		    matches(*argv, "change") == 0)
    464 			return brlink_modify(argc-1, argv+1);
    465 		if (matches(*argv, "show") == 0 ||
    466 		    matches(*argv, "lst") == 0 ||
    467 		    matches(*argv, "list") == 0)
    468 			return brlink_show(argc-1, argv+1);
    469 		if (matches(*argv, "help") == 0)
    470 			usage();
    471 	} else
    472 		return brlink_show(0, NULL);
    473 
    474 	fprintf(stderr, "Command \"%s\" is unknown, try \"bridge link help\".\n", *argv);
    475 	exit(-1);
    476 }
    477