11a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt/*
21a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt * iplink_vlan.c	VLAN device support
31a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt *
41a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt *              This program is free software; you can redistribute it and/or
51a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt *              modify it under the terms of the GNU General Public License
61a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt *              as published by the Free Software Foundation; either version
71a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt *              2 of the License, or (at your option) any later version.
81a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt *
91a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt * Authors:     Patrick McHardy <kaber@trash.net>
101a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt *		Arnd Bergmann <arnd@arndb.de>
111a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt */
121a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt
131a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt#include <stdio.h>
141a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt#include <stdlib.h>
151a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt#include <string.h>
161a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt#include <sys/socket.h>
171a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt#include <linux/if_link.h>
181a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt
191a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt#include "rt_names.h"
201a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt#include "utils.h"
211a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt#include "ip_common.h"
221a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt
231a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidtstatic void explain(void)
241a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt{
251a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt	fprintf(stderr,
261a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt		"Usage: ... macvlan mode { private | vepa | bridge }\n"
271a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt	);
281a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt}
291a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt
301a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidtstatic int mode_arg(void)
311a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt{
321a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt        fprintf(stderr, "Error: argument of \"mode\" must be \"private\", "
331a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt		"\"vepa\" or \"bridge\"\n");
341a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt        return -1;
351a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt}
361a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt
371a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidtstatic int macvlan_parse_opt(struct link_util *lu, int argc, char **argv,
381a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt			  struct nlmsghdr *n)
391a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt{
401a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt	while (argc > 0) {
411a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt		if (matches(*argv, "mode") == 0) {
421a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt			__u32 mode = 0;
431a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt			NEXT_ARG();
441a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt
451a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt			if (strcmp(*argv, "private") == 0)
461a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt				mode = MACVLAN_MODE_PRIVATE;
471a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt			else if (strcmp(*argv, "vepa") == 0)
481a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt				mode = MACVLAN_MODE_VEPA;
491a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt			else if (strcmp(*argv, "bridge") == 0)
501a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt				mode = MACVLAN_MODE_BRIDGE;
511a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt			else
521a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt				return mode_arg();
531a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt
541a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt			addattr32(n, 1024, IFLA_MACVLAN_MODE, mode);
551a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt		} else if (matches(*argv, "help") == 0) {
561a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt			explain();
571a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt			return -1;
581a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt		} else {
591a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt			fprintf(stderr, "macvlan: what is \"%s\"?\n", *argv);
601a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt			explain();
611a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt			return -1;
621a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt		}
631a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt		argc--, argv++;
641a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt	}
651a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt
661a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt	return 0;
671a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt}
681a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt
691a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidtstatic void macvlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
701a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt{
711a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt	__u32 mode;
721a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt
731a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt	if (!tb)
741a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt		return;
751a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt
761a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt	if (!tb[IFLA_MACVLAN_MODE] ||
771a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt	    RTA_PAYLOAD(tb[IFLA_MACVLAN_MODE]) < sizeof(__u32))
781a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt		return;
791a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt
801a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt	mode = *(__u32 *)RTA_DATA(tb[IFLA_VLAN_ID]);
811a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt	fprintf(f, " mode %s ",
821a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt		  mode == MACVLAN_MODE_PRIVATE ? "private"
831a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt		: mode == MACVLAN_MODE_VEPA    ? "vepa"
841a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt		: mode == MACVLAN_MODE_BRIDGE  ? "bridge"
851a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt		:				 "unknown");
861a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt}
871a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt
881a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidtstruct link_util macvlan_link_util = {
891a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt	.id		= "macvlan",
901a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt	.maxattr	= IFLA_MACVLAN_MAX,
911a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt	.parse_opt	= macvlan_parse_opt,
921a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt	.print_opt	= macvlan_print_opt,
931a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt};
94