Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

can: cangw: introduce optional uid to reference created routing jobs

Similar to referencing iptables rules by their line number this UID allows to
reference created routing jobs, e.g. to alter configured data modifications.

The UID is an optional non-zero value which can be provided at routing job
creation time. When the UID is set the UID replaces the data modification
configuration as job identification attribute e.g. at job removal time.

Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>

authored by

Oliver Hartkopp and committed by
Marc Kleine-Budde
dd895d7f 3d5db5e1

+61 -12
+5
include/uapi/linux/can/gw.h
··· 78 78 CGW_FILTER, /* specify struct can_filter on source CAN device */ 79 79 CGW_DELETED, /* number of deleted CAN frames (see max_hops param) */ 80 80 CGW_LIM_HOPS, /* limit the number of hops of this specific rule */ 81 + CGW_MOD_UID, /* user defined identifier for modification updates */ 81 82 __CGW_MAX 82 83 }; 83 84 ··· 162 161 * frame can be processed as much as 'max_hops' times (which is given at module 163 162 * load time of the can-gw module). This value is used to reduce the number of 164 163 * possible hops for this gateway rule to a value smaller then max_hops. 164 + * 165 + * CGW_MOD_UID (length 4 bytes): 166 + * Optional non-zero user defined routing job identifier to alter existing 167 + * modification settings at runtime. 165 168 * 166 169 * CGW_CS_XOR (length 4 bytes): 167 170 * Set a simple XOR checksum starting with an initial value into
+56 -12
net/can/gw.c
··· 110 110 void (*xor)(struct can_frame *cf, struct cgw_csum_xor *xor); 111 111 void (*crc8)(struct can_frame *cf, struct cgw_csum_crc8 *crc8); 112 112 } csumfunc; 113 + u32 uid; 113 114 }; 114 115 115 116 ··· 549 548 goto cancel; 550 549 } 551 550 551 + if (gwj->mod.uid) { 552 + if (nla_put_u32(skb, CGW_MOD_UID, gwj->mod.uid) < 0) 553 + goto cancel; 554 + } 555 + 552 556 if (gwj->mod.csumfunc.crc8) { 553 557 if (nla_put(skb, CGW_CS_CRC8, CGW_CS_CRC8_LEN, 554 558 &gwj->mod.csum.crc8) < 0) ··· 625 619 [CGW_DST_IF] = { .type = NLA_U32 }, 626 620 [CGW_FILTER] = { .len = sizeof(struct can_filter) }, 627 621 [CGW_LIM_HOPS] = { .type = NLA_U8 }, 622 + [CGW_MOD_UID] = { .type = NLA_U32 }, 628 623 }; 629 624 630 625 /* check for common and gwtype specific attributes */ ··· 768 761 else 769 762 mod->csumfunc.xor = cgw_csum_xor_neg; 770 763 } 764 + 765 + if (tb[CGW_MOD_UID]) { 766 + nla_memcpy(&mod->uid, tb[CGW_MOD_UID], sizeof(u32)); 767 + } 771 768 } 772 769 773 770 if (gwtype == CGW_TYPE_CAN_CAN) { ··· 813 802 { 814 803 struct rtcanmsg *r; 815 804 struct cgw_job *gwj; 805 + struct cf_mod mod; 806 + struct can_can_gw ccgw; 816 807 u8 limhops = 0; 817 808 int err = 0; 818 809 ··· 832 819 if (r->gwtype != CGW_TYPE_CAN_CAN) 833 820 return -EINVAL; 834 821 822 + err = cgw_parse_attr(nlh, &mod, CGW_TYPE_CAN_CAN, &ccgw, &limhops); 823 + if (err < 0) 824 + return err; 825 + 826 + if (mod.uid) { 827 + 828 + ASSERT_RTNL(); 829 + 830 + /* check for updating an existing job with identical uid */ 831 + hlist_for_each_entry(gwj, &cgw_list, list) { 832 + 833 + if (gwj->mod.uid != mod.uid) 834 + continue; 835 + 836 + /* interfaces & filters must be identical */ 837 + if (memcmp(&gwj->ccgw, &ccgw, sizeof(ccgw))) 838 + return -EINVAL; 839 + 840 + /* update modifications with disabled softirq & quit */ 841 + local_bh_disable(); 842 + memcpy(&gwj->mod, &mod, sizeof(mod)); 843 + local_bh_enable(); 844 + return 0; 845 + } 846 + } 847 + 848 + /* ifindex == 0 is not allowed for job creation */ 849 + if (!ccgw.src_idx || !ccgw.dst_idx) 850 + return -ENODEV; 851 + 835 852 gwj = kmem_cache_alloc(cgw_cache, GFP_KERNEL); 836 853 if (!gwj) 837 854 return -ENOMEM; ··· 871 828 gwj->deleted_frames = 0; 872 829 gwj->flags = r->flags; 873 830 gwj->gwtype = r->gwtype; 831 + gwj->limit_hops = limhops; 874 832 875 - err = cgw_parse_attr(nlh, &gwj->mod, CGW_TYPE_CAN_CAN, &gwj->ccgw, 876 - &limhops); 877 - if (err < 0) 878 - goto out; 833 + /* insert already parsed information */ 834 + memcpy(&gwj->mod, &mod, sizeof(mod)); 835 + memcpy(&gwj->ccgw, &ccgw, sizeof(ccgw)); 879 836 880 837 err = -ENODEV; 881 - 882 - /* ifindex == 0 is not allowed for job creation */ 883 - if (!gwj->ccgw.src_idx || !gwj->ccgw.dst_idx) 884 - goto out; 885 838 886 839 gwj->src.dev = __dev_get_by_index(&init_net, gwj->ccgw.src_idx); 887 840 ··· 894 855 895 856 if (gwj->dst.dev->type != ARPHRD_CAN) 896 857 goto out; 897 - 898 - gwj->limit_hops = limhops; 899 858 900 859 ASSERT_RTNL(); 901 860 ··· 968 931 if (gwj->limit_hops != limhops) 969 932 continue; 970 933 971 - if (memcmp(&gwj->mod, &mod, sizeof(mod))) 972 - continue; 934 + /* we have a match when uid is enabled and identical */ 935 + if (gwj->mod.uid || mod.uid) { 936 + if (gwj->mod.uid != mod.uid) 937 + continue; 938 + } else { 939 + /* no uid => check for identical modifications */ 940 + if (memcmp(&gwj->mod, &mod, sizeof(mod))) 941 + continue; 942 + } 973 943 974 944 /* if (r->gwtype == CGW_TYPE_CAN_CAN) - is made sure here */ 975 945 if (memcmp(&gwj->ccgw, &ccgw, sizeof(ccgw)))