]> rtime.felk.cvut.cz Git - socketcan-devel.git/commitdiff
Bring 2.4 kernel tree up-to-date to the latest mainline fixes.
authorhartkopp <hartkopp@030b6a49-0b11-0410-94ab-b0dab22257f2>
Fri, 19 Dec 2008 15:45:30 +0000 (15:45 +0000)
committerhartkopp <hartkopp@030b6a49-0b11-0410-94ab-b0dab22257f2>
Fri, 19 Dec 2008 15:45:30 +0000 (15:45 +0000)
git-svn-id: svn://svn.berlios.de//socketcan/trunk@882 030b6a49-0b11-0410-94ab-b0dab22257f2

kernel/2.4/include/linux/can/core.h
kernel/2.4/net/can/af_can.c
kernel/2.4/net/can/bcm.c
kernel/2.4/net/can/compat.h
kernel/2.4/net/can/raw.c

index 0ec6cc3be43223f3621eb62c7a93f9f559373d69..bedfc0a2fa8896202945e96ca3ca7a8d6173dbbf 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
 
-#define CAN_VERSION "20071116"
+#define CAN_VERSION "20081130"
 
 /* increment this number each time you change some user-space interface */
 #define CAN_ABI_VERSION "8"
index 308a03cfd27764fdd01c3327c4f7e2b435809435..7b3d0b6d93817e8a3c5e23ce04a017cdb34b0f27 100644 (file)
@@ -195,12 +195,19 @@ static int can_create(struct socket *sock, int protocol)
  *  -ENOBUFS on full driver queue (see net_xmit_errno())
  *  -ENOMEM when local loopback failed at calling skb_clone()
  *  -EPERM when trying to send on a non-CAN interface
+ *  -EINVAL when the skb->data does not contain a valid CAN frame
  */
 int can_send(struct sk_buff *skb, int loop)
 {
        struct sk_buff *newskb = NULL;
+       struct can_frame *cf = (struct can_frame *)skb->data;
        int err;
 
+       if (skb->len != sizeof(struct can_frame) || cf->can_dlc > 8) {
+               kfree_skb(skb);
+               return -EINVAL;
+       }
+
        if (skb->dev->type != ARPHRD_CAN) {
                kfree_skb(skb);
                return -EPERM;
@@ -292,23 +299,52 @@ static struct dev_rcv_lists *find_dev_rcv_lists(struct net_device *dev)
        return d;
 }
 
+/**
+ * find_rcv_list - determine optimal filterlist inside device filter struct
+ * @can_id: pointer to CAN identifier of a given can_filter
+ * @mask: pointer to CAN mask of a given can_filter
+ * @d: pointer to the device filter struct
+ *
+ * Description:
+ *  Returns the optimal filterlist to reduce the filter handling in the
+ *  receive path. This function is called by service functions that need
+ *  to register or unregister a can_filter in the filter lists.
+ *
+ *  A filter matches in general, when
+ *
+ *          <received_can_id> & mask == can_id & mask
+ *
+ *  so every bit set in the mask (even CAN_EFF_FLAG, CAN_RTR_FLAG) describe
+ *  relevant bits for the filter.
+ *
+ *  The filter can be inverted (CAN_INV_FILTER bit set in can_id) or it can
+ *  filter for error frames (CAN_ERR_FLAG bit set in mask). For error frames
+ *  there is a special filterlist and a special rx path filter handling.
+ *
+ * Return:
+ *  Pointer to optimal filterlist for the given can_id/mask pair.
+ *  Constistency checked mask.
+ *  Reduced can_id to have a preprocessed filter compare value.
+ */
 static struct receiver **find_rcv_list(canid_t *can_id, canid_t *mask,
                                       struct dev_rcv_lists *d)
 {
        canid_t inv = *can_id & CAN_INV_FILTER; /* save flag before masking */
 
-       /* filter error frames */
+       /* filter for error frames in extra filterlist */
        if (*mask & CAN_ERR_FLAG) {
-               /* clear CAN_ERR_FLAG in list entry */
+               /* clear CAN_ERR_FLAG in filter entry */
                *mask &= CAN_ERR_MASK;
                return &d->rx[RX_ERR];
        }
 
-       /* ensure valid values in can_mask */
-       if (*mask & CAN_EFF_FLAG)
-               *mask &= (CAN_EFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG);
-       else
-               *mask &= (CAN_SFF_MASK | CAN_RTR_FLAG);
+       /* with cleared CAN_ERR_FLAG we have a simple mask/value filterpair */
+
+#define CAN_EFF_RTR_FLAGS (CAN_EFF_FLAG | CAN_RTR_FLAG)
+
+       /* ensure valid values in can_mask for 'SFF only' frame filtering */
+       if ((*mask & CAN_EFF_FLAG) && !(*can_id & CAN_EFF_FLAG))
+               *mask &= (CAN_SFF_MASK | CAN_EFF_RTR_FLAGS);
 
        /* reduce condition testing at receive time */
        *can_id &= *mask;
@@ -321,15 +357,19 @@ static struct receiver **find_rcv_list(canid_t *can_id, canid_t *mask,
        if (!(*mask))
                return &d->rx[RX_ALL];
 
-       /* use extra filterset for the subscription of exactly *ONE* can_id */
-       if (*can_id & CAN_EFF_FLAG) {
-               if (*mask == (CAN_EFF_MASK | CAN_EFF_FLAG)) {
-                       /* RFC: a use-case for hash-tables in the future? */
-                       return &d->rx[RX_EFF];
+       /* extra filterlists for the subscription of a single non-RTR can_id */
+       if (((*mask & CAN_EFF_RTR_FLAGS) == CAN_EFF_RTR_FLAGS)
+           && !(*can_id & CAN_RTR_FLAG)) {
+
+               if (*can_id & CAN_EFF_FLAG) {
+                       if (*mask == (CAN_EFF_MASK | CAN_EFF_RTR_FLAGS)) {
+                               /* RFC: a future use-case for hash-tables? */
+                               return &d->rx[RX_EFF];
+                       }
+               } else {
+                       if (*mask == (CAN_SFF_MASK | CAN_EFF_RTR_FLAGS))
+                               return &d->rx_sff[*can_id];
                }
-       } else {
-               if (*mask == CAN_SFF_MASK)
-                       return &d->rx_sff[*can_id];
        }
 
        /* default: filter via can_id/can_mask */
@@ -533,7 +573,10 @@ static int can_rcv_filter(struct dev_rcv_lists *d, struct sk_buff *skb)
                }
        }
 
-       /* check CAN_ID specific entries */
+       /* check filterlists for single non-RTR can_ids */
+       if (can_id & CAN_RTR_FLAG)
+               return matches;
+
        if (can_id & CAN_EFF_FLAG) {
                for (r = d->rx[RX_EFF]; r; r = r->next) {
                        if (r->can_id == can_id) {
@@ -556,6 +599,7 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev,
                   struct packet_type *pt)
 {
        struct dev_rcv_lists *d;
+       struct can_frame *cf = (struct can_frame *)skb->data;
        int matches;
 
        if (dev->type != ARPHRD_CAN) {
@@ -563,6 +607,8 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev,
                return 0;
        }
 
+       BUG_ON(skb->len != sizeof(struct can_frame) || cf->can_dlc > 8);
+
        /* update statistics */
        can_stats.rx_frames++;
        can_stats.rx_frames_delta++;
index de3d3bfb707e892f2133fd6fa3b95018fee68b36..ddb2ebaa016fc92c73b02f964e4c1974dad6164e 100644 (file)
@@ -66,8 +66,9 @@ RCSID("$Id$");
 #define BCM_CAN_DLC_MASK 0x0F /* clean private flags in can_dlc by masking */
 
 /* get best masking value for can_rx_register() for a given single can_id */
-#define REGMASK(id) ((id & CAN_RTR_FLAG) | ((id & CAN_EFF_FLAG) ? \
-                       (CAN_EFF_MASK | CAN_EFF_FLAG) : CAN_SFF_MASK))
+#define REGMASK(id) ((id & CAN_EFF_FLAG) ? \
+                    (CAN_EFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG) : \
+                    (CAN_SFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG))
 
 #define CAN_BCM_VERSION CAN_VERSION
 static __initdata const char banner[] = KERN_INFO
@@ -333,7 +334,7 @@ static void bcm_send_to_user(struct bcm_op *op, struct bcm_msg_head *head,
 
        if (head->nframes) {
                /* can_frames starting here */
-               firstframe = (struct can_frame *) skb->tail;
+               firstframe = (struct can_frame *)skb->tail;
 
                memcpy(skb_put(skb, datalen), frames, datalen);
 
@@ -826,6 +827,10 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
                for (i = 0; i < msg_head->nframes; i++) {
                        err = memcpy_fromiovec((u8 *)&op->frames[i],
                                               msg->msg_iov, CFSIZ);
+
+                       if (op->frames[i].can_dlc > 8)
+                               err = -EINVAL;
+
                        if (err < 0)
                                return err;
 
@@ -858,6 +863,10 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
                for (i = 0; i < msg_head->nframes; i++) {
                        err = memcpy_fromiovec((u8 *)&op->frames[i],
                                               msg->msg_iov, CFSIZ);
+
+                       if (op->frames[i].can_dlc > 8)
+                               err = -EINVAL;
+
                        if (err < 0) {
                                if (op->frames != &op->sframe)
                                        kfree(op->frames);
@@ -1169,9 +1178,12 @@ static int bcm_tx_send(struct msghdr *msg, int ifindex, struct sock *sk)
 
        skb->dev = dev;
        skb->sk  = sk;
-       can_send(skb, 1); /* send with loopback */
+       err = can_send(skb, 1); /* send with loopback */
        dev_put(dev);
 
+       if (err)
+               return err;
+
        return CFSIZ + MHSIZ;
 }
 
@@ -1190,6 +1202,10 @@ static int bcm_sendmsg(struct socket *sock, struct msghdr *msg, int size,
        if (!bo->bound)
                return -ENOTCONN;
 
+       /* check for valid message length from userspace */
+       if (size < MHSIZ || (size - MHSIZ) % CFSIZ)
+               return -EINVAL;
+
        /* check for alternative ifindex for this bcm_op */
 
        if (!ifindex && msg->msg_name) {
@@ -1264,8 +1280,8 @@ static int bcm_sendmsg(struct socket *sock, struct msghdr *msg, int size,
                break;
 
        case TX_SEND:
-               /* we need at least one can_frame */
-               if (msg_head.nframes < 1)
+               /* we need exactly one can_frame behind the msg head */
+               if ((msg_head.nframes != 1) || (size != CFSIZ + MHSIZ))
                        ret = -EINVAL;
                else
                        ret = bcm_tx_send(msg, ifindex, sk);
index dc5489bf6ec9fa46bfdc8f7523e96e827d53d627..645d9c0bc9176faa7ce4f6c30e4d2d1c2e93792f 100644 (file)
@@ -42,7 +42,13 @@ static inline void setup_timer(struct timer_list * timer,
 #define sk_refcnt              refcnt
 
 /* Force a compilation error if condition is true */
+#ifndef BUILD_BUG_ON
 #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
+#endif
+
+#ifndef BUG_ON
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
+#endif
 
 #undef container_of
 /*
index 14c2c3d41298019d267a38aba514a7cd2be306c0..30e3a51a7f9a5857678f7f9b069c06a4b8746931 100644 (file)
@@ -640,6 +640,9 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, int size,
        } else
                ifindex = ro->ifindex;
 
+       if (size != sizeof(struct can_frame))
+               return -EINVAL;
+
        dev = dev_get_by_index(&init_net, ifindex);
        if (!dev)
                return -ENXIO;