Home | History | Annotate | Download | only in ip
      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