1 /*
2  * virebtables.c: Helper APIs for managing ebtables
3  *
4  * Copyright (C) 2007-2014 Red Hat, Inc.
5  * Copyright (C) 2009 IBM Corp.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library.  If not, see
19  * <http://www.gnu.org/licenses/>.
20  */
21 
22 #include <config.h>
23 
24 #include "internal.h"
25 #include "virebtables.h"
26 #include "viralloc.h"
27 #include "virerror.h"
28 #include "virlog.h"
29 #include "virstring.h"
30 #include "virfirewall.h"
31 
32 #define VIR_FROM_THIS VIR_FROM_NONE
33 
34 VIR_LOG_INIT("util.ebtables");
35 
36 struct _ebtablesContext
37 {
38     char *chain;
39 };
40 
41 enum {
42     ADD = 0,
43     REMOVE,
44 };
45 
46 /**
47  * ebtablesContextNew:
48  *
49  * Create a new ebtable context
50  *
51  * Returns a pointer to the new structure or NULL in case of error
52  */
53 ebtablesContext *
ebtablesContextNew(const char * driver)54 ebtablesContextNew(const char *driver)
55 {
56     ebtablesContext *ctx = NULL;
57 
58     ctx = g_new0(ebtablesContext, 1);
59 
60     ctx->chain = g_strdup_printf("libvirt_%s_FORWARD", driver);
61 
62     return ctx;
63 }
64 
65 /**
66  * ebtablesContextFree:
67  * @ctx: pointer to the EB table context
68  *
69  * Free the resources associated with an EB table context
70  */
71 void
ebtablesContextFree(ebtablesContext * ctx)72 ebtablesContextFree(ebtablesContext *ctx)
73 {
74     if (!ctx)
75         return;
76     g_free(ctx->chain);
77     g_free(ctx);
78 }
79 
80 
81 int
ebtablesAddForwardPolicyReject(ebtablesContext * ctx)82 ebtablesAddForwardPolicyReject(ebtablesContext *ctx)
83 {
84     g_autoptr(virFirewall) fw = virFirewallNew();
85 
86     virFirewallStartTransaction(fw, VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS);
87     virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET,
88                        "--new-chain", ctx->chain,
89                        NULL);
90     virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET,
91                        "--insert", "FORWARD",
92                        "--jump", ctx->chain, NULL);
93 
94     virFirewallStartTransaction(fw, 0);
95     virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET,
96                        "-P", ctx->chain, "DROP",
97                        NULL);
98 
99     return virFirewallApply(fw);
100 }
101 
102 
103 /*
104  * Allow all traffic destined to the bridge, with a valid network address
105  */
106 static int
ebtablesForwardAllowIn(ebtablesContext * ctx,const char * iface,const char * macaddr,int action)107 ebtablesForwardAllowIn(ebtablesContext *ctx,
108                        const char *iface,
109                        const char *macaddr,
110                        int action)
111 {
112     g_autoptr(virFirewall) fw = virFirewallNew();
113 
114     virFirewallStartTransaction(fw, 0);
115     virFirewallAddRule(fw, VIR_FIREWALL_LAYER_ETHERNET,
116                        action == ADD ? "--insert" : "--delete",
117                        ctx->chain,
118                        "--in-interface", iface,
119                        "--source", macaddr,
120                        "--jump", "ACCEPT",
121                        NULL);
122 
123     return virFirewallApply(fw);
124 }
125 
126 /**
127  * ebtablesAddForwardAllowIn:
128  * @ctx: pointer to the EB table context
129  * @iface: the output interface name
130  * @physdev: the physical input device or NULL
131  *
132  * Add rules to the EB table context to allow the traffic on
133  * @physdev device to be forwarded to interface @iface. This allows
134  * the inbound traffic on a bridge.
135  *
136  * Returns 0 in case of success or an error code otherwise
137  */
138 int
ebtablesAddForwardAllowIn(ebtablesContext * ctx,const char * iface,const virMacAddr * mac)139 ebtablesAddForwardAllowIn(ebtablesContext *ctx,
140                           const char *iface,
141                           const virMacAddr *mac)
142 {
143     char macaddr[VIR_MAC_STRING_BUFLEN];
144 
145     virMacAddrFormat(mac, macaddr);
146     return ebtablesForwardAllowIn(ctx, iface, macaddr, ADD);
147 }
148 
149 /**
150  * ebtablesRemoveForwardAllowIn:
151  * @ctx: pointer to the EB table context
152  * @iface: the output interface name
153  * @physdev: the physical input device or NULL
154  *
155  * Remove rules from the EB table context hence forbidding the traffic
156  * on the @physdev device to be forwarded to interface @iface. This
157  * stops the inbound traffic on a bridge.
158  *
159  * Returns 0 in case of success or an error code otherwise
160  */
161 int
ebtablesRemoveForwardAllowIn(ebtablesContext * ctx,const char * iface,const virMacAddr * mac)162 ebtablesRemoveForwardAllowIn(ebtablesContext *ctx,
163                              const char *iface,
164                              const virMacAddr *mac)
165 {
166     char macaddr[VIR_MAC_STRING_BUFLEN];
167 
168     virMacAddrFormat(mac, macaddr);
169     return ebtablesForwardAllowIn(ctx, iface, macaddr, REMOVE);
170 }
171