230
230
if ((item->flags & NWFILTER_ENTRY_ITEM_FLAG_HAS_VAR)) {
233
val = virNWFilterVarCombIterGetVarValue(vars, item->var);
233
val = virNWFilterVarCombIterGetVarValue(vars, item->varAccess);
235
235
/* error has been reported */
239
239
if (!virStrcpy(buf, val, bufsize)) {
242
varName = virNWFilterVarAccessGetVarName(item->varAccess);
240
243
virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
241
_("Buffer to small to print MAC address "
244
_("Buffer too small to print variable "
245
"'%s' into"), varName);
262
if (printVar(vars, buf, bufsize, item, &done))
264
if (printVar(vars, buf, bufsize, item, &done) < 0)
269
271
case DATATYPE_IPADDR:
270
272
data = virSocketAddrFormat(&item->u.ipaddr);
273
275
if (snprintf(buf, bufsize, "%s", data) >= bufsize) {
274
276
virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, "%s",
275
277
_("buffer too small for IP address"));
282
284
case DATATYPE_IPV6ADDR:
283
285
data = virSocketAddrFormat(&item->u.ipaddr);
287
289
if (snprintf(buf, bufsize, "%s", data) >= bufsize) {
288
290
virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, "%s",
289
291
_("buffer too small for IPv6 address"));
298
300
if (bufsize < VIR_MAC_STRING_BUFLEN) {
299
301
virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, "%s",
300
302
_("Buffer too small for MAC address"));
304
virFormatMacAddr(item->u.macaddr.addr, buf);
306
virMacAddrFormat(item->u.macaddr.addr, buf);
307
309
case DATATYPE_IPV6MASK:
340
342
item->u.u8) >= bufsize) {
341
343
virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, "%s",
342
344
_("Buffer too small for uint8 type"));
348
350
virNWFilterReportError(VIR_ERR_INTERNAL_ERROR,
349
351
_("Unhandled datatype %x"), item->datatype);
442
444
if (HAS_ENTRY_ITEM(ðHdr->dataSrcMACAddr)) {
443
445
if (printDataType(vars,
444
446
macaddr, sizeof(macaddr),
445
ðHdr->dataSrcMACAddr))
447
ðHdr->dataSrcMACAddr) < 0)
448
450
virBufferAsprintf(buf,
454
456
if (HAS_ENTRY_ITEM(ðHdr->dataSrcMACMask)) {
455
457
if (printDataType(vars,
456
458
macaddr, sizeof(macaddr),
457
ðHdr->dataSrcMACMask))
459
ðHdr->dataSrcMACMask) < 0)
460
462
virBufferAsprintf(buf,
466
468
if (HAS_ENTRY_ITEM(ðHdr->dataDstMACAddr)) {
467
469
if (printDataType(vars,
468
470
macaddr, sizeof(macaddr),
469
ðHdr->dataDstMACAddr))
471
ðHdr->dataDstMACAddr) < 0)
472
474
virBufferAsprintf(buf,
478
480
if (HAS_ENTRY_ITEM(ðHdr->dataDstMACMask)) {
479
481
if (printDataType(vars,
480
482
macaddr, sizeof(macaddr),
481
ðHdr->dataDstMACMask))
483
ðHdr->dataDstMACMask) < 0)
484
486
virBufferAsprintf(buf,
1106
1108
if (HAS_ENTRY_ITEM(&portData->dataSrcPortStart)) {
1107
1109
if (printDataType(vars,
1108
1110
portstr, sizeof(portstr),
1109
&portData->dataSrcPortStart))
1111
&portData->dataSrcPortStart) < 0)
1112
1114
virBufferAsprintf(buf,
1118
1120
if (HAS_ENTRY_ITEM(&portData->dataSrcPortEnd)) {
1119
1121
if (printDataType(vars,
1120
1122
portstr, sizeof(portstr),
1121
&portData->dataSrcPortEnd))
1123
&portData->dataSrcPortEnd) < 0)
1124
1126
virBufferAsprintf(buf,
1130
1132
if (HAS_ENTRY_ITEM(&portData->dataDstPortStart)) {
1131
1133
if (printDataType(vars,
1132
1134
portstr, sizeof(portstr),
1133
&portData->dataDstPortStart))
1135
&portData->dataDstPortStart) < 0)
1136
1138
virBufferAsprintf(buf,
1142
1144
if (HAS_ENTRY_ITEM(&portData->dataDstPortEnd)) {
1143
1145
if (printDataType(vars,
1144
1146
portstr, sizeof(portstr),
1145
&portData->dataDstPortEnd))
1147
&portData->dataDstPortEnd) < 0)
1148
1150
virBufferAsprintf(buf,
1268
1270
if (iptablesHandlePortData(&buf,
1270
1272
&rule->p.tcpHdrFilter.portData,
1274
1276
if (HAS_ENTRY_ITEM(&rule->p.tcpHdrFilter.dataTCPOption)) {
1275
1277
if (printDataType(vars,
1276
1278
number, sizeof(number),
1277
&rule->p.tcpHdrFilter.dataTCPOption))
1279
&rule->p.tcpHdrFilter.dataTCPOption) < 0)
1280
1282
virBufferAsprintf(&buf,
1706
1708
if (create && (rule->flags & IPTABLES_STATE_FLAGS)) {
1707
if (printStateMatchFlags(rule->flags, &matchState))
1709
if (printStateMatchFlags(rule->flags, &matchState) < 0)
1711
1713
chainPrefix[1] = CHAINPREFIX_HOST_IN_TEMP;
1738
1740
if (create && (rule->flags & IPTABLES_STATE_FLAGS)) {
1739
if (printStateMatchFlags(rule->flags, &matchState))
1741
if (printStateMatchFlags(rule->flags, &matchState) < 0)
1743
1745
chainPrefix[1] = CHAINPREFIX_HOST_OUT_TEMP;
1963
1965
if (ebtablesHandleEthHdr(&buf,
1965
1967
&rule->p.ethHdrFilter.ethHdr,
1969
1971
if (HAS_ENTRY_ITEM(&rule->p.ethHdrFilter.dataProtocolID)) {
1970
1972
if (printDataTypeAsHex(vars,
1971
1973
number, sizeof(number),
1972
&rule->p.ethHdrFilter.dataProtocolID))
1974
&rule->p.ethHdrFilter.dataProtocolID) < 0)
1974
1976
virBufferAsprintf(&buf,
1998
2000
if (HAS_ENTRY_ITEM(&rule->p.STRUCT.ITEM)) { \
1999
2001
if (printDataType(vars, \
2000
2002
field, sizeof(field), \
2001
&rule->p.STRUCT.ITEM)) \
2003
&rule->p.STRUCT.ITEM) < 0) \
2002
2004
goto err_exit; \
2003
2005
virBufferAsprintf(&buf, \
2004
2006
" " CLI " %s %s", \
2010
2012
if (HAS_ENTRY_ITEM(&rule->p.STRUCT.ITEM)) { \
2011
2013
if (printDataType(vars, \
2012
2014
field, sizeof(field), \
2013
&rule->p.STRUCT.ITEM)) \
2015
&rule->p.STRUCT.ITEM) < 0) \
2014
2016
goto err_exit; \
2015
2017
virBufferAsprintf(&buf, \
2016
2018
" " CLI " %s %s", \
2019
2021
if (HAS_ENTRY_ITEM(&rule->p.STRUCT.ITEM_HI)) { \
2020
2022
if (printDataType(vars, \
2021
2023
field, sizeof(field), \
2022
&rule->p.STRUCT.ITEM_HI)) \
2024
&rule->p.STRUCT.ITEM_HI) < 0) \
2023
2025
goto err_exit; \
2024
2026
virBufferAsprintf(&buf, SEP "%s", field); \
2055
2057
if (ebtablesHandleEthHdr(&buf,
2057
2059
&rule->p.stpHdrFilter.ethHdr,
2061
2063
virBufferAddLit(&buf, " -d " NWFILTER_MAC_BGA);
2092
2094
if (ebtablesHandleEthHdr(&buf,
2094
2096
&rule->p.arpHdrFilter.ethHdr,
2098
2100
virBufferAsprintf(&buf, " -p 0x%x",
2125
2127
if (HAS_ENTRY_ITEM(&rule->p.arpHdrFilter.dataProtocolType)) {
2126
2128
if (printDataTypeAsHex(vars,
2127
2129
number, sizeof(number),
2128
&rule->p.arpHdrFilter.dataProtocolType))
2130
&rule->p.arpHdrFilter.dataProtocolType) < 0)
2130
2132
virBufferAsprintf(&buf,
2131
2133
" --arp-ptype %s %s",
2162
2164
if (HAS_ENTRY_ITEM(&rule->p.arpHdrFilter.dataARPSrcMACAddr)) {
2163
2165
if (printDataType(vars,
2164
2166
macaddr, sizeof(macaddr),
2165
&rule->p.arpHdrFilter.dataARPSrcMACAddr))
2167
&rule->p.arpHdrFilter.dataARPSrcMACAddr) < 0)
2168
2170
virBufferAsprintf(&buf,
2175
2177
if (HAS_ENTRY_ITEM(&rule->p.arpHdrFilter.dataARPDstMACAddr)) {
2176
2178
if (printDataType(vars,
2177
2179
macaddr, sizeof(macaddr),
2178
&rule->p.arpHdrFilter.dataARPDstMACAddr))
2180
&rule->p.arpHdrFilter.dataARPDstMACAddr) < 0)
2181
2183
virBufferAsprintf(&buf,
2319
2327
if (HAS_ENTRY_ITEM(&rule->p.ipHdrFilter.ipHdr.dataDSCP)) {
2320
2328
if (printDataTypeAsHex(vars,
2321
2329
number, sizeof(number),
2322
&rule->p.ipHdrFilter.ipHdr.dataDSCP))
2330
&rule->p.ipHdrFilter.ipHdr.dataDSCP) < 0)
2325
2333
virBufferAsprintf(&buf,
2346
2354
if (HAS_ENTRY_ITEM(&rule->p.ipv6HdrFilter.ipHdr.dataSrcIPAddr)) {
2347
2355
if (printDataType(vars,
2348
2356
ipv6addr, sizeof(ipv6addr),
2349
&rule->p.ipv6HdrFilter.ipHdr.dataSrcIPAddr))
2357
&rule->p.ipv6HdrFilter.ipHdr.dataSrcIPAddr) < 0)
2352
2360
virBufferAsprintf(&buf,
2510
2524
* Convert a single rule into its representation for later instantiation
2512
2526
* Returns 0 in case of success with the result stored in the data structure
2513
* pointed to by res, != 0 otherwise.
2527
* pointed to by res, -1 otherwise
2516
2530
ebiptablesCreateRuleInstance(enum virDomainNetType nettype ATTRIBUTE_UNUSED,
2619
2633
* iterate over all combinations of the variables' values and instantiate
2620
2634
* the filtering rule with each combination.
2622
vciter = virNWFilterVarCombIterCreate(vars, rule->vars, rule->nvars);
2636
vciter = virNWFilterVarCombIterCreate(vars,
2637
rule->varAccess, rule->nVarAccess);
2627
2642
rc = ebiptablesCreateRuleInstance(nettype,
2873
2888
protostr = strdup("");
2875
2890
case L2_PROTO_STP_IDX:
2876
virAsprintf(&protostr, "-d " NWFILTER_MAC_BGA " ");
2891
ignore_value(virAsprintf(&protostr, "-d " NWFILTER_MAC_BGA " "));
2879
virAsprintf(&protostr, "-p 0x%04x ", l3_protocols[protoidx].attr);
2894
ignore_value(virAsprintf(&protostr, "-p 0x%04x ",
2895
l3_protocols[protoidx].attr));
3092
3108
* @macaddr: MAC address the VM is using in packets sent through the
3095
* Returns 0 on success, 1 on failure with the rules removed
3111
* Returns 0 on success, -1 on failure with the rules removed
3097
3113
* Apply basic filtering rules on the given interface
3098
3114
* - filtering for MAC address spoofing
3111
3127
virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3112
3128
_("cannot create rules since ebtables tool is "
3117
virFormatMacAddr(macaddr, macaddr_str);
3133
virMacAddrFormat(macaddr, macaddr_str);
3119
3135
ebiptablesAllTeardown(ifname);
3180
3196
* @ifname: name of the backend-interface to which to apply the rules
3181
3197
* @macaddr: MAC address the VM is using in packets sent through the
3183
* @dhcpserver: The DHCP server from which the VM may receive traffic
3199
* @dhcpsrvrs: The DHCP server(s) from which the VM may receive traffic
3184
3200
* from; may be NULL
3185
3201
* @leaveTemporary: Whether to leave the table names with their temporary
3186
3202
* names (true) or also perform the renaming to their final names as
3187
3203
* part of this call (false)
3189
* Returns 0 on success, 1 on failure with the rules removed
3205
* Returns 0 on success, -1 on failure with the rules removed
3191
3207
* Apply filtering rules so that the VM can only send and receive
3192
3208
* DHCP traffic and nothing else.
3195
3211
ebtablesApplyDHCPOnlyRules(const char *ifname,
3196
3212
const unsigned char *macaddr,
3197
const char *dhcpserver,
3213
virNWFilterVarValuePtr dhcpsrvrs,
3198
3214
bool leaveTemporary)
3200
3216
virBuffer buf = VIR_BUFFER_INITIALIZER;
3201
3217
char chain_in [MAX_CHAINNAME_LENGTH],
3202
3218
chain_out[MAX_CHAINNAME_LENGTH];
3203
3219
char macaddr_str[VIR_MAC_STRING_BUFLEN];
3204
char *srcIPParam = NULL;
3220
unsigned int idx = 0;
3221
unsigned int num_dhcpsrvrs;
3206
3223
if (!ebtables_cmd_path) {
3207
3224
virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, "%s",
3208
3225
_("cannot create rules since ebtables tool is "
3214
virBufferAsprintf(&buf, " --ip-src %s", dhcpserver);
3215
if (virBufferError(&buf))
3217
srcIPParam = virBufferContentAndReset(&buf);
3220
virFormatMacAddr(macaddr, macaddr_str);
3230
virMacAddrFormat(macaddr, macaddr_str);
3222
3232
ebiptablesAllTeardown(ifname);
3232
3242
virBufferAsprintf(&buf,
3233
3243
CMD_DEF("$EBT -t nat -A %s"
3234
" -s %s -d Broadcast "
3235
3245
" -p ipv4 --ip-protocol udp"
3236
" --ip-src 0.0.0.0 --ip-dst 255.255.255.255"
3237
3246
" --ip-sport 68 --ip-dport 67"
3238
3247
" -j ACCEPT") CMD_SEPARATOR
3252
3261
CMD_STOPONERR(1));
3254
virBufferAsprintf(&buf,
3255
CMD_DEF("$EBT -t nat -A %s"
3257
" -p ipv4 --ip-protocol udp"
3259
" --ip-sport 67 --ip-dport 68"
3260
" -j ACCEPT") CMD_SEPARATOR
3266
srcIPParam != NULL ? srcIPParam : "",
3263
num_dhcpsrvrs = (dhcpsrvrs != NULL)
3264
? virNWFilterVarValueGetCardinality(dhcpsrvrs)
3268
char *srcIPParam = NULL;
3270
if (idx < num_dhcpsrvrs) {
3271
const char *dhcpserver;
3273
dhcpserver = virNWFilterVarValueGetNthValue(dhcpsrvrs, idx);
3275
if (virAsprintf(&srcIPParam, "--ip-src %s", dhcpserver) < 0) {
3276
virReportOOMError();
3277
goto tear_down_tmpebchains;
3281
virBufferAsprintf(&buf,
3282
CMD_DEF("$EBT -t nat -A %s"
3284
" -p ipv4 --ip-protocol udp"
3286
" --ip-sport 67 --ip-dport 68"
3287
" -j ACCEPT") CMD_SEPARATOR
3293
srcIPParam != NULL ? srcIPParam : "",
3296
VIR_FREE(srcIPParam);
3298
if (idx == num_dhcpsrvrs)
3269
3304
virBufferAsprintf(&buf,
3270
3305
CMD_DEF("$EBT -t nat -A %s -j DROP") CMD_SEPARATOR
3308
3339
* @ifname: name of the backend-interface to which to apply the rules
3310
* Returns 0 on success, 1 on failure with the rules removed
3341
* Returns 0 on success, -1 on failure with the rules removed
3312
3343
* Apply filtering rules so that the VM cannot receive or send traffic.
3575
3609
const char *name = inst[i]->neededProtocolChain;
3576
3610
if (inst[i]->chainprefix == CHAINPREFIX_HOST_IN_TEMP) {
3577
3611
if (virHashUpdateEntry(chains_in_set, name,
3578
&inst[i]->chainPriority)) {
3612
&inst[i]->chainPriority) < 0) {
3579
3613
virReportOOMError();
3580
3614
goto exit_free_sets;
3583
3617
if (virHashUpdateEntry(chains_out_set, name,
3584
&inst[i]->chainPriority)) {
3618
&inst[i]->chainPriority) < 0) {
3585
3619
virReportOOMError();
3586
3620
goto exit_free_sets;
3605
3639
NWFILTER_SET_EBTABLES_SHELLVAR(&buf);
3607
3641
/* create needed chains */
3608
if (ebtablesCreateTmpRootAndSubChains(&buf, ifname, chains_in_set , 1,
3609
&ebtChains, &nEbtChains) ||
3610
ebtablesCreateTmpRootAndSubChains(&buf, ifname, chains_out_set, 0,
3611
&ebtChains, &nEbtChains)) {
3642
if ((virHashSize(chains_in_set) > 0 &&
3643
ebtablesCreateTmpRootAndSubChains(&buf, ifname, chains_in_set , 1,
3644
&ebtChains, &nEbtChains) < 0) ||
3645
(virHashSize(chains_out_set) > 0 &&
3646
ebtablesCreateTmpRootAndSubChains(&buf, ifname, chains_out_set, 0,
3647
&ebtChains, &nEbtChains) < 0)) {
3612
3648
goto tear_down_tmpebchains;
3930
if (ebiptablesExecCLI(&buf, &cli_status, NULL))
3966
if (ebiptablesExecCLI(&buf, &cli_status, NULL) < 0)
3933
3969
if (cli_status) {
3934
3970
virNWFilterReportError(VIR_ERR_BUILD_FIREWALL,
3936
3972
_("error while executing CLI commands"));
4018
4054
ebiptablesDriverInit(bool privileged)
4020
4056
virBuffer buf = VIR_BUFFER_INITIALIZER;
4057
char *errmsg = NULL;
4022
4059
if (!privileged)
4025
if (virMutexInit(&execCLIMutex))
4062
if (virMutexInit(&execCLIMutex) < 0)
4028
4065
gawk_cmd_path = virFindFileInPath("awk");
4029
4066
grep_cmd_path = virFindFileInPath("grep");
4039
4076
CMD_STOPONERR(1));
4041
if (ebiptablesExecCLI(&buf, NULL, NULL) < 0)
4042
VIR_FREE(ebtables_cmd_path);
4078
if (ebiptablesExecCLI(&buf, NULL, &errmsg) < 0) {
4079
VIR_FREE(ebtables_cmd_path);
4080
VIR_ERROR(_("Testing of ebtables command failed: %s"),
4084
VIR_WARN("Could not find 'ebtables' executable");
4045
4087
iptables_cmd_path = virFindFileInPath("iptables");
4053
4095
CMD_STOPONERR(1));
4055
if (ebiptablesExecCLI(&buf, NULL, NULL) < 0)
4056
VIR_FREE(iptables_cmd_path);
4097
if (ebiptablesExecCLI(&buf, NULL, &errmsg) < 0) {
4098
VIR_FREE(iptables_cmd_path);
4099
VIR_ERROR(_("Testing of iptables command failed: %s"),
4103
VIR_WARN("Could not find 'iptables' executable");
4059
4106
ip6tables_cmd_path = virFindFileInPath("ip6tables");
4067
4114
CMD_STOPONERR(1));
4069
if (ebiptablesExecCLI(&buf, NULL, NULL) < 0)
4070
VIR_FREE(ip6tables_cmd_path);
4116
if (ebiptablesExecCLI(&buf, NULL, &errmsg) < 0) {
4117
VIR_FREE(ip6tables_cmd_path);
4118
VIR_ERROR(_("Testing of ip6tables command failed: %s"),
4122
VIR_WARN("Could not find 'ip6tables' executable");
4073
4125
/* ip(6)tables support needs gawk & grep, ebtables doesn't */
4074
4126
if ((iptables_cmd_path != NULL || ip6tables_cmd_path != NULL) &&
4075
4127
(!grep_cmd_path || !gawk_cmd_path)) {
4076
virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4077
_("essential tools to support ip(6)tables "
4078
"firewalls could not be located"));
4128
VIR_ERROR(_("essential tools to support ip(6)tables "
4129
"firewalls could not be located"));
4079
4130
VIR_FREE(iptables_cmd_path);
4080
4131
VIR_FREE(ip6tables_cmd_path);
4084
4136
if (!ebtables_cmd_path && !iptables_cmd_path && !ip6tables_cmd_path) {
4085
virNWFilterReportError(VIR_ERR_INTERNAL_ERROR, "%s",
4086
_("firewall tools were not found or "
4137
VIR_ERROR(_("firewall tools were not found or cannot be used"));
4088
4138
ebiptablesDriverShutdown();
4092
4142
ebiptables_driver.flags = TECHDRV_FLAG_INITIALIZED;