From fbc2459bef44d10a1bd7481d53cf65d799bd37cf Mon Sep 17 00:00:00 2001 From: hartkopp Date: Fri, 19 Feb 2010 05:12:49 +0000 Subject: [PATCH] Swapped the parameters inside the modifier attribute to have the aligned struct can_frame the first parameter. This allows the usage of 'packed' structs in userspace with an aligned access to the CAN frame structures. git-svn-id: svn://svn.berlios.de//socketcan/trunk@1129 030b6a49-0b11-0410-94ab-b0dab22257f2 --- kernel/2.6/include/socketcan/can/gw.h | 2 +- kernel/2.6/net/can/gw.c | 32 ++++++++--------- test/gwtest.c | 50 ++++++++++++++++++++++----- 3 files changed, 58 insertions(+), 26 deletions(-) diff --git a/kernel/2.6/include/socketcan/can/gw.h b/kernel/2.6/include/socketcan/can/gw.h index 20feea3..b0dba41 100644 --- a/kernel/2.6/include/socketcan/can/gw.h +++ b/kernel/2.6/include/socketcan/can/gw.h @@ -65,8 +65,8 @@ enum { * Specifies a modification that's done to a received CAN frame before it is * send out to the destination interface. * - * affected CAN frame elements * data used as operator + * affected CAN frame elements * * Remark: The attribute data is a linear buffer. Beware of sending structs! */ diff --git a/kernel/2.6/net/can/gw.c b/kernel/2.6/net/can/gw.c index dafd079..262934b 100644 --- a/kernel/2.6/net/can/gw.c +++ b/kernel/2.6/net/can/gw.c @@ -334,16 +334,16 @@ static int gw_create_job(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) nla_len(tb[CGW_MOD_AND]) == CGW_MODATTR_LEN) { nla_memcpy(&buf, tb[CGW_MOD_AND], CGW_MODATTR_LEN); - memcpy(&gwj->ccgw.modframe.and, &buf[1], + memcpy(&gwj->ccgw.modframe.and, buf, sizeof(struct can_frame)); - if (buf[0] & CGW_MOD_ID) + if (buf[sizeof(struct can_frame)] & CGW_MOD_ID) gwj->ccgw.modfunc[modidx++] = mod_and_id; - if (buf[0] & CGW_MOD_DLC) + if (buf[sizeof(struct can_frame)] & CGW_MOD_DLC) gwj->ccgw.modfunc[modidx++] = mod_and_dlc; - if (buf[0] & CGW_MOD_DATA) + if (buf[sizeof(struct can_frame)] & CGW_MOD_DATA) gwj->ccgw.modfunc[modidx++] = mod_and_data; } @@ -351,16 +351,16 @@ static int gw_create_job(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) nla_len(tb[CGW_MOD_OR]) == CGW_MODATTR_LEN) { nla_memcpy(&buf, tb[CGW_MOD_OR], CGW_MODATTR_LEN); - memcpy(&gwj->ccgw.modframe.or, &buf[1], + memcpy(&gwj->ccgw.modframe.or, buf, sizeof(struct can_frame)); - if (buf[0] & CGW_MOD_ID) + if (buf[sizeof(struct can_frame)] & CGW_MOD_ID) gwj->ccgw.modfunc[modidx++] = mod_or_id; - if (buf[0] & CGW_MOD_DLC) + if (buf[sizeof(struct can_frame)] & CGW_MOD_DLC) gwj->ccgw.modfunc[modidx++] = mod_or_dlc; - if (buf[0] & CGW_MOD_DATA) + if (buf[sizeof(struct can_frame)] & CGW_MOD_DATA) gwj->ccgw.modfunc[modidx++] = mod_or_data; } @@ -368,16 +368,16 @@ static int gw_create_job(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) nla_len(tb[CGW_MOD_XOR]) == CGW_MODATTR_LEN) { nla_memcpy(&buf, tb[CGW_MOD_XOR], CGW_MODATTR_LEN); - memcpy(&gwj->ccgw.modframe.xor, &buf[1], + memcpy(&gwj->ccgw.modframe.xor, buf, sizeof(struct can_frame)); - if (buf[0] & CGW_MOD_ID) + if (buf[sizeof(struct can_frame)] & CGW_MOD_ID) gwj->ccgw.modfunc[modidx++] = mod_xor_id; - if (buf[0] & CGW_MOD_DLC) + if (buf[sizeof(struct can_frame)] & CGW_MOD_DLC) gwj->ccgw.modfunc[modidx++] = mod_xor_dlc; - if (buf[0] & CGW_MOD_DATA) + if (buf[sizeof(struct can_frame)] & CGW_MOD_DATA) gwj->ccgw.modfunc[modidx++] = mod_xor_data; } @@ -385,16 +385,16 @@ static int gw_create_job(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) nla_len(tb[CGW_MOD_SET]) == CGW_MODATTR_LEN) { nla_memcpy(&buf, tb[CGW_MOD_SET], CGW_MODATTR_LEN); - memcpy(&gwj->ccgw.modframe.set, &buf[1], + memcpy(&gwj->ccgw.modframe.set, buf, sizeof(struct can_frame)); - if (buf[0] & CGW_MOD_ID) + if (buf[sizeof(struct can_frame)] & CGW_MOD_ID) gwj->ccgw.modfunc[modidx++] = mod_set_id; - if (buf[0] & CGW_MOD_DLC) + if (buf[sizeof(struct can_frame)] & CGW_MOD_DLC) gwj->ccgw.modfunc[modidx++] = mod_set_dlc; - if (buf[0] & CGW_MOD_DATA) + if (buf[sizeof(struct can_frame)] & CGW_MOD_DATA) gwj->ccgw.modfunc[modidx++] = mod_set_data; } diff --git a/test/gwtest.c b/test/gwtest.c index 283d420..4aeb871 100644 --- a/test/gwtest.c +++ b/test/gwtest.c @@ -44,6 +44,8 @@ int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data, return 0; } +#define USE_PACKED_STRUCT + int main(int argc, char **argv) { int s; @@ -56,10 +58,20 @@ int main(int argc, char **argv) } req; - static struct can_frame modframe; struct can_filter filter; struct sockaddr_nl nladdr; + +#ifdef USE_PACKED_STRUCT + struct modattr { + struct can_frame cf; + __u8 modtype; + } __attribute__((packed)); + + struct modattr modmsg; +#else + static struct can_frame modframe; char modbuf[CGW_MODATTR_LEN]; +#endif s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); @@ -81,25 +93,45 @@ int main(int argc, char **argv) filter.can_mask = 0x700; addattr_l(&req.n, sizeof(req), CGW_FILTER, &filter, sizeof(filter)); + +#ifdef USE_PACKED_STRUCT + + if (sizeof(modmsg) != CGW_MODATTR_LEN) { + printf("Problem with packed msg. Use linear copy instead.\n"); + return 1; + } + + modmsg.cf.can_id = 0x555; + modmsg.cf.can_dlc = 5; + *(unsigned long long *)modmsg.cf.data = 0x5555555555555555ULL; + + modmsg.modtype = CGW_MOD_ID; + addattr_l(&req.n, sizeof(req), CGW_MOD_SET, &modmsg, CGW_MODATTR_LEN); + + modmsg.modtype = CGW_MOD_DLC; + addattr_l(&req.n, sizeof(req), CGW_MOD_AND, &modmsg, CGW_MODATTR_LEN); + + modmsg.modtype = CGW_MOD_DATA; + addattr_l(&req.n, sizeof(req), CGW_MOD_XOR, &modmsg, CGW_MODATTR_LEN); + +#else + modframe.can_id = 0x555; modframe.can_dlc = 5; *(unsigned long long *)modframe.data = 0x5555555555555555ULL; - modbuf[0] = CGW_MOD_ID; - memcpy(&modbuf[1], &modframe, sizeof(struct can_frame)); + memcpy(modbuf, &modframe, sizeof(struct can_frame)); + modbuf[sizeof(struct can_frame)] = CGW_MOD_ID; addattr_l(&req.n, sizeof(req), CGW_MOD_SET, modbuf, CGW_MODATTR_LEN); - modbuf[0] = CGW_MOD_DLC; - memcpy(&modbuf[1], &modframe, sizeof(struct can_frame)); - + modbuf[sizeof(struct can_frame)] = CGW_MOD_DLC; addattr_l(&req.n, sizeof(req), CGW_MOD_AND, modbuf, CGW_MODATTR_LEN); - modbuf[0] = CGW_MOD_DATA; - memcpy(&modbuf[1], &modframe, sizeof(struct can_frame)); - + modbuf[sizeof(struct can_frame)] = CGW_MOD_DATA; addattr_l(&req.n, sizeof(req), CGW_MOD_XOR, modbuf, CGW_MODATTR_LEN); +#endif memset(&nladdr, 0, sizeof(nladdr)); nladdr.nl_family = AF_NETLINK; -- 2.39.2