19eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich#include <stdio.h>
29eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich#include <stdlib.h>
39eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich#include <unistd.h>
49eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich#include <fcntl.h>
59eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich#include <sys/socket.h>
69eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich#include <net/if.h>
79eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich#include <netinet/in.h>
89eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich#include <linux/if_bridge.h>
99eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich#include <linux/if_ether.h>
109eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich#include <string.h>
119eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
129eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich#include "libnetlink.h"
139eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich#include "br_common.h"
149eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich#include "utils.h"
159eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
169dca899b2d97163f18b66c21b5e7acec893b0fa4Andreas Henrikssonstatic unsigned int filter_index;
179eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
189eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevichstatic void usage(void)
199eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich{
209eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	fprintf(stderr, "Usage: bridge vlan { add | del } vid VLAN_ID dev DEV [ pvid] [ untagged ]\n");
219eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	fprintf(stderr, "                                                     [ self ] [ master ]\n");
229eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	fprintf(stderr, "       bridge vlan { show } [ dev DEV ]\n");
239eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	exit(-1);
249eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich}
259eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
269eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevichstatic int vlan_modify(int cmd, int argc, char **argv)
279eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich{
289eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	struct {
299eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		struct nlmsghdr 	n;
309eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		struct ifinfomsg 	ifm;
319eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		char   			buf[1024];
329eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	} req;
339eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	char *d = NULL;
349eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	short vid = -1;
353ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu	short vid_end = -1;
369eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	struct rtattr *afspec;
379eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	struct bridge_vlan_info vinfo;
389eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	unsigned short flags = 0;
399eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
409eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	memset(&vinfo, 0, sizeof(vinfo));
419eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	memset(&req, 0, sizeof(req));
429eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
439eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
449eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	req.n.nlmsg_flags = NLM_F_REQUEST;
459eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	req.n.nlmsg_type = cmd;
469eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	req.ifm.ifi_family = PF_BRIDGE;
479eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
489eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	while (argc > 0) {
499eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		if (strcmp(*argv, "dev") == 0) {
509eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich			NEXT_ARG();
519eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich			d = *argv;
529eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		} else if (strcmp(*argv, "vid") == 0) {
533ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu			char *p;
549eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich			NEXT_ARG();
553ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu			p = strchr(*argv, '-');
563ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu			if (p) {
573ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu				*p = '\0';
583ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu				p++;
593ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu				vid = atoi(*argv);
603ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu				vid_end = atoi(p);
613ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu				vinfo.flags |= BRIDGE_VLAN_INFO_RANGE_BEGIN;
623ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu			} else {
633ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu				vid = atoi(*argv);
643ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu			}
659eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		} else if (strcmp(*argv, "self") == 0) {
669eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich			flags |= BRIDGE_FLAGS_SELF;
679eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		} else if (strcmp(*argv, "master") == 0) {
689eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich			flags |= BRIDGE_FLAGS_MASTER;
699eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		} else if (strcmp(*argv, "pvid") == 0) {
709eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich			vinfo.flags |= BRIDGE_VLAN_INFO_PVID;
719eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		} else if (strcmp(*argv, "untagged") == 0) {
729eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich			vinfo.flags |= BRIDGE_VLAN_INFO_UNTAGGED;
739eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		} else {
749eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich			if (matches(*argv, "help") == 0) {
759eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich				NEXT_ARG();
769eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich			}
779eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		}
789eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		argc--; argv++;
799eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	}
809eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
819eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	if (d == NULL || vid == -1) {
829eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		fprintf(stderr, "Device and VLAN ID are required arguments.\n");
8342ecedd4bae534fc688194a795eb4548c6530cdaRoopa Prabhu		return -1;
849eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	}
859eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
869eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	req.ifm.ifi_index = ll_name_to_index(d);
879eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	if (req.ifm.ifi_index == 0) {
889eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		fprintf(stderr, "Cannot find bridge device \"%s\"\n", d);
899eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		return -1;
909eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	}
919eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
929eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	if (vid >= 4096) {
939eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		fprintf(stderr, "Invalid VLAN ID \"%hu\"\n", vid);
949eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		return -1;
959eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	}
969eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
973ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu	if (vinfo.flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) {
983ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu		if (vid_end == -1 || vid_end >= 4096 || vid >= vid_end) {
993ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu			fprintf(stderr, "Invalid VLAN range \"%hu-%hu\"\n",
1003ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu				vid, vid_end);
1013ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu			return -1;
1023ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu		}
1033ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu		if (vinfo.flags & BRIDGE_VLAN_INFO_PVID) {
1043ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu			fprintf(stderr,
1053ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu				"pvid cannot be configured for a vlan range\n");
1063ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu			return -1;
1073ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu		}
1083ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu	}
1099eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
1109eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	afspec = addattr_nest(&req.n, sizeof(req), IFLA_AF_SPEC);
1119eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
1129eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	if (flags)
1139eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		addattr16(&req.n, sizeof(req), IFLA_BRIDGE_FLAGS, flags);
1149eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
1153ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu	vinfo.vid = vid;
1163ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu	if (vid_end != -1) {
1173ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu		/* send vlan range start */
1183ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu		addattr_l(&req.n, sizeof(req), IFLA_BRIDGE_VLAN_INFO, &vinfo,
1193ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu			  sizeof(vinfo));
1203ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu		vinfo.flags &= ~BRIDGE_VLAN_INFO_RANGE_BEGIN;
1213ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu
1223ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu		/* Now send the vlan range end */
1233ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu		vinfo.flags |= BRIDGE_VLAN_INFO_RANGE_END;
1243ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu		vinfo.vid = vid_end;
1253ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu		addattr_l(&req.n, sizeof(req), IFLA_BRIDGE_VLAN_INFO, &vinfo,
1263ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu			  sizeof(vinfo));
1273ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu	} else {
1283ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu		addattr_l(&req.n, sizeof(req), IFLA_BRIDGE_VLAN_INFO, &vinfo,
1293ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu			  sizeof(vinfo));
1303ac0d36ddde9715a8d027a919eb564f7b42c6c40Roopa Prabhu	}
1319eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
1329eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	addattr_nest_end(&req.n, afspec);
1339eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
134c079e121a73af5eb49e003b13607e8a690331df6Stephen Hemminger	if (rtnl_talk(&rth, &req.n, NULL, 0) < 0)
13542ecedd4bae534fc688194a795eb4548c6530cdaRoopa Prabhu		return -1;
1369eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
1379eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	return 0;
1389eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich}
1399eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
1409eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevichstatic int print_vlan(const struct sockaddr_nl *who,
1419eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		      struct nlmsghdr *n,
1429eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		      void *arg)
1439eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich{
1449eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	FILE *fp = arg;
1459eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	struct ifinfomsg *ifm = NLMSG_DATA(n);
1469eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	int len = n->nlmsg_len;
1479eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	struct rtattr * tb[IFLA_MAX+1];
1489eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
1499eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	if (n->nlmsg_type != RTM_NEWLINK) {
1509eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		fprintf(stderr, "Not RTM_NEWLINK: %08x %08x %08x\n",
1519eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich			n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
1529eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		return 0;
1539eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	}
1549eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
1559eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	len -= NLMSG_LENGTH(sizeof(*ifm));
1569eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	if (len < 0) {
1579eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
1589eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		return -1;
1599eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	}
1609eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
1619eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	if (ifm->ifi_family != AF_BRIDGE)
1629eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		return 0;
1639eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
1649eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	if (filter_index && filter_index != ifm->ifi_index)
1659eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		return 0;
1669eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
1679eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifm), len);
1689eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
1699eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	/* if AF_SPEC isn't there, vlan table is not preset for this port */
1709eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	if (!tb[IFLA_AF_SPEC]) {
1719eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		fprintf(fp, "%s\tNone\n", ll_index_to_name(ifm->ifi_index));
1729eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		return 0;
1739eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	} else {
1749eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		struct rtattr *i, *list = tb[IFLA_AF_SPEC];
1759eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		int rem = RTA_PAYLOAD(list);
1769eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
1779eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		fprintf(fp, "%s", ll_index_to_name(ifm->ifi_index));
1789eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		for (i = RTA_DATA(list); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
1799eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich			struct bridge_vlan_info *vinfo;
1809eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
1819eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich			if (i->rta_type != IFLA_BRIDGE_VLAN_INFO)
1829eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich				continue;
1839eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
1849eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich			vinfo = RTA_DATA(i);
185a2f7934dd04f8e762cc7a3f5f2e7a1edd4a93643Roopa Prabhu			if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_END)
186a2f7934dd04f8e762cc7a3f5f2e7a1edd4a93643Roopa Prabhu				fprintf(fp, "-%hu", vinfo->vid);
187a2f7934dd04f8e762cc7a3f5f2e7a1edd4a93643Roopa Prabhu			else
188a2f7934dd04f8e762cc7a3f5f2e7a1edd4a93643Roopa Prabhu				fprintf(fp, "\t %hu", vinfo->vid);
189a2f7934dd04f8e762cc7a3f5f2e7a1edd4a93643Roopa Prabhu			if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN)
190a2f7934dd04f8e762cc7a3f5f2e7a1edd4a93643Roopa Prabhu				continue;
1919eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich			if (vinfo->flags & BRIDGE_VLAN_INFO_PVID)
1929eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich				fprintf(fp, " PVID");
1939eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich			if (vinfo->flags & BRIDGE_VLAN_INFO_UNTAGGED)
1949eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich				fprintf(fp, " Egress Untagged");
1959eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich			fprintf(fp, "\n");
1969eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		}
1979eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	}
1989eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	fprintf(fp, "\n");
1999eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	fflush(fp);
2009eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	return 0;
2019eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich}
2029eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
2039eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevichstatic int vlan_show(int argc, char **argv)
2049eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich{
2059eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	char *filter_dev = NULL;
2069eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
2079eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	while (argc > 0) {
2089eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		if (strcmp(*argv, "dev") == 0) {
2099eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich			NEXT_ARG();
2109eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich			if (filter_dev)
2119eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich				duparg("dev", *argv);
2129eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich			filter_dev = *argv;
2139eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		}
2149eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		argc--; argv++;
2159eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	}
2169eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
2179eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	if (filter_dev) {
2189eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		if ((filter_index = if_nametoindex(filter_dev)) == 0) {
2199eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich			fprintf(stderr, "Cannot find device \"%s\"\n",
2209eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich			       filter_dev);
2219eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich			return -1;
2229eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		}
2239eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	}
2249eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
2259eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	if (rtnl_wilddump_req_filter(&rth, PF_BRIDGE, RTM_GETLINK,
226a2f7934dd04f8e762cc7a3f5f2e7a1edd4a93643Roopa Prabhu				    (compress_vlans ?
227a2f7934dd04f8e762cc7a3f5f2e7a1edd4a93643Roopa Prabhu				    RTEXT_FILTER_BRVLAN_COMPRESSED :
228a2f7934dd04f8e762cc7a3f5f2e7a1edd4a93643Roopa Prabhu				    RTEXT_FILTER_BRVLAN)) < 0) {
2299eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		perror("Cannont send dump request");
2309eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		exit(1);
2319eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	}
2329eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
2339eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	printf("port\tvlan ids\n");
2349eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	if (rtnl_dump_filter(&rth, print_vlan, stdout) < 0) {
2359eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		fprintf(stderr, "Dump ternminated\n");
2369eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		exit(1);
2379eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	}
2389eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
2399eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	return 0;
2409eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich}
2419eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
2429eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
2439eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevichint do_vlan(int argc, char **argv)
2449eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich{
2459eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	ll_init_map(&rth);
2469eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
2479eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	if (argc > 0) {
2489eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		if (matches(*argv, "add") == 0)
2499eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich			return vlan_modify(RTM_SETLINK, argc-1, argv+1);
2509eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		if (matches(*argv, "delete") == 0)
2519eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich			return vlan_modify(RTM_DELLINK, argc-1, argv+1);
2529eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		if (matches(*argv, "show") == 0 ||
2539eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		    matches(*argv, "lst") == 0 ||
2549eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		    matches(*argv, "list") == 0)
2559eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich			return vlan_show(argc-1, argv+1);
2569eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		if (matches(*argv, "help") == 0)
2579eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich			usage();
2589eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	} else
2599eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich		return vlan_show(0, NULL);
2609eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich
2619eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	fprintf(stderr, "Command \"%s\" is unknown, try \"bridge fdb help\".\n", *argv);
2629eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich	exit(-1);
2639eff0e5cc44770137fd0e383f80d0eaab948a03cVlad Yasevich}
264