]> err.no Git - linux-2.6/blobdiff - net/9p/trans_fd.c
mac80211: fix an oops in several failure paths in key allocation
[linux-2.6] / net / 9p / trans_fd.c
index c6eda999fa7d04ddb6b57a8b5037bf3f03c736fb..4507f744f44e527cc140b6b5601e556c10bfd361 100644 (file)
@@ -1196,35 +1196,46 @@ void p9_conn_cancel(struct p9_conn *m, int err)
 }
 
 /**
- * v9fs_parse_options - parse mount options into session structure
+ * parse_options - parse mount options into session structure
  * @options: options string passed from mount
  * @opts: transport-specific structure to parse options into
  *
+ * Returns 0 upon success, -ERRNO upon failure
  */
 
-static void parse_opts(char *options, struct p9_fd_opts *opts)
+static int parse_opts(char *params, struct p9_fd_opts *opts)
 {
        char *p;
        substring_t args[MAX_OPT_ARGS];
        int option;
+       char *options;
        int ret;
 
        opts->port = P9_PORT;
        opts->rfd = ~0;
        opts->wfd = ~0;
 
-       if (!options)
-               return;
+       if (!params)
+               return 0;
+
+       options = kstrdup(params, GFP_KERNEL);
+       if (!options) {
+               P9_DPRINTK(P9_DEBUG_ERROR,
+                               "failed to allocate copy of option string\n");
+               return -ENOMEM;
+       }
 
        while ((p = strsep(&options, ",")) != NULL) {
                int token;
+               int r;
                if (!*p)
                        continue;
                token = match_token(p, tokens, args);
-               ret = match_int(&args[0], &option);
-               if (ret < 0) {
+               r = match_int(&args[0], &option);
+               if (r < 0) {
                        P9_DPRINTK(P9_DEBUG_ERROR,
                         "integer field, but no integer?\n");
+                       ret = r;
                        continue;
                }
                switch (token) {
@@ -1241,6 +1252,8 @@ static void parse_opts(char *options, struct p9_fd_opts *opts)
                        continue;
                }
        }
+       kfree(options);
+       return 0;
 }
 
 static int p9_fd_open(struct p9_trans *trans, int rfd, int wfd)
@@ -1420,6 +1433,23 @@ static void p9_fd_close(struct p9_trans *trans)
        kfree(ts);
 }
 
+/*
+ * stolen from NFS - maybe should be made a generic function?
+ */
+static inline int valid_ipaddr4(const char *buf)
+{
+       int rc, count, in[4];
+
+       rc = sscanf(buf, "%d.%d.%d.%d", &in[0], &in[1], &in[2], &in[3]);
+       if (rc != 4)
+               return -EINVAL;
+       for (count = 0; count < 4; count++) {
+               if (in[count] > 255)
+                       return -EINVAL;
+       }
+       return 0;
+}
+
 static struct p9_trans *
 p9_trans_create_tcp(const char *addr, char *args, int msize, unsigned char dotu)
 {
@@ -1430,7 +1460,12 @@ p9_trans_create_tcp(const char *addr, char *args, int msize, unsigned char dotu)
        struct p9_fd_opts opts;
        struct p9_trans_fd *p;
 
-       parse_opts(args, &opts);
+       err = parse_opts(args, &opts);
+       if (err < 0)
+               return ERR_PTR(err);
+
+       if (valid_ipaddr4(addr) < 0)
+               return ERR_PTR(-EINVAL);
 
        csocket = NULL;
        trans = kmalloc(sizeof(struct p9_trans), GFP_KERNEL);
@@ -1610,7 +1645,7 @@ static struct p9_trans_module p9_fd_trans = {
        .create = p9_trans_create_fd,
 };
 
-static int __init p9_trans_fd_init(void)
+int p9_trans_fd_init(void)
 {
        int ret = p9_mux_global_init();
        if (ret) {
@@ -1624,9 +1659,4 @@ static int __init p9_trans_fd_init(void)
 
        return 0;
 }
-
-module_init(p9_trans_fd_init);
-
-MODULE_AUTHOR("Latchesar Ionkov <lucho@ionkov.net>");
-MODULE_AUTHOR("Eric Van Hensbergen <ericvh@gmail.com>");
-MODULE_LICENSE("GPL");
+EXPORT_SYMBOL(p9_trans_fd_init);