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, test_8021q_ipv4 ; 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 #0xc0 ; PTP_CLASS_VLAN|PTP_CLASS_L2 62 * ret a ; return PTP class 63 * 64 * ; PTP over UDP over IPv4 over 802.1Q over Ethernet 65 * test_8021q_ipv4: 66 * jneq #0x800, test_8021q_ipv6 ; ETH_P_IP ? 67 * ldb [27] ; load proto 68 * jneq #17, drop_8021q_ipv4 ; IPPROTO_UDP ? 69 * ldh [24] ; load frag offset field 70 * jset #0x1fff, drop_8021q_ipv4; don't allow fragments 71 * ldxb 4*([18]&0xf) ; load IP header len 72 * ldh [x + 20] ; load UDP dst port 73 * jneq #319, drop_8021q_ipv4 ; is port PTP_EV_PORT ? 74 * ldh [x + 26] ; load payload 75 * and #0xf ; mask PTP_CLASS_VMASK 76 * or #0x90 ; PTP_CLASS_VLAN|PTP_CLASS_IPV4 77 * ret a ; return PTP class 78 * drop_8021q_ipv4: ret #0x0 ; PTP_CLASS_NONE 79 * 80 * ; PTP over UDP over IPv6 over 802.1Q over Ethernet 81 * test_8021q_ipv6: 82 * jneq #0x86dd, drop_8021q_ipv6 ; ETH_P_IPV6 ? 83 * ldb [24] ; load proto 84 * jneq #17, drop_8021q_ipv6 ; IPPROTO_UDP ? 85 * ldh [60] ; load UDP dst port 86 * jneq #319, drop_8021q_ipv6 ; is port PTP_EV_PORT ? 87 * ldh [66] ; load payload 88 * and #0xf ; mask PTP_CLASS_VMASK 89 * or #0xa0 ; PTP_CLASS_VLAN|PTP_CLASS_IPV6 90 * ret a ; return PTP class 91 * drop_8021q_ipv6: ret #0x0 ; PTP_CLASS_NONE 92 * 93 * ; PTP over Ethernet 94 * test_ieee1588: 95 * jneq #0x88f7, drop_ieee1588 ; ETH_P_1588 ? 96 * ldb [14] ; load payload 97 * and #0x8 ; as we don't have ports here, test 98 * jneq #0x0, drop_ieee1588 ; for PTP_GEN_BIT and drop these 99 * ldh [14] ; reload payload 100 * and #0xf ; mask PTP_CLASS_VMASK 101 * or #0x40 ; PTP_CLASS_L2 102 * ret a ; return PTP class 103 * drop_ieee1588: ret #0x0 ; PTP_CLASS_NONE 104 */ 105 106#include <linux/skbuff.h> 107#include <linux/filter.h> 108#include <linux/ptp_classify.h> 109 110static struct bpf_prog *ptp_insns __read_mostly; 111 112unsigned int ptp_classify_raw(const struct sk_buff *skb) 113{ 114 return BPF_PROG_RUN(ptp_insns, skb); 115} 116EXPORT_SYMBOL_GPL(ptp_classify_raw); 117 118void __init ptp_classifier_init(void) 119{ 120 static struct sock_filter ptp_filter[] __initdata = { 121 { 0x28, 0, 0, 0x0000000c }, 122 { 0x15, 0, 12, 0x00000800 }, 123 { 0x30, 0, 0, 0x00000017 }, 124 { 0x15, 0, 9, 0x00000011 }, 125 { 0x28, 0, 0, 0x00000014 }, 126 { 0x45, 7, 0, 0x00001fff }, 127 { 0xb1, 0, 0, 0x0000000e }, 128 { 0x48, 0, 0, 0x00000010 }, 129 { 0x15, 0, 4, 0x0000013f }, 130 { 0x48, 0, 0, 0x00000016 }, 131 { 0x54, 0, 0, 0x0000000f }, 132 { 0x44, 0, 0, 0x00000010 }, 133 { 0x16, 0, 0, 0x00000000 }, 134 { 0x06, 0, 0, 0x00000000 }, 135 { 0x15, 0, 9, 0x000086dd }, 136 { 0x30, 0, 0, 0x00000014 }, 137 { 0x15, 0, 6, 0x00000011 }, 138 { 0x28, 0, 0, 0x00000038 }, 139 { 0x15, 0, 4, 0x0000013f }, 140 { 0x28, 0, 0, 0x0000003e }, 141 { 0x54, 0, 0, 0x0000000f }, 142 { 0x44, 0, 0, 0x00000020 }, 143 { 0x16, 0, 0, 0x00000000 }, 144 { 0x06, 0, 0, 0x00000000 }, 145 { 0x15, 0, 32, 0x00008100 }, 146 { 0x28, 0, 0, 0x00000010 }, 147 { 0x15, 0, 7, 0x000088f7 }, 148 { 0x30, 0, 0, 0x00000012 }, 149 { 0x54, 0, 0, 0x00000008 }, 150 { 0x15, 0, 35, 0x00000000 }, 151 { 0x28, 0, 0, 0x00000012 }, 152 { 0x54, 0, 0, 0x0000000f }, 153 { 0x44, 0, 0, 0x000000c0 }, 154 { 0x16, 0, 0, 0x00000000 }, 155 { 0x15, 0, 12, 0x00000800 }, 156 { 0x30, 0, 0, 0x0000001b }, 157 { 0x15, 0, 9, 0x00000011 }, 158 { 0x28, 0, 0, 0x00000018 }, 159 { 0x45, 7, 0, 0x00001fff }, 160 { 0xb1, 0, 0, 0x00000012 }, 161 { 0x48, 0, 0, 0x00000014 }, 162 { 0x15, 0, 4, 0x0000013f }, 163 { 0x48, 0, 0, 0x0000001a }, 164 { 0x54, 0, 0, 0x0000000f }, 165 { 0x44, 0, 0, 0x00000090 }, 166 { 0x16, 0, 0, 0x00000000 }, 167 { 0x06, 0, 0, 0x00000000 }, 168 { 0x15, 0, 8, 0x000086dd }, 169 { 0x30, 0, 0, 0x00000018 }, 170 { 0x15, 0, 6, 0x00000011 }, 171 { 0x28, 0, 0, 0x0000003c }, 172 { 0x15, 0, 4, 0x0000013f }, 173 { 0x28, 0, 0, 0x00000042 }, 174 { 0x54, 0, 0, 0x0000000f }, 175 { 0x44, 0, 0, 0x000000a0 }, 176 { 0x16, 0, 0, 0x00000000 }, 177 { 0x06, 0, 0, 0x00000000 }, 178 { 0x15, 0, 7, 0x000088f7 }, 179 { 0x30, 0, 0, 0x0000000e }, 180 { 0x54, 0, 0, 0x00000008 }, 181 { 0x15, 0, 4, 0x00000000 }, 182 { 0x28, 0, 0, 0x0000000e }, 183 { 0x54, 0, 0, 0x0000000f }, 184 { 0x44, 0, 0, 0x00000040 }, 185 { 0x16, 0, 0, 0x00000000 }, 186 { 0x06, 0, 0, 0x00000000 }, 187 }; 188 struct sock_fprog_kern ptp_prog = { 189 .len = ARRAY_SIZE(ptp_filter), .filter = ptp_filter, 190 }; 191 192 BUG_ON(bpf_prog_create(&ptp_insns, &ptp_prog)); 193} 194