diff options
| author | Ben Pfaff <blp@nicira.com> | 2010-02-11 14:58:02 -0800 |
|---|---|---|
| committer | Ben Pfaff <blp@nicira.com> | 2010-02-12 13:55:47 -0800 |
| commit | 30012c72af2e0984fb58e386a4e2a5f6e3b6631a (patch) | |
| tree | eb348cd65d88ef84fa1bf0dc39d795db512493bc /lib/vconn.c | |
| parent | 88a20d6e4c8a44bec62e288748620e69d97a729a (diff) | |
| download | openvswitch-30012c72af2e0984fb58e386a4e2a5f6e3b6631a.tar.gz | |
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 <jt@hpl.hp.com>
Diffstat (limited to 'lib/vconn.c')
| -rw-r--r-- | lib/vconn.c | 162 |
1 files changed, 120 insertions, 42 deletions
diff --git a/lib/vconn.c b/lib/vconn.c index d2015897e..51a51b9cd 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 |
