1 /* PTP classifier 2 * 3 * This program is free software; you can redistribute it and/or 4 * modify it under the terms of version 2 of the GNU General Public 5 * License as published by the Free Software Foundation. 6 * 7 * This program is distributed in the hope that it will be useful, but 8 * WITHOUT ANY WARRANTY; without even the implied warranty of 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 * General Public License for more details. 11 */ 12 13 /* The below program is the bpf_asm (tools/net/) representation of 14 * the opcode array in the ptp_filter structure. 15 * 16 * For convenience, this can easily be altered and reviewed with 17 * bpf_asm and bpf_dbg, e.g. `./bpf_asm -c prog` where prog is a 18 * simple file containing the below program: 19 * 20 * ldh [12] ; load ethertype 21 * 22 * ; PTP over UDP over IPv4 over Ethernet 23 * test_ipv4: 24 * jneq #0x800, test_ipv6 ; ETH_P_IP ? 25 * ldb [23] ; load proto 26 * jneq #17, drop_ipv4 ; IPPROTO_UDP ? 27 * ldh [20] ; load frag offset field 28 * jset #0x1fff, drop_ipv4 ; don't allow fragments 29 * ldxb 4*([14]&0xf) ; load IP header len 30 * ldh [x + 16] ; load UDP dst port 31 * jneq #319, drop_ipv4 ; is port PTP_EV_PORT ? 32 * ldh [x + 22] ; load payload 33 * and #0xf ; mask PTP_CLASS_VMASK 34 * or #0x10 ; PTP_CLASS_IPV4 35 * ret a ; return PTP class 36 * drop_ipv4: ret #0x0 ; PTP_CLASS_NONE 37 * 38 * ; PTP over UDP over IPv6 over Ethernet 39 * test_ipv6: 40 * jneq #0x86dd, test_8021q ; ETH_P_IPV6 ? 41 * ldb [20] ; load proto 42 * jneq #17, drop_ipv6 ; IPPROTO_UDP ? 43 * ldh [56] ; load UDP dst port 44 * jneq #319, drop_ipv6 ; is port PTP_EV_PORT ? 45 * ldh [62] ; load payload 46 * and #0xf ; mask PTP_CLASS_VMASK 47 * or #0x20 ; PTP_CLASS_IPV6 48 * ret a ; return PTP class 49 * drop_ipv6: ret #0x0 ; PTP_CLASS_NONE 50 * 51 * ; PTP over 802.1Q over Ethernet 52 * test_8021q: 53 * jneq #0x8100, test_ieee1588 ; ETH_P_8021Q ? 54 * ldh [16] ; load inner type 55 * jneq #0x88f7, drop_ieee1588 ; ETH_P_1588 ? 56 * ldb [18] ; load payload 57 * and #0x8 ; as we don't have ports here, test 58 * jneq #0x0, drop_ieee1588 ; for PTP_GEN_BIT and drop these 59 * ldh [18] ; reload payload 60 * and #0xf ; mask PTP_CLASS_VMASK 61 * or #0x40 ; PTP_CLASS_V2_VLAN 62 * ret a ; return PTP class 63 * 64 * ; PTP over Ethernet 65 * test_ieee1588: 66 * jneq #0x88f7, drop_ieee1588 ; ETH_P_1588 ? 67 * ldb [14] ; load payload 68 * and #0x8 ; as we don't have ports here, test 69 * jneq #0x0, drop_ieee1588 ; for PTP_GEN_BIT and drop these 70 * ldh [14] ; reload payload 71 * and #0xf ; mask PTP_CLASS_VMASK 72 * or #0x30 ; PTP_CLASS_L2 73 * ret a ; return PTP class 74 * drop_ieee1588: ret #0x0 ; PTP_CLASS_NONE 75 */ 76 77 #include <linux/skbuff.h> 78 #include <linux/filter.h> 79 #include <linux/ptp_classify.h> 80 81 static struct sk_filter *ptp_insns __read_mostly; 82 83 unsigned int ptp_classify_raw(const struct sk_buff *skb) 84 { 85 return SK_RUN_FILTER(ptp_insns, skb); 86 } 87 EXPORT_SYMBOL_GPL(ptp_classify_raw); 88 89 void __init ptp_classifier_init(void) 90 { 91 static struct sock_filter ptp_filter[] __initdata = { 92 { 0x28, 0, 0, 0x0000000c }, 93 { 0x15, 0, 12, 0x00000800 }, 94 { 0x30, 0, 0, 0x00000017 }, 95 { 0x15, 0, 9, 0x00000011 }, 96 { 0x28, 0, 0, 0x00000014 }, 97 { 0x45, 7, 0, 0x00001fff }, 98 { 0xb1, 0, 0, 0x0000000e }, 99 { 0x48, 0, 0, 0x00000010 }, 100 { 0x15, 0, 4, 0x0000013f }, 101 { 0x48, 0, 0, 0x00000016 }, 102 { 0x54, 0, 0, 0x0000000f }, 103 { 0x44, 0, 0, 0x00000010 }, 104 { 0x16, 0, 0, 0x00000000 }, 105 { 0x06, 0, 0, 0x00000000 }, 106 { 0x15, 0, 9, 0x000086dd }, 107 { 0x30, 0, 0, 0x00000014 }, 108 { 0x15, 0, 6, 0x00000011 }, 109 { 0x28, 0, 0, 0x00000038 }, 110 { 0x15, 0, 4, 0x0000013f }, 111 { 0x28, 0, 0, 0x0000003e }, 112 { 0x54, 0, 0, 0x0000000f }, 113 { 0x44, 0, 0, 0x00000020 }, 114 { 0x16, 0, 0, 0x00000000 }, 115 { 0x06, 0, 0, 0x00000000 }, 116 { 0x15, 0, 9, 0x00008100 }, 117 { 0x28, 0, 0, 0x00000010 }, 118 { 0x15, 0, 15, 0x000088f7 }, 119 { 0x30, 0, 0, 0x00000012 }, 120 { 0x54, 0, 0, 0x00000008 }, 121 { 0x15, 0, 12, 0x00000000 }, 122 { 0x28, 0, 0, 0x00000012 }, 123 { 0x54, 0, 0, 0x0000000f }, 124 { 0x44, 0, 0, 0x00000040 }, 125 { 0x16, 0, 0, 0x00000000 }, 126 { 0x15, 0, 7, 0x000088f7 }, 127 { 0x30, 0, 0, 0x0000000e }, 128 { 0x54, 0, 0, 0x00000008 }, 129 { 0x15, 0, 4, 0x00000000 }, 130 { 0x28, 0, 0, 0x0000000e }, 131 { 0x54, 0, 0, 0x0000000f }, 132 { 0x44, 0, 0, 0x00000030 }, 133 { 0x16, 0, 0, 0x00000000 }, 134 { 0x06, 0, 0, 0x00000000 }, 135 }; 136 struct sock_fprog_kern ptp_prog = { 137 .len = ARRAY_SIZE(ptp_filter), .filter = ptp_filter, 138 }; 139 140 BUG_ON(sk_unattached_filter_create(&ptp_insns, &ptp_prog)); 141 } 142