xref: /freebsd/sbin/ifconfig/iflagg.c (revision 0bb263df82e129f5f8c82da6deb55dfe10daa677)
1 /*-
2  */
3 
4 #ifndef lint
5 static const char rcsid[] =
6   "$FreeBSD$";
7 #endif /* not lint */
8 
9 #include <sys/param.h>
10 #include <sys/ioctl.h>
11 #include <sys/socket.h>
12 #include <sys/sockio.h>
13 
14 #include <stdlib.h>
15 #include <unistd.h>
16 
17 #include <net/ethernet.h>
18 #include <net/if.h>
19 #include <net/if_lagg.h>
20 #include <net/route.h>
21 
22 #include <ctype.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <err.h>
28 #include <errno.h>
29 
30 #include "ifconfig.h"
31 
32 static void
33 setlaggport(const char *val, int d, int s, const struct afswtch *afp)
34 {
35 	struct lagg_reqport rp;
36 
37 	bzero(&rp, sizeof(rp));
38 	strlcpy(rp.rp_ifname, name, sizeof(rp.rp_ifname));
39 	strlcpy(rp.rp_portname, val, sizeof(rp.rp_portname));
40 
41 	if (ioctl(s, SIOCSLAGGPORT, &rp))
42 		err(1, "SIOCSLAGGPORT");
43 }
44 
45 static void
46 unsetlaggport(const char *val, int d, int s, const struct afswtch *afp)
47 {
48 	struct lagg_reqport rp;
49 
50 	bzero(&rp, sizeof(rp));
51 	strlcpy(rp.rp_ifname, name, sizeof(rp.rp_ifname));
52 	strlcpy(rp.rp_portname, val, sizeof(rp.rp_portname));
53 
54 	if (ioctl(s, SIOCSLAGGDELPORT, &rp))
55 		err(1, "SIOCSLAGGDELPORT");
56 }
57 
58 static void
59 setlaggproto(const char *val, int d, int s, const struct afswtch *afp)
60 {
61 	struct lagg_protos lpr[] = LAGG_PROTOS;
62 	struct lagg_reqall ra;
63 	int i;
64 
65 	bzero(&ra, sizeof(ra));
66 	ra.ra_proto = LAGG_PROTO_MAX;
67 
68 	for (i = 0; i < (sizeof(lpr) / sizeof(lpr[0])); i++) {
69 		if (strcmp(val, lpr[i].lpr_name) == 0) {
70 			ra.ra_proto = lpr[i].lpr_proto;
71 			break;
72 		}
73 	}
74 	if (ra.ra_proto == LAGG_PROTO_MAX)
75 		errx(1, "Invalid aggregation protocol: %s", val);
76 
77 	strlcpy(ra.ra_ifname, name, sizeof(ra.ra_ifname));
78 	if (ioctl(s, SIOCSLAGG, &ra) != 0)
79 		err(1, "SIOCSLAGG");
80 }
81 
82 static void
83 lagg_status(int s)
84 {
85 	struct lagg_protos lpr[] = LAGG_PROTOS;
86 	struct lagg_reqport rp, rpbuf[LAGG_MAX_PORTS];
87 	struct lagg_reqall ra;
88 	const char *proto = "<unknown>";
89 	int i, isport = 0;
90 
91 	bzero(&rp, sizeof(rp));
92 	bzero(&ra, sizeof(ra));
93 
94 	strlcpy(rp.rp_ifname, name, sizeof(rp.rp_ifname));
95 	strlcpy(rp.rp_portname, name, sizeof(rp.rp_portname));
96 
97 	if (ioctl(s, SIOCGLAGGPORT, &rp) == 0)
98 		isport = 1;
99 
100 	strlcpy(ra.ra_ifname, name, sizeof(ra.ra_ifname));
101 	ra.ra_size = sizeof(rpbuf);
102 	ra.ra_port = rpbuf;
103 
104 	if (ioctl(s, SIOCGLAGG, &ra) == 0) {
105 		for (i = 0; i < (sizeof(lpr) / sizeof(lpr[0])); i++) {
106 			if (ra.ra_proto == lpr[i].lpr_proto) {
107 				proto = lpr[i].lpr_name;
108 				break;
109 			}
110 		}
111 
112 		printf("\tlagg: laggproto %s", proto);
113 		if (isport)
114 			printf(" laggdev %s", rp.rp_ifname);
115 		putchar('\n');
116 
117 		for (i = 0; i < ra.ra_ports; i++) {
118 			printf("\t\tlaggport %s ", rpbuf[i].rp_portname);
119 			printb("", rpbuf[i].rp_flags, LAGG_PORT_BITS);
120 			putchar('\n');
121 		}
122 
123 		if (0 /* XXX */) {
124 			printf("\tsupported aggregation protocols:\n");
125 			for (i = 0; i < (sizeof(lpr) / sizeof(lpr[0])); i++)
126 				printf("\t\tlaggproto %s\n", lpr[i].lpr_name);
127 		}
128 	} else if (isport)
129 		printf("\tlagg: laggdev %s\n", rp.rp_ifname);
130 }
131 
132 static struct cmd lagg_cmds[] = {
133 	DEF_CMD_ARG("laggport",		setlaggport),
134 	DEF_CMD_ARG("-laggport",	unsetlaggport),
135 	DEF_CMD_ARG("laggproto",	setlaggproto),
136 };
137 static struct afswtch af_lagg = {
138 	.af_name	= "af_lagg",
139 	.af_af		= AF_UNSPEC,
140 	.af_other_status = lagg_status,
141 };
142 
143 static __constructor void
144 lagg_ctor(void)
145 {
146 #define	N(a)	(sizeof(a) / sizeof(a[0]))
147 	int i;
148 
149 	for (i = 0; i < N(lagg_cmds);  i++)
150 		cmd_register(&lagg_cmds[i]);
151 	af_register(&af_lagg);
152 #undef N
153 }
154