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 (at) trash.net> 10 * Arnd Bergmann <arnd (at) 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 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 37 static void explain(struct link_util *lu) 38 { 39 print_explain(lu, stderr); 40 } 41 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 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 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 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