From: Ben Pfaff Date: Thu, 11 Feb 2010 22:58:02 +0000 (-0800) Subject: vconn: New functions vconn_verify_name(), pvconn_verify_name(). X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=30012c72af2e0984fb58e386a4e2a5f6e3b6631a;p=openvswitch vconn: New functions vconn_verify_name(), pvconn_verify_name(). These are useful for checking that the syntax of a name is valid, so that completely invalid names can be rejected at program startup time. CC: Jean Tourrilhes --- diff --git a/lib/vconn.c b/lib/vconn.c index d2015897..51a51b9c 100644 --- a/lib/vconn.c +++ b/lib/vconn.c @@ -163,6 +163,42 @@ vconn_usage(bool active, bool passive, bool bootstrap OVS_UNUSED) #endif } +/* Given 'name', a connection name in the form "TYPE:ARGS", stores the class + * named "TYPE" into '*classp' and returns 0. Returns EAFNOSUPPORT and stores + * a null pointer into '*classp' if 'name' is in the wrong form or if no such + * class exists. */ +static int +vconn_lookup_class(const char *name, struct vconn_class **classp) +{ + size_t prefix_len; + + prefix_len = strcspn(name, ":"); + if (name[prefix_len] != '\0') { + size_t i; + + for (i = 0; i < ARRAY_SIZE(vconn_classes); i++) { + struct vconn_class *class = vconn_classes[i]; + if (strlen(class->name) == prefix_len + && !memcmp(class->name, name, prefix_len)) { + *classp = class; + return 0; + } + } + } + + *classp = NULL; + return EAFNOSUPPORT; +} + +/* Returns 0 if 'name' is a connection name in the form "TYPE:ARGS" and TYPE is + * a supported connection type, otherwise EAFNOSUPPORT. */ +int +vconn_verify_name(const char *name) +{ + struct vconn_class *class; + return vconn_lookup_class(name, &class); +} + /* Attempts to connect to an OpenFlow device. 'name' is a connection name in * the form "TYPE:ARGS", where TYPE is an active vconn class's name and ARGS * are vconn class-specific. @@ -177,35 +213,37 @@ vconn_usage(bool active, bool passive, bool bootstrap OVS_UNUSED) int vconn_open(const char *name, int min_version, struct vconn **vconnp) { - size_t prefix_len; - size_t i; + struct vconn_class *class; + struct vconn *vconn; + char *suffix_copy; + int error; COVERAGE_INC(vconn_open); check_vconn_classes(); - *vconnp = NULL; - prefix_len = strcspn(name, ":"); - if (prefix_len == strlen(name)) { - return EAFNOSUPPORT; + /* Look up the class. */ + error = vconn_lookup_class(name, &class); + if (!class) { + goto error; } - for (i = 0; i < ARRAY_SIZE(vconn_classes); i++) { - struct vconn_class *class = vconn_classes[i]; - if (strlen(class->name) == prefix_len - && !memcmp(class->name, name, prefix_len)) { - struct vconn *vconn; - char *suffix_copy = xstrdup(name + prefix_len + 1); - int retval = class->open(name, suffix_copy, &vconn); - free(suffix_copy); - if (!retval) { - assert(vconn->state != VCS_CONNECTING - || vconn->class->connect); - vconn->min_version = min_version; - *vconnp = vconn; - } - return retval; - } + + /* Call class's "open" function. */ + suffix_copy = xstrdup(strchr(name, ':') + 1); + error = class->open(name, suffix_copy, &vconn); + free(suffix_copy); + if (error) { + goto error; } - return EAFNOSUPPORT; + + /* Success. */ + assert(vconn->state != VCS_CONNECTING || vconn->class->connect); + vconn->min_version = min_version; + *vconnp = vconn; + return 0; + +error: + *vconnp = NULL; + return error; } int @@ -664,6 +702,42 @@ vconn_send_wait(struct vconn *vconn) vconn_wait(vconn, WAIT_SEND); } +/* Given 'name', a connection name in the form "TYPE:ARGS", stores the class + * named "TYPE" into '*classp' and returns 0. Returns EAFNOSUPPORT and stores + * a null pointer into '*classp' if 'name' is in the wrong form or if no such + * class exists. */ +static int +pvconn_lookup_class(const char *name, struct pvconn_class **classp) +{ + size_t prefix_len; + + prefix_len = strcspn(name, ":"); + if (name[prefix_len] != '\0') { + size_t i; + + for (i = 0; i < ARRAY_SIZE(pvconn_classes); i++) { + struct pvconn_class *class = pvconn_classes[i]; + if (strlen(class->name) == prefix_len + && !memcmp(class->name, name, prefix_len)) { + *classp = class; + return 0; + } + } + } + + *classp = NULL; + return EAFNOSUPPORT; +} + +/* Returns 0 if 'name' is a connection name in the form "TYPE:ARGS" and TYPE is + * a supported connection type, otherwise EAFNOSUPPORT. */ +int +pvconn_verify_name(const char *name) +{ + struct pvconn_class *class; + return pvconn_lookup_class(name, &class); +} + /* Attempts to start listening for OpenFlow connections. 'name' is a * connection name in the form "TYPE:ARGS", where TYPE is an passive vconn * class's name and ARGS are vconn class-specific. @@ -674,30 +748,34 @@ vconn_send_wait(struct vconn *vconn) int pvconn_open(const char *name, struct pvconn **pvconnp) { - size_t prefix_len; - size_t i; + struct pvconn_class *class; + struct pvconn *pvconn; + char *suffix_copy; + int error; check_vconn_classes(); - *pvconnp = NULL; - prefix_len = strcspn(name, ":"); - if (prefix_len == strlen(name)) { - return EAFNOSUPPORT; + /* Look up the class. */ + error = pvconn_lookup_class(name, &class); + if (!class) { + goto error; } - for (i = 0; i < ARRAY_SIZE(pvconn_classes); i++) { - struct pvconn_class *class = pvconn_classes[i]; - if (strlen(class->name) == prefix_len - && !memcmp(class->name, name, prefix_len)) { - char *suffix_copy = xstrdup(name + prefix_len + 1); - int retval = class->listen(name, suffix_copy, pvconnp); - free(suffix_copy); - if (retval) { - *pvconnp = NULL; - } - return retval; - } + + /* Call class's "open" function. */ + suffix_copy = xstrdup(strchr(name, ':') + 1); + error = class->listen(name, suffix_copy, &pvconn); + free(suffix_copy); + if (error) { + goto error; } - return EAFNOSUPPORT; + + /* Success. */ + *pvconnp = pvconn; + return 0; + +error: + *pvconnp = NULL; + return error; } /* Returns the name that was used to open 'pvconn'. The caller must not diff --git a/lib/vconn.h b/lib/vconn.h index 0c13744c..e2a35772 100644 --- a/lib/vconn.h +++ b/lib/vconn.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009 Nicira Networks. + * Copyright (c) 2008, 2009, 2010 Nicira Networks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,6 +35,7 @@ struct vconn; void vconn_usage(bool active, bool passive, bool bootstrap); /* Active vconns: virtual connections to OpenFlow devices. */ +int vconn_verify_name(const char *name); int vconn_open(const char *name, int min_version, struct vconn **); void vconn_close(struct vconn *); const char *vconn_get_name(const struct vconn *); @@ -63,6 +64,7 @@ void vconn_recv_wait(struct vconn *); void vconn_send_wait(struct vconn *); /* Passive vconns: virtual listeners for incoming OpenFlow connections. */ +int pvconn_verify_name(const char *name); int pvconn_open(const char *name, struct pvconn **); const char *pvconn_get_name(const struct pvconn *); void pvconn_close(struct pvconn *);