• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * iplink_macvlan.c	macvlan/macvtap 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:     Patrick McHardy <kaber@trash.net>
10  *		Arnd Bergmann <arnd@arndb.de>
11  */
12 
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <sys/socket.h>
17 #include <linux/if_link.h>
18 
19 #include "rt_names.h"
20 #include "utils.h"
21 #include "ip_common.h"
22 
23 #define pfx_err(lu, ...) {               \
24 	fprintf(stderr, "%s: ", lu->id); \
25 	fprintf(stderr, __VA_ARGS__);    \
26 	fprintf(stderr, "\n");           \
27 }
28 
print_explain(struct link_util * lu,FILE * f)29 static void print_explain(struct link_util *lu, FILE *f)
30 {
31 	fprintf(f,
32 		"Usage: ... %s mode { private | vepa | bridge | passthru [nopromisc] }\n",
33 		lu->id
34 	);
35 }
36 
explain(struct link_util * lu)37 static void explain(struct link_util *lu)
38 {
39 	print_explain(lu, stderr);
40 }
41 
mode_arg(const char * arg)42 static int mode_arg(const char *arg)
43 {
44         fprintf(stderr, "Error: argument of \"mode\" must be \"private\", "
45 		"\"vepa\", \"bridge\" or \"passthru\", not \"%s\"\n", arg);
46         return -1;
47 }
48 
macvlan_parse_opt(struct link_util * lu,int argc,char ** argv,struct nlmsghdr * n)49 static int macvlan_parse_opt(struct link_util *lu, int argc, char **argv,
50 			  struct nlmsghdr *n)
51 {
52 	__u32 mode = 0;
53 	__u16 flags = 0;
54 
55 	while (argc > 0) {
56 		if (matches(*argv, "mode") == 0) {
57 			NEXT_ARG();
58 
59 			if (strcmp(*argv, "private") == 0)
60 				mode = MACVLAN_MODE_PRIVATE;
61 			else if (strcmp(*argv, "vepa") == 0)
62 				mode = MACVLAN_MODE_VEPA;
63 			else if (strcmp(*argv, "bridge") == 0)
64 				mode = MACVLAN_MODE_BRIDGE;
65 			else if (strcmp(*argv, "passthru") == 0)
66 				mode = MACVLAN_MODE_PASSTHRU;
67 			else
68 				return mode_arg(*argv);
69 		} else if (matches(*argv, "nopromisc") == 0) {
70 			flags |= MACVLAN_FLAG_NOPROMISC;
71 		} else if (matches(*argv, "help") == 0) {
72 			explain(lu);
73 			return -1;
74 		} else {
75 			pfx_err(lu, "unknown option \"%s\"?", *argv);
76 			explain(lu);
77 			return -1;
78 		}
79 		argc--, argv++;
80 	}
81 
82 	if (mode)
83 		addattr32(n, 1024, IFLA_MACVLAN_MODE, mode);
84 
85 	if (flags) {
86 		if (flags & MACVLAN_FLAG_NOPROMISC &&
87 		    mode != MACVLAN_MODE_PASSTHRU) {
88 			pfx_err(lu, "nopromisc flag only valid in passthru mode");
89 			explain(lu);
90 			return -1;
91 		}
92 		addattr16(n, 1024, IFLA_MACVLAN_FLAGS, flags);
93 	}
94 	return 0;
95 }
96 
macvlan_print_opt(struct link_util * lu,FILE * f,struct rtattr * tb[])97 static void macvlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
98 {
99 	__u32 mode;
100 	__u16 flags;
101 
102 	if (!tb)
103 		return;
104 
105 	if (!tb[IFLA_MACVLAN_MODE] ||
106 	    RTA_PAYLOAD(tb[IFLA_MACVLAN_MODE]) < sizeof(__u32))
107 		return;
108 
109 	mode = rta_getattr_u32(tb[IFLA_MACVLAN_MODE]);
110 	fprintf(f, " mode %s ",
111 		  mode == MACVLAN_MODE_PRIVATE ? "private"
112 		: mode == MACVLAN_MODE_VEPA    ? "vepa"
113 		: mode == MACVLAN_MODE_BRIDGE  ? "bridge"
114 		: mode == MACVLAN_MODE_PASSTHRU  ? "passthru"
115 		:				 "unknown");
116 
117 	if (!tb[IFLA_MACVLAN_FLAGS] ||
118 	    RTA_PAYLOAD(tb[IFLA_MACVLAN_FLAGS]) < sizeof(__u16))
119 		return;
120 
121 	flags = rta_getattr_u16(tb[IFLA_MACVLAN_FLAGS]);
122 	if (flags & MACVLAN_FLAG_NOPROMISC)
123 		fprintf(f, "nopromisc ");
124 }
125 
macvlan_print_help(struct link_util * lu,int argc,char ** argv,FILE * f)126 static void macvlan_print_help(struct link_util *lu, int argc, char **argv,
127 	FILE *f)
128 {
129 	print_explain(lu, f);
130 }
131 
132 struct link_util macvlan_link_util = {
133 	.id		= "macvlan",
134 	.maxattr	= IFLA_MACVLAN_MAX,
135 	.parse_opt	= macvlan_parse_opt,
136 	.print_opt	= macvlan_print_opt,
137 	.print_help	= macvlan_print_help,
138 };
139 
140 struct link_util macvtap_link_util = {
141 	.id		= "macvtap",
142 	.maxattr	= IFLA_MACVLAN_MAX,
143 	.parse_opt	= macvlan_parse_opt,
144 	.print_opt	= macvlan_print_opt,
145 	.print_help	= macvlan_print_help,
146 };
147