• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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 
print_explain(FILE * f)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 
explain(void)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 
print_portstate(FILE * f,__u8 state)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 
print_onoff(FILE * f,char * flag,__u8 val)56 static void print_onoff(FILE *f, char *flag, __u8 val)
57 {
58 	fprintf(f, "%s %s ", flag, val ? "on" : "off");
59 }
60 
bridge_slave_print_opt(struct link_util * lu,FILE * f,struct rtattr * tb[])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 
bridge_slave_parse_on_off(char * arg_name,char * arg_val,struct nlmsghdr * n,int type)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 
bridge_slave_parse_opt(struct link_util * lu,int argc,char ** argv,struct nlmsghdr * n)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 
bridge_slave_print_help(struct link_util * lu,int argc,char ** argv,FILE * f)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