include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / net / irda / ircomm / ircomm_core.c
index 2868819..e970820 100644 (file)
@@ -1,5 +1,5 @@
 /*********************************************************************
- *                
+ *
  * Filename:      ircomm_core.c
  * Version:       1.0
  * Description:   IrCOMM service interface
@@ -8,33 +8,32 @@
  * Created at:    Sun Jun  6 20:37:34 1999
  * Modified at:   Tue Dec 21 13:26:41 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
+ *
  *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
  *     Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com>
- *     
- *     This program is free software; you can redistribute it and/or 
- *     modify it under the terms of the GNU General Public License as 
- *     published by the Free Software Foundation; either version 2 of 
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
  *     the License, or (at your option) any later version.
- * 
+ *
  *     This program is distributed in the hope that it will be useful,
  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  *     GNU General Public License for more details.
- * 
- *     You should have received a copy of the GNU General Public License 
- *     along with this program; if not, write to the Free Software 
- *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+ *
+ *     You should have received a copy of the GNU General Public License
+ *     along with this program; if not, write to the Free Software
+ *     Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  *     MA 02111-1307 USA
- *     
+ *
  ********************************************************************/
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/sched.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/init.h>
+#include <linux/slab.h>
 
 #include <net/irda/irda.h>
 #include <net/irda/irmod.h>
 #include <net/irda/ircomm_core.h>
 
 static int __ircomm_close(struct ircomm_cb *self);
-static void ircomm_control_indication(struct ircomm_cb *self, 
+static void ircomm_control_indication(struct ircomm_cb *self,
                                      struct sk_buff *skb, int clen);
 
 #ifdef CONFIG_PROC_FS
 extern struct proc_dir_entry *proc_irda;
 static int ircomm_seq_open(struct inode *, struct file *);
 
-static struct file_operations ircomm_proc_fops = {
+static const struct file_operations ircomm_proc_fops = {
        .owner          = THIS_MODULE,
        .open           = ircomm_seq_open,
        .read           = seq_read,
@@ -70,28 +69,30 @@ hashbin_t *ircomm = NULL;
 
 static int __init ircomm_init(void)
 {
-       ircomm = hashbin_new(HB_LOCK); 
+       ircomm = hashbin_new(HB_LOCK);
        if (ircomm == NULL) {
-               IRDA_ERROR("%s(), can't allocate hashbin!\n", __FUNCTION__);
+               IRDA_ERROR("%s(), can't allocate hashbin!\n", __func__);
                return -ENOMEM;
        }
-       
+
 #ifdef CONFIG_PROC_FS
        { struct proc_dir_entry *ent;
-       ent = create_proc_entry("ircomm", 0, proc_irda);
-       if (ent) 
-               ent->proc_fops = &ircomm_proc_fops;
+       ent = proc_create("ircomm", 0, proc_irda, &ircomm_proc_fops);
+       if (!ent) {
+               printk(KERN_ERR "ircomm_init: can't create /proc entry!\n");
+               return -ENODEV;
+       }
        }
 #endif /* CONFIG_PROC_FS */
-       
+
        IRDA_MESSAGE("IrCOMM protocol (Dag Brattli)\n");
-               
+
        return 0;
 }
 
 static void __exit ircomm_cleanup(void)
 {
-       IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
+       IRDA_DEBUG(2, "%s()\n", __func__ );
 
        hashbin_delete(ircomm, (FREE_FUNC) __ircomm_close);
 
@@ -111,17 +112,15 @@ struct ircomm_cb *ircomm_open(notify_t *notify, __u8 service_type, int line)
        struct ircomm_cb *self = NULL;
        int ret;
 
-       IRDA_DEBUG(2, "%s(), service_type=0x%02x\n", __FUNCTION__ ,
+       IRDA_DEBUG(2, "%s(), service_type=0x%02x\n", __func__ ,
                   service_type);
 
        IRDA_ASSERT(ircomm != NULL, return NULL;);
 
-       self = kmalloc(sizeof(struct ircomm_cb), GFP_ATOMIC);
+       self = kzalloc(sizeof(struct ircomm_cb), GFP_ATOMIC);
        if (self == NULL)
                return NULL;
 
-       memset(self, 0, sizeof(struct ircomm_cb));
-
        self->notify = *notify;
        self->magic = IRCOMM_MAGIC;
 
@@ -142,7 +141,7 @@ struct ircomm_cb *ircomm_open(notify_t *notify, __u8 service_type, int line)
 
        hashbin_insert(ircomm, (irda_queue_t *) self, line, NULL);
 
-       ircomm_next_state(self, IRCOMM_IDLE);   
+       ircomm_next_state(self, IRCOMM_IDLE);
 
        return self;
 }
@@ -157,7 +156,7 @@ EXPORT_SYMBOL(ircomm_open);
  */
 static int __ircomm_close(struct ircomm_cb *self)
 {
-       IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
+       IRDA_DEBUG(2, "%s()\n", __func__ );
 
        /* Disconnect link if any */
        ircomm_do_event(self, IRCOMM_DISCONNECT_REQUEST, NULL, NULL);
@@ -193,13 +192,13 @@ int ircomm_close(struct ircomm_cb *self)
        IRDA_ASSERT(self != NULL, return -EIO;);
        IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -EIO;);
 
-       IRDA_DEBUG(0, "%s()\n", __FUNCTION__ );
+       IRDA_DEBUG(0, "%s()\n", __func__ );
 
        entry = hashbin_remove(ircomm, self->line, NULL);
 
        IRDA_ASSERT(entry == self, return -1;);
-       
-        return __ircomm_close(self);
+
+       return __ircomm_close(self);
 }
 
 EXPORT_SYMBOL(ircomm_close);
@@ -209,16 +208,16 @@ EXPORT_SYMBOL(ircomm_close);
  *
  *    Impl. of this function is differ from one of the reference. This
  *    function does discovery as well as sending connect request
- * 
+ *
  */
-int ircomm_connect_request(struct ircomm_cb *self, __u8 dlsap_sel, 
+int ircomm_connect_request(struct ircomm_cb *self, __u8 dlsap_sel,
                           __u32 saddr, __u32 daddr, struct sk_buff *skb,
                           __u8 service_type)
 {
        struct ircomm_info info;
        int ret;
 
-       IRDA_DEBUG(2 , "%s()\n", __FUNCTION__ );
+       IRDA_DEBUG(2 , "%s()\n", __func__ );
 
        IRDA_ASSERT(self != NULL, return -1;);
        IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
@@ -246,24 +245,24 @@ void ircomm_connect_indication(struct ircomm_cb *self, struct sk_buff *skb,
                               struct ircomm_info *info)
 {
        int clen = 0;
-       
-       IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
+
+       IRDA_DEBUG(2, "%s()\n", __func__ );
 
        /* Check if the packet contains data on the control channel */
        if (skb->len > 0)
                clen = skb->data[0];
-       
-       /* 
-        * If there are any data hiding in the control channel, we must 
-        * deliver it first. The side effect is that the control channel 
+
+       /*
+        * If there are any data hiding in the control channel, we must
+        * deliver it first. The side effect is that the control channel
         * will be removed from the skb
         */
        if (self->notify.connect_indication)
-               self->notify.connect_indication(self->notify.instance, self, 
+               self->notify.connect_indication(self->notify.instance, self,
                                                info->qos, info->max_data_size,
                                                info->max_header_size, skb);
        else {
-               IRDA_DEBUG(0, "%s(), missing handler\n", __FUNCTION__ );
+               IRDA_DEBUG(0, "%s(), missing handler\n", __func__ );
        }
 }
 
@@ -280,12 +279,12 @@ int ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata)
        IRDA_ASSERT(self != NULL, return -1;);
        IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
 
-       IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
+       IRDA_DEBUG(4, "%s()\n", __func__ );
 
        ret = ircomm_do_event(self, IRCOMM_CONNECT_RESPONSE, userdata, NULL);
 
        return ret;
-}      
+}
 
 EXPORT_SYMBOL(ircomm_connect_response);
 
@@ -298,15 +297,15 @@ EXPORT_SYMBOL(ircomm_connect_response);
 void ircomm_connect_confirm(struct ircomm_cb *self, struct sk_buff *skb,
                            struct ircomm_info *info)
 {
-       IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
+       IRDA_DEBUG(4, "%s()\n", __func__ );
 
        if (self->notify.connect_confirm )
                self->notify.connect_confirm(self->notify.instance,
-                                            self, info->qos, 
+                                            self, info->qos,
                                             info->max_data_size,
                                             info->max_header_size, skb);
        else {
-               IRDA_DEBUG(0, "%s(), missing handler\n", __FUNCTION__ );
+               IRDA_DEBUG(0, "%s(), missing handler\n", __func__ );
        }
 }
 
@@ -320,12 +319,12 @@ int ircomm_data_request(struct ircomm_cb *self, struct sk_buff *skb)
 {
        int ret;
 
-       IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
+       IRDA_DEBUG(4, "%s()\n", __func__ );
 
        IRDA_ASSERT(self != NULL, return -EFAULT;);
        IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -EFAULT;);
        IRDA_ASSERT(skb != NULL, return -EFAULT;);
-       
+
        ret = ircomm_do_event(self, IRCOMM_DATA_REQUEST, skb, NULL);
 
        return ret;
@@ -340,15 +339,15 @@ EXPORT_SYMBOL(ircomm_data_request);
  *
  */
 void ircomm_data_indication(struct ircomm_cb *self, struct sk_buff *skb)
-{      
-       IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
+{
+       IRDA_DEBUG(4, "%s()\n", __func__ );
 
        IRDA_ASSERT(skb->len > 0, return;);
 
        if (self->notify.data_indication)
                self->notify.data_indication(self->notify.instance, self, skb);
        else {
-               IRDA_DEBUG(0, "%s(), missing handler\n", __FUNCTION__ );
+               IRDA_DEBUG(0, "%s(), missing handler\n", __func__ );
        }
 }
 
@@ -366,9 +365,21 @@ void ircomm_process_data(struct ircomm_cb *self, struct sk_buff *skb)
 
        clen = skb->data[0];
 
-       /* 
-        * If there are any data hiding in the control channel, we must 
-        * deliver it first. The side effect is that the control channel 
+       /*
+        * Input validation check: a stir4200/mcp2150 combinations sometimes
+        * results in frames with clen > remaining packet size. These are
+        * illegal; if we throw away just this frame then it seems to carry on
+        * fine
+        */
+       if (unlikely(skb->len < (clen + 1))) {
+               IRDA_DEBUG(2, "%s() throwing away illegal frame\n",
+                          __func__ );
+               return;
+       }
+
+       /*
+        * If there are any data hiding in the control channel, we must
+        * deliver it first. The side effect is that the control channel
         * will be removed from the skb
         */
        if (clen > 0)
@@ -378,10 +389,10 @@ void ircomm_process_data(struct ircomm_cb *self, struct sk_buff *skb)
        skb_pull(skb, clen+1);
 
        if (skb->len)
-               ircomm_data_indication(self, skb);              
+               ircomm_data_indication(self, skb);
        else {
                IRDA_DEBUG(4, "%s(), data was control info only!\n",
-                          __FUNCTION__ );
+                          __func__ );
        }
 }
 
@@ -394,13 +405,13 @@ void ircomm_process_data(struct ircomm_cb *self, struct sk_buff *skb)
 int ircomm_control_request(struct ircomm_cb *self, struct sk_buff *skb)
 {
        int ret;
-       
-       IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
+
+       IRDA_DEBUG(2, "%s()\n", __func__ );
 
        IRDA_ASSERT(self != NULL, return -EFAULT;);
        IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -EFAULT;);
        IRDA_ASSERT(skb != NULL, return -EFAULT;);
-       
+
        ret = ircomm_do_event(self, IRCOMM_CONTROL_REQUEST, skb, NULL);
 
        return ret;
@@ -414,10 +425,10 @@ EXPORT_SYMBOL(ircomm_control_request);
  *    Data has arrived on the control channel
  *
  */
-static void ircomm_control_indication(struct ircomm_cb *self, 
+static void ircomm_control_indication(struct ircomm_cb *self,
                                      struct sk_buff *skb, int clen)
 {
-       IRDA_DEBUG(2, "%s()\n", __FUNCTION__ ); 
+       IRDA_DEBUG(2, "%s()\n", __func__ );
 
        /* Use udata for delivering data on the control channel */
        if (self->notify.udata_indication) {
@@ -430,15 +441,15 @@ static void ircomm_control_indication(struct ircomm_cb *self,
 
                /* Remove data channel from control channel */
                skb_trim(ctrl_skb, clen+1);
-       
-               self->notify.udata_indication(self->notify.instance, self, 
+
+               self->notify.udata_indication(self->notify.instance, self,
                                              ctrl_skb);
 
                /* Drop reference count -
                 * see ircomm_tty_control_indication(). */
                dev_kfree_skb(ctrl_skb);
        } else {
-               IRDA_DEBUG(0, "%s(), missing handler\n", __FUNCTION__ );
+               IRDA_DEBUG(0, "%s(), missing handler\n", __func__ );
        }
 }
 
@@ -453,12 +464,12 @@ int ircomm_disconnect_request(struct ircomm_cb *self, struct sk_buff *userdata)
        struct ircomm_info info;
        int ret;
 
-       IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
+       IRDA_DEBUG(2, "%s()\n", __func__ );
 
        IRDA_ASSERT(self != NULL, return -1;);
        IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -1;);
 
-       ret = ircomm_do_event(self, IRCOMM_DISCONNECT_REQUEST, userdata, 
+       ret = ircomm_do_event(self, IRCOMM_DISCONNECT_REQUEST, userdata,
                              &info);
        return ret;
 }
@@ -474,27 +485,27 @@ EXPORT_SYMBOL(ircomm_disconnect_request);
 void ircomm_disconnect_indication(struct ircomm_cb *self, struct sk_buff *skb,
                                  struct ircomm_info *info)
 {
-       IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
-       
+       IRDA_DEBUG(2, "%s()\n", __func__ );
+
        IRDA_ASSERT(info != NULL, return;);
 
        if (self->notify.disconnect_indication) {
                self->notify.disconnect_indication(self->notify.instance, self,
                                                   info->reason, skb);
        } else {
-               IRDA_DEBUG(0, "%s(), missing handler\n", __FUNCTION__ );
+               IRDA_DEBUG(0, "%s(), missing handler\n", __func__ );
        }
 }
 
 /*
  * Function ircomm_flow_request (self, flow)
  *
- *    
+ *
  *
  */
 void ircomm_flow_request(struct ircomm_cb *self, LOCAL_FLOW flow)
 {
-       IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
+       IRDA_DEBUG(2, "%s()\n", __func__ );
 
        IRDA_ASSERT(self != NULL, return;);
        IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return;);
@@ -520,7 +531,7 @@ static void *ircomm_seq_start(struct seq_file *seq, loff_t *pos)
             self = (struct ircomm_cb *) hashbin_get_next(ircomm)) {
                if (off++ == *pos)
                        break;
-               
+
        }
        return self;
 }
@@ -538,7 +549,7 @@ static void ircomm_seq_stop(struct seq_file *seq, void *v)
 }
 
 static int ircomm_seq_show(struct seq_file *seq, void *v)
-{      
+{
        const struct ircomm_cb *self = v;
 
        IRDA_ASSERT(self->magic == IRCOMM_MAGIC, return -EINVAL; );
@@ -551,7 +562,7 @@ static int ircomm_seq_show(struct seq_file *seq, void *v)
        seq_printf(seq,
                   " state: %s, slsap_sel: %#02x, dlsap_sel: %#02x, mode:",
                   ircomm_state[ self->state],
-                  self->slsap_sel, self->dlsap_sel); 
+                  self->slsap_sel, self->dlsap_sel);
 
        if(self->service_type & IRCOMM_3_WIRE_RAW)
                seq_printf(seq, " 3-wire-raw");
@@ -566,7 +577,7 @@ static int ircomm_seq_show(struct seq_file *seq, void *v)
        return 0;
 }
 
-static struct seq_operations ircomm_seq_ops = {
+static const struct seq_operations ircomm_seq_ops = {
        .start  = ircomm_seq_start,
        .next   = ircomm_seq_next,
        .stop   = ircomm_seq_stop,