X-Git-Url: https://git.rohieb.name/openwrt.git/blobdiff_plain/69ae98b46ec77c81215a3c334fd0f85df4888a4c..c291b847846f5921d669b17478cbf59f0c83ee19:/package/switch/src/switch-core.c diff --git a/package/switch/src/switch-core.c b/package/switch/src/switch-core.c index 6b59b9ba2..c34386b76 100644 --- a/package/switch/src/switch-core.c +++ b/package/switch/src/switch-core.c @@ -32,7 +32,7 @@ * ports: same syntax as for nvram's vlan*ports (eg. "1 2 3 4 5*") */ -#include +#include #include #include #include @@ -64,8 +64,8 @@ static ssize_t switch_proc_read(struct file *file, char *buf, size_t count, loff static ssize_t switch_proc_write(struct file *file, const char *buf, size_t count, void *data); static struct file_operations switch_proc_fops = { - read: switch_proc_read, - write: switch_proc_write + .read = (ssize_t (*) (struct file *, char __user *, size_t, loff_t *))switch_proc_read, + .write = (ssize_t (*) (struct file *, const char __user *, size_t, loff_t *))switch_proc_write }; static ssize_t switch_proc_read(struct file *file, char *buf, size_t count, loff_t *ppos) @@ -100,6 +100,7 @@ static ssize_t switch_proc_read(struct file *file, char *buf, size_t count, loff len = 0; } + kfree(page); return len; } @@ -138,18 +139,18 @@ static ssize_t switch_proc_write(struct file *file, const char *buf, size_t coun static int handle_driver_name(void *driver, char *buf, int nr) { - char *name = ((switch_driver *) driver)->name; + const char *name = ((switch_driver *) driver)->name; return sprintf(buf, "%s\n", name); } static int handle_driver_version(void *driver, char *buf, int nr) { - char *version = ((switch_driver *) driver)->version; + const char *version = ((switch_driver *) driver)->version; strcpy(buf, version); return sprintf(buf, "%s\n", version); } -static void add_handler(switch_driver *driver, switch_config *handler, struct proc_dir_entry *parent, int nr) +static void add_handler(switch_driver *driver, const switch_config *handler, struct proc_dir_entry *parent, int nr) { switch_priv *priv = (switch_priv *) driver->data; struct proc_dir_entry *p; @@ -157,6 +158,8 @@ static void add_handler(switch_driver *driver, switch_config *handler, struct pr switch_proc_handler *tmp; tmp = (switch_proc_handler *) kmalloc(sizeof(switch_proc_handler), GFP_KERNEL); + if (!tmp) + return; INIT_LIST_HEAD(&tmp->list); tmp->parent = parent; tmp->nr = nr; @@ -174,7 +177,7 @@ static void add_handler(switch_driver *driver, switch_config *handler, struct pr } } -static inline void add_handlers(switch_driver *driver, switch_config *handlers, struct proc_dir_entry *parent, int nr) +static inline void add_handlers(switch_driver *driver, const switch_config *handlers, struct proc_dir_entry *parent, int nr) { int i; @@ -238,11 +241,26 @@ static int do_register(switch_driver *driver) switch_priv *priv; int i; char buf[4]; - - if ((priv = kmalloc(sizeof(switch_priv), GFP_KERNEL)) == NULL) - return -ENOBUFS; + + priv = kmalloc(sizeof(switch_priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; driver->data = (void *) priv; + priv->ports = kmalloc((driver->ports + 1) * sizeof(struct proc_dir_entry *), + GFP_KERNEL); + if (!priv->ports) { + kfree(priv); + return -ENOMEM; + } + priv->vlans = kmalloc((driver->vlans + 1) * sizeof(struct proc_dir_entry *), + GFP_KERNEL); + if (!priv->vlans) { + kfree(priv->ports); + kfree(priv); + return -ENOMEM; + } + INIT_LIST_HEAD(&priv->data.list); priv->nr = drv_num++; @@ -253,7 +271,6 @@ static int do_register(switch_driver *driver) } priv->port_dir = proc_mkdir("port", priv->driver_dir); - priv->ports = kmalloc((driver->ports + 1) * sizeof(struct proc_dir_entry *), GFP_KERNEL); for (i = 0; i < driver->ports; i++) { sprintf(buf, "%d", i); priv->ports[i] = proc_mkdir(buf, priv->port_dir); @@ -263,7 +280,6 @@ static int do_register(switch_driver *driver) priv->ports[i] = NULL; priv->vlan_dir = proc_mkdir("vlan", priv->driver_dir); - priv->vlans = kmalloc((driver->vlans + 1) * sizeof(struct proc_dir_entry *), GFP_KERNEL); for (i = 0; i < driver->vlans; i++) { sprintf(buf, "%d", i); priv->vlans[i] = proc_mkdir(buf, priv->vlan_dir); @@ -338,6 +354,8 @@ switch_vlan_config *switch_parse_vlan(switch_driver *driver, char *buf) int j, u, p, s; c = kmalloc(sizeof(switch_vlan_config), GFP_KERNEL); + if (!c) + return NULL; memset(c, 0, sizeof(switch_vlan_config)); while (isspace(*buf)) buf++; @@ -386,12 +404,27 @@ switch_vlan_config *switch_parse_vlan(switch_driver *driver, char *buf) } +int switch_device_registered (char* device) { + struct list_head *pos; + switch_driver *new; + + list_for_each(pos, &drivers.list) { + if (strcmp(list_entry(pos, switch_driver, list)->interface, device) == 0) { + printk("There is already a switch registered on the device '%s'\n", device); + return -EINVAL; + } + } + + return 0; +} + + int switch_register_driver(switch_driver *driver) { struct list_head *pos; switch_driver *new; int ret; - + list_for_each(pos, &drivers.list) { if (strcmp(list_entry(pos, switch_driver, list)->name, driver->name) == 0) { printk("Switch driver '%s' already exists in the kernel\n", driver->name); @@ -404,10 +437,12 @@ int switch_register_driver(switch_driver *driver) } new = kmalloc(sizeof(switch_driver), GFP_KERNEL); + if (!new) + return -ENOMEM; memcpy(new, driver, sizeof(switch_driver)); new->name = strdup(driver->name); new->interface = strdup(driver->interface); - + if ((ret = do_register(new)) < 0) { kfree(new->name); kfree(new); @@ -436,7 +471,7 @@ void switch_unregister_driver(char *name) { } } -static int __init switch_init() +static int __init switch_init(void) { if ((switch_root = proc_mkdir("switch", NULL)) == NULL) { printk("%s: proc_mkdir failed.\n", __FILE__); @@ -448,7 +483,7 @@ static int __init switch_init() return 0; } -static void __exit switch_exit() +static void __exit switch_exit(void) { remove_proc_entry("switch", NULL); } @@ -456,6 +491,7 @@ static void __exit switch_exit() MODULE_AUTHOR("Felix Fietkau "); MODULE_LICENSE("GPL"); +EXPORT_SYMBOL(switch_device_registered); EXPORT_SYMBOL(switch_register_driver); EXPORT_SYMBOL(switch_unregister_driver); EXPORT_SYMBOL(switch_parse_vlan);