[libvirt] [PATCH v2 3/7] util: new virFirewallD APIs + docs
Laine Stump
laine at laine.org
Fri Feb 1 15:06:44 UTC 2019
On 2/1/19 8:17 AM, Daniel P. Berrangé wrote:
> On Thu, Jan 31, 2019 at 08:24:54PM -0500, Laine Stump wrote:
>> +int
>> +virFirewallDGetBackend(void)
>> +{
>> + DBusConnection *sysbus = virDBusGetSystemBus();
>> + DBusMessage *reply = NULL;
>> + virError error;
>> + VIR_AUTOFREE(char *) backendStr = NULL;
>> + int backend = -1;
>> +
>> + if (!sysbus)
>> + return -1;
>> +
>> + memset(&error, 0, sizeof(error));
>> +
>> + if (virDBusCallMethod(sysbus,
>> + &reply,
>> + &error,
>> + VIR_FIREWALL_FIREWALLD_SERVICE,
>> + "/org/fedoraproject/FirewallD1/config",
>> + "org.freedesktop.DBus.Properties",
>> + "Get",
>> + "ss",
>> + "org.fedoraproject.FirewallD1.config",
>> + "FirewallBackend") < 0)
>> + goto cleanup;
>> +
>> + if (error.level == VIR_ERR_ERROR) {
>> + /* we don't want to log any error in the case that
>> + * FirewallBackend isn't implemented in this firewalld, since
>> + * that just means that it is an old version, and only has an
>> + * iptables backend.
>> + */
>> + VIR_DEBUG("Failed to get FirewallBackend setting, assuming 'iptables'");
>> + backend = VIR_FIREWALLD_BACKEND_IPTABLES;
>> + goto cleanup;
>> + }
> Surely we need an '} else {' case here to propagate 'error'
> as fatal.
The point is to ignore all errors. If error.level != VIR_ERR_ERROR, then
there is no error to propagate (and if it is then we already ignored
it). Am I missing something? (Very likely, since I can count on one hand
the number of times I've had to directly interact with an error object.)
>
>> +
>> + if (virDBusMessageRead(reply, "v", "s", &backendStr) < 0)
>> + goto cleanup;
>> +
>> + VIR_DEBUG("FirewallD backend: %s", backendStr);
>> +
>> + if ((backend = virFirewallDBackendTypeFromString(backendStr)) < 0) {
>> + virReportError(VIR_ERR_INTERNAL_ERROR,
>> + _("Unrecognized firewalld backend type: %s"),
>> + backendStr);
>> + }
> I'd usually put an explicit 'goto cleanup' here. I've seen bugs
> in the past where people optimized by assuming we'll immediately
> hit the cleanup, but someome later introduces more code and
> doesn't notice the missing goto.
Yeah, me too. I just missed it. I'll add it in.
>
>> +
>> + cleanup:
>> + virResetError(&error);
>> + virDBusMessageUnref(reply);
>> + return backend;
>> +}
>
>> +/**
>> + * virFirewallDGetZones:
>> + * @zones: array of char *, each entry is a null-terminated zone name
>> + * @nzones: number of entries in @zones
>> + *
>> + * Get the number of currently active firewalld zones, and their names in an
>> + * array of null-terminated strings.
>> + *
>> + * Returns 0 on success, -1 (and failure logged) on error
>> + */
>> +int
>> +virFirewallDGetZones(char ***zones, size_t *nzones)
>> +{
>> + DBusConnection *sysbus = virDBusGetSystemBus();
>> + DBusMessage *reply = NULL;
>> + int ret = -1;
>> +
>> + *nzones = 0;
>> + *zones = NULL;
>> +
>> + if (!sysbus)
>> + return -1;
>> +
>> + if (virDBusCallMethod(sysbus,
>> + &reply,
>> + NULL,
>> + VIR_FIREWALL_FIREWALLD_SERVICE,
>> + "/org/fedoraproject/FirewallD1",
>> + "org.fedoraproject.FirewallD1.zone",
>> + "getZones",
>> + NULL) < 0)
>> + goto cleanup;
>> +
>> + if (virDBusMessageRead(reply, "a&s", nzones, zones) < 0)
>> + goto cleanup;
>> +
>> + ret = 0;
>> + cleanup:
>> + virDBusMessageUnref(reply);
>> + return ret;
>> +}
>> +
>> +
>> +/**
>> + * virFirewallDZoneExists:
>> + * @match: name of zone to look for
>> + *
>> + * Returns true if the requested zone exists, or false if it doesn't exist
>> + */
>> +bool
>> +virFirewallDZoneExists(const char *match)
>> +{
>> + size_t nzones = 0, i;
>> + char **zones = NULL;
>> + bool result = false;
>> +
>> + return true;
>> +
>> + if (virFirewallDGetZones(&zones, &nzones) < 0)
>> + goto cleanup;
>> +
>> + for (i = 0; i < nzones; i++) {
>> + VIR_DEBUG("FirewallD zone: %s", zones[i]);
>> + if (STREQ_NULLABLE(zones[i], match))
>> + result = true;
>> + }
>> +
>> + cleanup:
>> + /* NB: zones points to memory inside reply, so it is cleaned
>> + * up by virDBusMessageUnref, and doesn't need to be freed
>> + */
> I'm confused by this comment. virDBusMessageUnref has already
> run before control even returned to this method, so it 'zones'
> is owned by the reply, we've been using free'd memory.
>
> The very next lines, however, contradict this comment by
> freein'g zones anyway, which makes me even more confused :-)
Yeah, I changed the code and forgot to remove the comment (even through
probably a dozen or more rebases *and* moving a large chunk of this
function into the preceding virFirewalldGetZones() function!! Somehow my
brain just glossed right over the comment as I was changing and moving
the code.)
The comment arose from me misunderstanding something you said in IRC (or
maybe you misunderstood what I was asking about - for a period I thought
that the references returned for a&s args sent to virDBusMessageRead
were pointers to memory inside the DBusMessage, and that they would be
cleaned up by virDBusMessageUnref(), so I wrote that comment early on
when writing the function, but then when I looked at the test programs,
I saw they *were* freeing the memory, and a run under valgrind confirmed
that I needed to free it. So I changed the code, by neglected to clean
out the comment.
Anyway, I'll remove the comment.
>
>> + VIR_DEBUG("Requested zone '%s' %s exist",
>> + match, result ? "does" : "doesn't");
>> + for (i = 0; i < nzones; i++)
>> + VIR_FREE(zones[i]);
>> + VIR_FREE(zones);
>> + return result;
>> +}
>> +
>
>
> Regards,
> Daniel
More information about the libvir-list
mailing list