On Tue, Feb 09, 2010 at 06:03:30PM +0100, Oliver Hartkopp wrote:
> Kurt Van Dijck wrote:
> > On Tue, Feb 09, 2010 at 10:33:05AM +0100, Wolfgang Grandegger wrote:
> 
> 
> >> Anyhow, there is no
> >> user of this code. Why should we add it?
> 
> > 
> > The newly introduce 'code' does not add features, nor does it add
> > 'functions', but it add 'flexibility'.
> 
[...]
> Hi Kurt,
> 
> if it's ok for you, i would like to move the discussion to your intended
> extensions ...
* first things first: the patch is white-space mangled too. sorry for
  that. I attached a better one below.
* The proposed patch is seperate from any protocol extension. It's about
  binary compatibility.
  To visualize my problem, I included my current version of
  sockaddr_can below. Note that when you would extend sockaddr_can in this or
  any other way, you'll want the patch in order to not recompile every
  userspace binary.
* Since I'm not the only contributor, I'm not in a position to force
  such things, now or later :-). If the discussion is moved, I'll have
  to accept that.

> 
> AFAIK in J1939 you have broadcast announce messages (BAM) that send on two
> different CAN identifiers in one direction. This could be handled within the
> union.
In fact, there's a lot more.
J1939 introduces a network addressing (both source & destination).
And this addressing tables (comparable to arp tables I think) should be
kept in kernel.
The CAN id's are then seperated into SRC & DST fields, and a PGN
(iso11783 naming). SRC & DST is comparable to IP, in the way that is a
mapped address from an 'ISONAME' (iso11783 naming). The PGN is roughly
to be compared with a TCP port number, but again, roughly.

So, J1939 much better matches the kernel-to-userspace API sendto,
   recvfrom, .... using all a 'struct sockaddr_xxx' derivate.
I could use a seperate struct, but don't think that's an elegant
solution.

The transport protocol indeed used 2 'PGN's, but they are fixed. the
transport protocol must thus be serialized, but that's a different
thing.

> 
> What are your proposed new structure elements for a J1939 socketcan address?
struct sockaddr_can {
        sa_family_t can_family;
        int         can_ifindex;
        union {
                /* transport protocol class address information (e.g. ISOTP) */
                struct { canid_t rx_id, tx_id; } tp;

                /* J1939 address information */
                struct {
                        /*
                         * any of these parameters that are used in connect()
                         * can be overruled by using sendto()
                         */
                        /* name: bind() sets source, connect sets dest */
                        uint64_t name; /* bind != connect */
                        /* pgn & priority: can be set by bind & connect */
                        uint32_t pgn;
                        uint8_t priority;
                        /*
                         * 'sa' is used in bind() & sendto(),
                         * 'da' is used in connect() & sendto()
                         */
                        uint8_t sa; /* the originator address */
                        uint8_t da; /* the destination address */
                } j1939;

                /* reserved for future CAN protocols address information */
        } can_addr;
};

this is my current working version.

Now, this is a preliminary thing, and only for j1939/iso11783.

> 
> Regards,
> Oliver
Regards,
Kurt
> 
---
This patch solves a problem that 'regular' socket types
do require the full struct sockaddr_can be present, while using only the
first few fields.

It does so by not testing on sizeof() but using a newly introduced macro
'partial_struct_size', which returns the size of the struct up to the
requested struct member.
When socketcan is compiled with bigger struct sockaddr_can, It will not
pose any problems with userspace binaries that got compiled with older
revisions of struct sockaddr_can.
Please not that the 'partial_struct_size' macro can only work when the
struct in only added to, not modified, which is the case here.

Signed-off-by: Kurt Van Dijck <[email protected]>
---

Index: include/socketcan/can/core.h
===================================================================
--- include/socketcan/can/core.h        (revision 1124)
+++ include/socketcan/can/core.h        (working copy)
@@ -52,6 +52,15 @@
 #endif
 };
 
+
+/*
+ * partial_struct_size
+ * macro to find the size of a struct up to a requested member (inclusive)
+ */
+#define partial_struct_size(member, type) \
+       (offsetof(typeof(type), member) + \
+        sizeof(((typeof(type) *)(0))->member))
+
 /* function prototypes for the CAN networklayer core (af_can.c) */
 
 extern int  can_proto_register(struct can_proto *cp);
Index: net/can/isotp.c
===================================================================
--- net/can/isotp.c     (revision 1124)
+++ net/can/isotp.c     (working copy)
@@ -826,7 +826,7 @@
        int err = 0;
        int notify_enetdown = 0;
 
-       if (len < sizeof(*addr))
+       if (len < partial_struct_size(can_addr.tp, *addr))
                return -EINVAL;
 
        if (addr->can_addr.tp.rx_id == addr->can_addr.tp.tx_id)
Index: net/can/bcm.c
===================================================================
--- net/can/bcm.c       (revision 1124)
+++ net/can/bcm.c       (working copy)
@@ -1610,6 +1610,9 @@
        if (bo->bound)
                return -EISCONN;
 
+       if (len < partial_struct_size(can_ifindex, *addr))
+               return -EINVAL;
+
        /* bind a device to this socket */
        if (addr->can_ifindex) {
                struct net_device *dev;
Index: net/can/raw.c
===================================================================
--- net/can/raw.c       (revision 1124)
+++ net/can/raw.c       (working copy)
@@ -354,7 +354,7 @@
        int err = 0;
        int notify_enetdown = 0;
 
-       if (len < sizeof(*addr))
+       if (len < partial_struct_size(can_ifindex, *addr))
                return -EINVAL;
 
        lock_sock(sk);
Index: net/can/bcm-prior-2-6-22.c
===================================================================
--- net/can/bcm-prior-2-6-22.c  (revision 1124)
+++ net/can/bcm-prior-2-6-22.c  (working copy)
@@ -1475,6 +1475,9 @@
        if (bo->bound)
                return -EISCONN;
 
+       if (len < partial_struct_size(can_ifindex, *addr))
+               return -EINVAL;
+
        /* bind a device to this socket */
        if (addr->can_ifindex) {
                struct net_device *dev;
_______________________________________________
Socketcan-core mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/socketcan-core

Reply via email to