Home | History | Annotate | Download | only in ip
      1 /*
      2  * iplink_bridge_slave.c	Bridge slave device support
      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:     Jiri Pirko <jiri (at) resnulli.us>
     10  */
     11 
     12 #include <stdio.h>
     13 #include <sys/socket.h>
     14 #include <netinet/in.h>
     15 #include <linux/if_link.h>
     16 #include <linux/if_bridge.h>
     17 
     18 #include "rt_names.h"
     19 #include "utils.h"
     20 #include "ip_common.h"
     21 
     22 static void print_explain(FILE *f)
     23 {
     24 	fprintf(f,
     25 		"Usage: ... bridge_slave [ state STATE ] [ priority PRIO ] [cost COST ]\n"
     26 		"                        [ guard {on | off} ]\n"
     27 		"                        [ hairpin {on | off} ] \n"
     28 		"                        [ fastleave {on | off} ]\n"
     29 		"                        [ root_block {on | off} ]\n"
     30 		"                        [ learning {on | off} ]\n"
     31 		"                        [ flood {on | off} ]\n"
     32 	);
     33 }
     34 
     35 static void explain(void)
     36 {
     37 	print_explain(stderr);
     38 }
     39 
     40 static const char *port_states[] = {
     41 	[BR_STATE_DISABLED] = "disabled",
     42 	[BR_STATE_LISTENING] = "listening",
     43 	[BR_STATE_LEARNING] = "learning",
     44 	[BR_STATE_FORWARDING] = "forwarding",
     45 	[BR_STATE_BLOCKING] = "blocking",
     46 };
     47 
     48 static void print_portstate(FILE *f, __u8 state)
     49 {
     50 	if (state <= BR_STATE_BLOCKING)
     51 		fprintf(f, "state %s ", port_states[state]);
     52 	else
     53 		fprintf(f, "state (%d) ", state);
     54 }
     55 
     56 static void print_onoff(FILE *f, char *flag, __u8 val)
     57 {
     58 	fprintf(f, "%s %s ", flag, val ? "on" : "off");
     59 }
     60 
     61 static void bridge_slave_print_opt(struct link_util *lu, FILE *f,
     62 				   struct rtattr *tb[])
     63 {
     64 	if (!tb)
     65 		return;
     66 
     67 	if (tb[IFLA_BRPORT_STATE])
     68 		print_portstate(f, rta_getattr_u8(tb[IFLA_BRPORT_STATE]));
     69 
     70 	if (tb[IFLA_BRPORT_PRIORITY])
     71 		fprintf(f, "priority %d ",
     72 			rta_getattr_u16(tb[IFLA_BRPORT_PRIORITY]));
     73 
     74 	if (tb[IFLA_BRPORT_COST])
     75 		fprintf(f, "cost %d ",
     76 			rta_getattr_u32(tb[IFLA_BRPORT_COST]));
     77 
     78 	if (tb[IFLA_BRPORT_MODE])
     79 		print_onoff(f, "hairpin",
     80 			    rta_getattr_u8(tb[IFLA_BRPORT_MODE]));
     81 
     82 	if (tb[IFLA_BRPORT_GUARD])
     83 		print_onoff(f, "guard",
     84 			    rta_getattr_u8(tb[IFLA_BRPORT_GUARD]));
     85 
     86 	if (tb[IFLA_BRPORT_PROTECT])
     87 		print_onoff(f, "root_block",
     88 			    rta_getattr_u8(tb[IFLA_BRPORT_PROTECT]));
     89 
     90 	if (tb[IFLA_BRPORT_FAST_LEAVE])
     91 		print_onoff(f, "fastleave",
     92 			    rta_getattr_u8(tb[IFLA_BRPORT_FAST_LEAVE]));
     93 
     94 	if (tb[IFLA_BRPORT_LEARNING])
     95 		print_onoff(f, "learning",
     96 			rta_getattr_u8(tb[IFLA_BRPORT_LEARNING]));
     97 
     98 	if (tb[IFLA_BRPORT_UNICAST_FLOOD])
     99 		print_onoff(f, "flood",
    100 			rta_getattr_u8(tb[IFLA_BRPORT_UNICAST_FLOOD]));
    101 }
    102 
    103 static void bridge_slave_parse_on_off(char *arg_name, char *arg_val,
    104 				      struct nlmsghdr *n, int type)
    105 {
    106 	__u8 val;
    107 
    108 	if (strcmp(arg_val, "on") == 0)
    109 		val = 1;
    110 	else if (strcmp(arg_val, "off") == 0)
    111 		val = 0;
    112 	else
    113 		invarg("should be \"on\" or \"off\"", arg_name);
    114 
    115 	addattr8(n, 1024, type, val);
    116 }
    117 
    118 static int bridge_slave_parse_opt(struct link_util *lu, int argc, char **argv,
    119 				  struct nlmsghdr *n)
    120 {
    121 	__u8 state;
    122 	__u16 priority;
    123 	__u32 cost;
    124 
    125 	while (argc > 0) {
    126 		if (matches(*argv, "state") == 0) {
    127 			NEXT_ARG();
    128 			if (get_u8(&state, *argv, 0))
    129 				invarg("state is invalid", *argv);
    130 			addattr8(n, 1024, IFLA_BRPORT_STATE, state);
    131 		} else if (matches(*argv, "priority") == 0) {
    132 			NEXT_ARG();
    133 			if (get_u16(&priority, *argv, 0))
    134 				invarg("priority is invalid", *argv);
    135 			addattr16(n, 1024, IFLA_BRPORT_PRIORITY, priority);
    136 		} else if (matches(*argv, "cost") == 0) {
    137 			NEXT_ARG();
    138 			if (get_u32(&cost, *argv, 0))
    139 				invarg("cost is invalid", *argv);
    140 			addattr32(n, 1024, IFLA_BRPORT_COST, cost);
    141 		} else if (matches(*argv, "hairpin") == 0) {
    142 			NEXT_ARG();
    143 			bridge_slave_parse_on_off("hairpin", *argv, n,
    144 						  IFLA_BRPORT_MODE);
    145 		} else if (matches(*argv, "guard") == 0) {
    146 			NEXT_ARG();
    147 			bridge_slave_parse_on_off("guard", *argv, n,
    148 						  IFLA_BRPORT_GUARD);
    149 		} else if (matches(*argv, "root_block") == 0) {
    150 			NEXT_ARG();
    151 			bridge_slave_parse_on_off("root_block", *argv, n,
    152 						  IFLA_BRPORT_PROTECT);
    153 		} else if (matches(*argv, "fastleave") == 0) {
    154 			NEXT_ARG();
    155 			bridge_slave_parse_on_off("fastleave", *argv, n,
    156 						  IFLA_BRPORT_FAST_LEAVE);
    157 		} else if (matches(*argv, "learning") == 0) {
    158 			NEXT_ARG();
    159 			bridge_slave_parse_on_off("learning", *argv, n,
    160 						  IFLA_BRPORT_LEARNING);
    161 		} else if (matches(*argv, "flood") == 0) {
    162 			NEXT_ARG();
    163 			bridge_slave_parse_on_off("flood", *argv, n,
    164 						  IFLA_BRPORT_UNICAST_FLOOD);
    165 		} else if (matches(*argv, "help") == 0) {
    166 			explain();
    167 			return -1;
    168 		} else {
    169 			fprintf(stderr, "bridge_slave: unknown option \"%s\"?\n",
    170 				*argv);
    171 			explain();
    172 			return -1;
    173 		}
    174 		argc--, argv++;
    175 	}
    176 
    177 	return 0;
    178 }
    179 
    180 static void bridge_slave_print_help(struct link_util *lu, int argc, char **argv,
    181 		FILE *f)
    182 {
    183 	print_explain(f);
    184 }
    185 
    186 struct link_util bridge_slave_link_util = {
    187 	.id		= "bridge",
    188 	.maxattr	= IFLA_BRPORT_MAX,
    189 	.print_opt	= bridge_slave_print_opt,
    190 	.parse_opt	= bridge_slave_parse_opt,
    191 	.print_help     = bridge_slave_print_help,
    192 	.slave		= true,
    193 };
    194