[libvirt] [RFC PATCH 1/3] add ebtables wrapper

Daniel P. Berrange berrange at redhat.com
Fri Oct 16 12:31:35 UTC 2009


On Tue, Oct 13, 2009 at 12:57:13PM +0200, Gerhard Stenzel wrote:
> +#ifdef ENABLE_EBTABLES_LOKKIT
> +static void
> +notifyRulesUpdated(const char *table,
> +                   const char *path)
> +{
> +    char arg[PATH_MAX];
> +    const char *argv[4];
> +
> +    snprintf(arg, sizeof(arg), "--custom-rules=ipv4:%s:%s", table, path);
> +
> +    argv[0] = (char *) LOKKIT_PATH;
> +    argv[1] = (char *) "--nostart";
> +    argv[2] = arg;
> +    argv[3] = NULL;

This is better declared upfront as

  const char *const argv[] = {
     LOKKIT_PATH, "--nostart", arg, NULL,
  };

> +
> +    char ebuf[1024];
> +    if (virRun(NULL, argv, NULL) < 0)
> +        VIR_WARN(_("Failed to run '%s %s': %s"),
> +                 LOKKIT_PATH, arg, virStrerror(errno, ebuf, sizeof ebuf));
> +}

> +
> +static void
> +notifyRulesRemoved(const char *table,
> +                   const char *path)
> +{
> +/* 10 MB limit on config file size as a sanity check */
> +#define MAX_FILE_LEN (1024*1024*10)
> +
> +    char arg[PATH_MAX];
> +    char *content;
> +    int len;
> +    FILE *f = NULL;
> +
> +    len = virFileReadAll(SYSCONF_DIR "/sysconfig/system-config-firewall",
> +                         MAX_FILE_LEN, &content);
> +    if (len < 0) {
> +        VIR_WARN("%s", _("Failed to read " SYSCONF_DIR
> +                         "/sysconfig/system-config-firewall"));
> +        return;
> +    }
> +
> +    snprintf(arg, sizeof(arg), "--custom-rules=ipv4:%s:%s", table, path);
> +
> +    if (!stripLine(content, len, arg)) {
> +        VIR_FREE(content);
> +        return;
> +    }
> +
> +    if (!(f = fopen(SYSCONF_DIR "/sysconfig/system-config-firewall", "w")))
> +        goto write_error;
> +
> +    if (fputs(content, f) == EOF)
> +        goto write_error;
> +
> +    if (fclose(f) == EOF) {
> +        f = NULL;
> +        goto write_error;
> +    }

This  fopen/fputs/fclose  triple could be nicely replaced with a
single call to 

    if (virFileWriteStr(SYSCONF_DIR "/sysconfig/system-config-firewall",
                        content) < 0)
       goto write_error;

> +
> +    VIR_FREE(content);
> +
> +    return;
> +
> + write_error:;
> +    char ebuf[1024];
> +    VIR_WARN(_("Failed to write to " SYSCONF_DIR
> +               "/sysconfig/system-config-firewall : %s"),
> +             virStrerror(errno, ebuf, sizeof ebuf));
> +    if (f)
> +        fclose(f);
> +    VIR_FREE(content);
> +
> +#undef MAX_FILE_LEN
> +}

> +
> +static ebtRules *
> +ebtRulesNew(const char *table,
> +            const char *chain)
> +{
> +    ebtRules *rules;
> +
> +    if (VIR_ALLOC(rules) < 0)
> +        return NULL;
> +
> +    if (!(rules->table = strdup(table)))
> +        goto error;
> +
> +    if (!(rules->chain = strdup(chain)))
> +        goto error;
> +
> +    rules->rules = NULL;
> +    rules->nrules = 0;
> +
> +#ifdef ENABLE_EBTABLES_LOKKIT
> +    if (virFileBuildPath(LOCAL_STATE_DIR "/lib/libvirt/ebtables", table, NULL,
> +                         rules->dir, sizeof(rules->dir)) < 0)
> +        goto error;
> +
> +    if (virFileBuildPath(rules->dir, chain, ".chain", rules->path, sizeof(rules->path)) < 0)
> +        goto error;
> +#endif /* ENABLE_EBTABLES_LOKKIT */

Don't forget to add a rule to src/Makefile.am to ensure that the
new ebtables directory is created by the 'install-data-local' rule

> index 0000000..a3f403a
> --- /dev/null
> +++ b/src/util/ebtables.h
> @@ -0,0 +1,134 @@
> +/*
> + * Copyright (C) 2009 IBM Corp.
> + * Copyright (C) 2007, 2008 Red Hat, Inc.
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
> + *
> + * based on iptables.h
> + * Authors:
> + *     Gerhard Stenzel <gerhard.stenzel at de.ibm.com>
> + */
> +
> +#ifndef __QEMUD_EBTABLES_H__
> +#define __QEMUD_EBTABLES_H__
> +
> +typedef struct
> +{
> +    char  *rule;
> +    const char **argv;
> +    int    command_idx;
> +} ebtRule;
> +
> +typedef struct
> +{
> +    char  *table;
> +    char  *chain;
> +
> +    int      nrules;
> +    ebtRule *rules;
> +
> +#ifdef ENABLE_EBTABLES_LOKKIT
> +
> +    char   dir[PATH_MAX];
> +    char   path[PATH_MAX];
> +
> +#endif /* ENABLE_EBTABLES_LOKKIT */
> +
> +} ebtRules;
> +
> +struct _ebtablesContext
> +{
> +    ebtRules *input_filter;
> +    ebtRules *forward_filter;
> +    ebtRules *nat_postrouting;
> +};

Since the caller of the API does not need to know the internals
of the struct, it is better to move these 3 struct definitions
into the ebtables.c file.

> +typedef struct _ebtablesContext ebtablesContext;
> +
> +ebtablesContext *ebtablesContextNew              (const char *driver);
> +void             ebtablesContextFree             (ebtablesContext *ctx);
> +
> +void             ebtablesSaveRules               (ebtablesContext *ctx);
> +void             ebtablesReloadRules             (ebtablesContext *ctx);
> +
> +int              ebtablesAddTcpInput             (ebtablesContext *ctx,
> +                                                  const char *iface,
> +                                                  int port);
> +int              ebtablesRemoveTcpInput          (ebtablesContext *ctx,
> +                                                  const char *iface,
> +                                                  int port);
> +
> +int              ebtablesAddUdpInput             (ebtablesContext *ctx,
> +                                                  const char *iface,
> +                                                  int port);
> +int              ebtablesRemoveUdpInput          (ebtablesContext *ctx,
> +                                                  const char *iface,
> +                                                  int port);
> +
> +int              ebtablesAddForwardAllowOut      (ebtablesContext *ctx,
> +                                                  const char *network,
> +                                                  const char *iface,
> +                                                  const char *physdev);
> +int              ebtablesRemoveForwardAllowOut   (ebtablesContext *ctx,
> +                                                  const char *network,
> +                                                  const char *iface,
> +                                                  const char *physdev);
> +
> +int              ebtablesAddForwardAllowRelatedIn(ebtablesContext *ctx,
> +                                                  const char *network,
> +                                                  const char *iface,
> +                                                  const char *physdev);
> +int              ebtablesRemoveForwardAllowRelatedIn(ebtablesContext *ctx,
> +                                                  const char *network,
> +                                                  const char *iface,
> +                                                  const char *physdev);
> +
> +int              ebtablesAddForwardAllowIn       (ebtablesContext *ctx,
> +                                                  const char *iface,
> +                                                  const char *physdev);
> +int              ebtablesRemoveForwardAllowIn    (ebtablesContext *ctx,
> +                                                  const char *iface,
> +                                                  const char *physdev);
> +
> +int              ebtablesAddForwardAllowCross    (ebtablesContext *ctx,
> +                                                  const char *iface);
> +int              ebtablesRemoveForwardAllowCross (ebtablesContext *ctx,
> +                                                  const char *iface);
> +
> +int              ebtablesAddForwardRejectOut     (ebtablesContext *ctx,
> +                                                  const char *iface);
> +int              ebtablesRemoveForwardRejectOut  (ebtablesContext *ctx,
> +                                                  const char *iface);
> +
> +int              ebtablesAddForwardRejectIn      (ebtablesContext *ctx,
> +                                                  const char *iface);
> +int              ebtablesRemoveForwardRejectIn   (ebtablesContext *ctx,
> +                                                  const char *iface);
> +
> +int              ebtablesAddForwardMasquerade    (ebtablesContext *ctx,
> +                                                  const char *network,
> +                                                  const char *physdev);
> +int              ebtablesRemoveForwardMasquerade (ebtablesContext *ctx,
> +                                                  const char *network,
> +                                                  const char *physdev);
> +
> +int              ebtablesAddForwardPolicyReject(ebtablesContext *ctx);
> +
> +int              ebtablesRemoveForwardPolicyReject(ebtablesContext *ctx);
> +
> +int              ebtablesForwardPolicyReject(ebtablesContext *ctx,
> +                                                  int action);

There seem like there's quite a lot of methods here that we don't 
actually need for MAC address filtering. It'd be a little clearer
if you removed the ones that aren't relevant. Alot of the complexity
of the iptables.h/c file on which this is based is relating to the
masquerading, and punching holes for DHCP/DNS. ebtables ought to be
alot simpler, since we're pretty much just doing a 'ALLOW <mac>'
followed by  'DENY ALL' on the tap device in question. 

Regards,
Daniel
-- 
|: Red Hat, Engineering, London   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|




More information about the libvir-list mailing list