xref: /freebsd/lib/libifconfig/libifconfig_bridge.c (revision e5539fb618cc73fa5a00fc82e35b2803dd1403b3)
1*e5539fb6SRyan Moeller /*
2*e5539fb6SRyan Moeller  * Copyright (c) 2020, Ryan Moeller <freqlabs@FreeBSD.org>
3*e5539fb6SRyan Moeller  *
4*e5539fb6SRyan Moeller  * Redistribution and use in source and binary forms, with or without
5*e5539fb6SRyan Moeller  * modification, are permitted provided that the following conditions
6*e5539fb6SRyan Moeller  * are met:
7*e5539fb6SRyan Moeller  * 1. Redistributions of source code must retain the above copyright
8*e5539fb6SRyan Moeller  *    notice, this list of conditions and the following disclaimer.
9*e5539fb6SRyan Moeller  * 2. Redistributions in binary form must reproduce the above copyright
10*e5539fb6SRyan Moeller  *    notice, this list of conditions and the following disclaimer in the
11*e5539fb6SRyan Moeller  *    documentation and/or other materials provided with the distribution.
12*e5539fb6SRyan Moeller  *
13*e5539fb6SRyan Moeller  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
14*e5539fb6SRyan Moeller  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15*e5539fb6SRyan Moeller  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16*e5539fb6SRyan Moeller  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
17*e5539fb6SRyan Moeller  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18*e5539fb6SRyan Moeller  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19*e5539fb6SRyan Moeller  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20*e5539fb6SRyan Moeller  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21*e5539fb6SRyan Moeller  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22*e5539fb6SRyan Moeller  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23*e5539fb6SRyan Moeller  * SUCH DAMAGE.
24*e5539fb6SRyan Moeller  *
25*e5539fb6SRyan Moeller  * $FreeBSD$
26*e5539fb6SRyan Moeller  */
27*e5539fb6SRyan Moeller #include <sys/param.h>
28*e5539fb6SRyan Moeller #include <sys/ioctl.h>
29*e5539fb6SRyan Moeller 
30*e5539fb6SRyan Moeller #include <net/ethernet.h>
31*e5539fb6SRyan Moeller #include <net/if.h>
32*e5539fb6SRyan Moeller #include <net/if_bridgevar.h>
33*e5539fb6SRyan Moeller #include <net/route.h>
34*e5539fb6SRyan Moeller 
35*e5539fb6SRyan Moeller #include <assert.h>
36*e5539fb6SRyan Moeller #include <errno.h>
37*e5539fb6SRyan Moeller #include <stdbool.h>
38*e5539fb6SRyan Moeller #include <stdlib.h>
39*e5539fb6SRyan Moeller #include <string.h>
40*e5539fb6SRyan Moeller 
41*e5539fb6SRyan Moeller #include "libifconfig.h"
42*e5539fb6SRyan Moeller #include "libifconfig_internal.h"
43*e5539fb6SRyan Moeller 
44*e5539fb6SRyan Moeller /* Internal structure used for allocations and frees */
45*e5539fb6SRyan Moeller struct _ifconfig_bridge_status {
46*e5539fb6SRyan Moeller 	struct ifconfig_bridge_status inner;	/* wrapped bridge status */
47*e5539fb6SRyan Moeller 	struct ifbropreq params;		/* operational parameters */
48*e5539fb6SRyan Moeller };
49*e5539fb6SRyan Moeller 
50*e5539fb6SRyan Moeller static int
51*e5539fb6SRyan Moeller ifconfig_bridge_ioctlwrap(ifconfig_handle_t *h, const char *name,
52*e5539fb6SRyan Moeller     unsigned long cmd, void *arg, size_t arglen, bool set)
53*e5539fb6SRyan Moeller {
54*e5539fb6SRyan Moeller 	struct ifdrv ifd = { 0 };
55*e5539fb6SRyan Moeller 	unsigned long req = set ? SIOCSDRVSPEC : SIOCGDRVSPEC;
56*e5539fb6SRyan Moeller 
57*e5539fb6SRyan Moeller 	strlcpy(ifd.ifd_name, name, sizeof(ifd.ifd_name));
58*e5539fb6SRyan Moeller 	ifd.ifd_cmd = cmd;
59*e5539fb6SRyan Moeller 	ifd.ifd_data = arg;
60*e5539fb6SRyan Moeller 	ifd.ifd_len = arglen;
61*e5539fb6SRyan Moeller 
62*e5539fb6SRyan Moeller 	return (ifconfig_ioctlwrap(h, AF_LOCAL, req, &ifd));
63*e5539fb6SRyan Moeller }
64*e5539fb6SRyan Moeller 
65*e5539fb6SRyan Moeller int
66*e5539fb6SRyan Moeller ifconfig_bridge_get_bridge_status(ifconfig_handle_t *h,
67*e5539fb6SRyan Moeller     const char *name, struct ifconfig_bridge_status **bridgep)
68*e5539fb6SRyan Moeller {
69*e5539fb6SRyan Moeller 	struct ifbifconf members;
70*e5539fb6SRyan Moeller 	struct ifbrparam cache_param;
71*e5539fb6SRyan Moeller 	struct _ifconfig_bridge_status *bridge;
72*e5539fb6SRyan Moeller 	char *buf;
73*e5539fb6SRyan Moeller 
74*e5539fb6SRyan Moeller 	*bridgep = NULL;
75*e5539fb6SRyan Moeller 
76*e5539fb6SRyan Moeller 	bridge = calloc(1, sizeof(struct _ifconfig_bridge_status));
77*e5539fb6SRyan Moeller 	if (bridge == NULL) {
78*e5539fb6SRyan Moeller 		h->error.errtype = OTHER;
79*e5539fb6SRyan Moeller 		h->error.errcode = ENOMEM;
80*e5539fb6SRyan Moeller 		return (-1);
81*e5539fb6SRyan Moeller 	}
82*e5539fb6SRyan Moeller 	bridge->inner.params = &bridge->params;
83*e5539fb6SRyan Moeller 
84*e5539fb6SRyan Moeller 	if (ifconfig_bridge_ioctlwrap(h, name, BRDGGCACHE,
85*e5539fb6SRyan Moeller 	    &cache_param, sizeof(cache_param), false) != 0) {
86*e5539fb6SRyan Moeller 		free(bridge);
87*e5539fb6SRyan Moeller 		return (-1);
88*e5539fb6SRyan Moeller 	}
89*e5539fb6SRyan Moeller 	bridge->inner.cache_size = cache_param.ifbrp_csize;
90*e5539fb6SRyan Moeller 
91*e5539fb6SRyan Moeller 	if (ifconfig_bridge_ioctlwrap(h, name, BRDGGTO,
92*e5539fb6SRyan Moeller 	    &cache_param, sizeof(cache_param), false) != 0) {
93*e5539fb6SRyan Moeller 		free(bridge);
94*e5539fb6SRyan Moeller 		return (-1);
95*e5539fb6SRyan Moeller 	}
96*e5539fb6SRyan Moeller 	bridge->inner.cache_lifetime = cache_param.ifbrp_ctime;
97*e5539fb6SRyan Moeller 
98*e5539fb6SRyan Moeller 	if (ifconfig_bridge_ioctlwrap(h, name, BRDGPARAM,
99*e5539fb6SRyan Moeller 	    &bridge->params, sizeof(bridge->params), false) != 0) {
100*e5539fb6SRyan Moeller 		free(bridge);
101*e5539fb6SRyan Moeller 		return (-1);
102*e5539fb6SRyan Moeller 	}
103*e5539fb6SRyan Moeller 
104*e5539fb6SRyan Moeller 	members.ifbic_buf = NULL;
105*e5539fb6SRyan Moeller 	for (size_t len = 8192;
106*e5539fb6SRyan Moeller 	    (buf = realloc(members.ifbic_buf, len)) != NULL;
107*e5539fb6SRyan Moeller 	    len *= 2) {
108*e5539fb6SRyan Moeller 		members.ifbic_buf = buf;
109*e5539fb6SRyan Moeller 		members.ifbic_len = len;
110*e5539fb6SRyan Moeller 		if (ifconfig_bridge_ioctlwrap(h, name, BRDGGIFS,
111*e5539fb6SRyan Moeller 		    &members, sizeof(members), false) != 0) {
112*e5539fb6SRyan Moeller 			free(buf);
113*e5539fb6SRyan Moeller 			free(bridge);
114*e5539fb6SRyan Moeller 			return (-1);
115*e5539fb6SRyan Moeller 		}
116*e5539fb6SRyan Moeller 		if (members.ifbic_len <= len)
117*e5539fb6SRyan Moeller 			break;
118*e5539fb6SRyan Moeller 	}
119*e5539fb6SRyan Moeller 	if (buf == NULL) {
120*e5539fb6SRyan Moeller 		free(members.ifbic_buf);
121*e5539fb6SRyan Moeller 		free(bridge);
122*e5539fb6SRyan Moeller 		h->error.errtype = OTHER;
123*e5539fb6SRyan Moeller 		h->error.errcode = ENOMEM;
124*e5539fb6SRyan Moeller 		return (-1);
125*e5539fb6SRyan Moeller 	}
126*e5539fb6SRyan Moeller 	bridge->inner.members = members.ifbic_req;
127*e5539fb6SRyan Moeller 	bridge->inner.members_count =
128*e5539fb6SRyan Moeller 	    members.ifbic_len / sizeof(*members.ifbic_req);
129*e5539fb6SRyan Moeller 
130*e5539fb6SRyan Moeller 	*bridgep = &bridge->inner;
131*e5539fb6SRyan Moeller 
132*e5539fb6SRyan Moeller 	return (0);
133*e5539fb6SRyan Moeller }
134*e5539fb6SRyan Moeller 
135*e5539fb6SRyan Moeller void
136*e5539fb6SRyan Moeller ifconfig_bridge_free_bridge_status(struct ifconfig_bridge_status *bridge)
137*e5539fb6SRyan Moeller {
138*e5539fb6SRyan Moeller 	if (bridge != NULL) {
139*e5539fb6SRyan Moeller 		free(bridge->members);
140*e5539fb6SRyan Moeller 		free(bridge);
141*e5539fb6SRyan Moeller 	}
142*e5539fb6SRyan Moeller }
143