ethernet: handle zvm-subchannels unmanaged spec (rh #591533)

This commit is contained in:
Dan Williams 2010-05-26 16:28:51 -07:00
parent 9c45b52f38
commit 5f03706a6b
3 changed files with 103 additions and 1 deletions

View file

@ -25,6 +25,7 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include "NetworkManagerUtils.h"
#include "nm-utils.h"
@ -487,6 +488,101 @@ nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr)
return FALSE;
}
#define BUFSIZE 10
static gboolean
parse_subchannels (const char *subchannels, guint32 *a, guint32 *b, guint32 *c)
{
long unsigned int tmp;
char buf[BUFSIZE + 1];
const char *p = subchannels;
int i = 0;
char *pa = NULL, *pb = NULL, *pc = NULL;
g_return_val_if_fail (subchannels != NULL, FALSE);
g_return_val_if_fail (a != NULL, FALSE);
g_return_val_if_fail (*a == 0, FALSE);
g_return_val_if_fail (b != NULL, FALSE);
g_return_val_if_fail (*b == 0, FALSE);
g_return_val_if_fail (c != NULL, FALSE);
g_return_val_if_fail (*c == 0, FALSE);
/* sanity check */
if (!isxdigit (subchannels[0]))
return FALSE;
/* Get the first channel */
while (*p && (*p != ',')) {
if (!isxdigit (*p) && (*p != '.'))
return FALSE; /* Invalid chars */
if (i >= BUFSIZE)
return FALSE; /* Too long to be a subchannel */
buf[i++] = *p++;
}
buf[i] = '\0';
/* and grab each of its elements, there should be 3 */
pa = &buf[0];
pb = strchr (buf, '.');
if (pb)
pc = strchr (pb + 1, '.');
if (!pa || !pb || !pc)
return FALSE;
/* Split the string */
*pb++ = '\0';
*pc++ = '\0';
errno = 0;
tmp = strtoul (pa, NULL, 16);
if (errno)
return FALSE;
*a = (guint32) tmp;
errno = 0;
tmp = strtoul (pb, NULL, 16);
if (errno)
return FALSE;
*b = (guint32) tmp;
errno = 0;
tmp = strtoul (pc, NULL, 16);
if (errno)
return FALSE;
*c = (guint32) tmp;
return TRUE;
}
#define SUBCHAN_TAG "zvm-subchannels:"
gboolean
nm_match_spec_zvm_subchannels (const GSList *specs, const char *subchannels)
{
const GSList *iter;
guint32 a = 0, b = 0, c = 0;
guint32 spec_a = 0, spec_b = 0, spec_c = 0;
g_return_val_if_fail (subchannels != NULL, FALSE);
if (!parse_subchannels (subchannels, &a, &b, &c))
return FALSE;
for (iter = specs; iter; iter = g_slist_next (iter)) {
const char *spec = iter->data;
if (!strncmp (spec, SUBCHAN_TAG, strlen (SUBCHAN_TAG))) {
spec += strlen (SUBCHAN_TAG);
if (parse_subchannels (spec, &spec_a, &spec_b, &spec_c)) {
if (a == spec_a && b == spec_b && c == spec_c)
return TRUE;
}
}
}
return FALSE;
}
/*********************************/
static void

View file

@ -15,7 +15,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright (C) 2004 - 2008 Red Hat, Inc.
* Copyright (C) 2004 - 2010 Red Hat, Inc.
* Copyright (C) 2005 - 2008 Novell, Inc.
*/
@ -48,6 +48,7 @@ void nm_utils_call_dispatcher (const char *action,
const char *vpn_iface);
gboolean nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr);
gboolean nm_match_spec_zvm_subchannels (const GSList *specs, const char *subchannels);
GHashTable *value_hash_create (void);

View file

@ -105,6 +105,7 @@ typedef struct {
gboolean disposed;
struct ether_addr hw_addr;
char * zvm_subchannels;
gboolean carrier;
NMNetlinkMonitor * monitor;
@ -1519,6 +1520,7 @@ real_check_connection_compatible (NMDevice *device,
static gboolean
spec_match_list (NMDevice *device, const GSList *specs)
{
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device);
struct ether_addr ether;
char *hwaddr;
gboolean matched;
@ -1528,6 +1530,9 @@ spec_match_list (NMDevice *device, const GSList *specs)
matched = nm_match_spec_hwaddr (specs, hwaddr);
g_free (hwaddr);
if (!matched && priv->zvm_subchannels)
matched = nm_match_spec_zvm_subchannels (specs, priv->zvm_subchannels);
return matched;
}