1 /* 2 * m_ife.c IFE actions module 3 * 4 * This program is free software; you can distribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 * 9 * Authors: J Hadi Salim (jhs (at) mojatatu.com) 10 * 11 */ 12 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <unistd.h> 16 #include <syslog.h> 17 #include <fcntl.h> 18 #include <sys/socket.h> 19 #include <netinet/in.h> 20 #include <arpa/inet.h> 21 #include <string.h> 22 #include <linux/netdevice.h> 23 24 #include "rt_names.h" 25 #include "utils.h" 26 #include "tc_util.h" 27 #include <linux/tc_act/tc_ife.h> 28 29 static void ife_explain(void) 30 { 31 fprintf(stderr, 32 "Usage:... ife {decode|encode} [{ALLOW|USE} ATTR] [dst DMAC] [src SMAC] [type TYPE] [CONTROL] [index INDEX]\n"); 33 fprintf(stderr, 34 "\tALLOW := Encode direction. Allows encoding specified metadata\n" 35 "\t\t e.g \"allow mark\"\n" 36 "\tUSE := Encode direction. Enforce Static encoding of specified metadata\n" 37 "\t\t e.g \"use mark 0x12\"\n" 38 "\tATTR := mark (32-bit), prio (32-bit), tcindex (16-bit)\n" 39 "\tDMAC := 6 byte Destination MAC address to encode\n" 40 "\tSMAC := optional 6 byte Source MAC address to encode\n" 41 "\tTYPE := optional 16 bit ethertype to encode\n" 42 "\tCONTROL := reclassify|pipe|drop|continue|ok\n" 43 "\tINDEX := optional IFE table index value used\n"); 44 fprintf(stderr, "encode is used for sending IFE packets\n"); 45 fprintf(stderr, "decode is used for receiving IFE packets\n"); 46 } 47 48 static void ife_usage(void) 49 { 50 ife_explain(); 51 exit(-1); 52 } 53 54 static int parse_ife(struct action_util *a, int *argc_p, char ***argv_p, 55 int tca_id, struct nlmsghdr *n) 56 { 57 int argc = *argc_p; 58 char **argv = *argv_p; 59 int ok = 0; 60 struct tc_ife p = { 0 }; 61 struct rtattr *tail; 62 struct rtattr *tail2; 63 char dbuf[ETH_ALEN]; 64 char sbuf[ETH_ALEN]; 65 __u16 ife_type = 0; 66 int user_type = 0; 67 __u32 ife_prio = 0; 68 __u32 ife_prio_v = 0; 69 __u32 ife_mark = 0; 70 __u32 ife_mark_v = 0; 71 __u16 ife_tcindex = 0; 72 __u16 ife_tcindex_v = 0; 73 char *daddr = NULL; 74 char *saddr = NULL; 75 76 if (argc <= 0) 77 return -1; 78 79 while (argc > 0) { 80 if (matches(*argv, "ife") == 0) { 81 NEXT_ARG(); 82 continue; 83 } else if (matches(*argv, "decode") == 0) { 84 p.flags = IFE_DECODE; /* readability aid */ 85 ok++; 86 } else if (matches(*argv, "encode") == 0) { 87 p.flags = IFE_ENCODE; 88 ok++; 89 } else if (matches(*argv, "allow") == 0) { 90 NEXT_ARG(); 91 if (matches(*argv, "mark") == 0) { 92 ife_mark = IFE_META_SKBMARK; 93 } else if (matches(*argv, "prio") == 0) { 94 ife_prio = IFE_META_PRIO; 95 } else if (matches(*argv, "tcindex") == 0) { 96 ife_tcindex = IFE_META_TCINDEX; 97 } else { 98 fprintf(stderr, "Illegal meta define <%s>\n", 99 *argv); 100 return -1; 101 } 102 } else if (matches(*argv, "use") == 0) { 103 NEXT_ARG(); 104 if (matches(*argv, "mark") == 0) { 105 NEXT_ARG(); 106 if (get_u32(&ife_mark_v, *argv, 0)) 107 invarg("ife mark val is invalid", 108 *argv); 109 } else if (matches(*argv, "prio") == 0) { 110 NEXT_ARG(); 111 if (get_u32(&ife_prio_v, *argv, 0)) 112 invarg("ife prio val is invalid", 113 *argv); 114 } else if (matches(*argv, "tcindex") == 0) { 115 NEXT_ARG(); 116 if (get_u16(&ife_tcindex_v, *argv, 0)) 117 invarg("ife tcindex val is invalid", 118 *argv); 119 } else { 120 fprintf(stderr, "Illegal meta use type <%s>\n", 121 *argv); 122 return -1; 123 } 124 } else if (matches(*argv, "type") == 0) { 125 NEXT_ARG(); 126 if (get_u16(&ife_type, *argv, 0)) 127 invarg("ife type is invalid", *argv); 128 fprintf(stderr, "IFE type 0x%04X\n", ife_type); 129 user_type = 1; 130 } else if (matches(*argv, "dst") == 0) { 131 NEXT_ARG(); 132 daddr = *argv; 133 if (sscanf(daddr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", 134 dbuf, dbuf + 1, dbuf + 2, 135 dbuf + 3, dbuf + 4, dbuf + 5) != 6) { 136 fprintf(stderr, "Invalid mac address %s\n", 137 daddr); 138 } 139 fprintf(stderr, "dst MAC address <%s>\n", daddr); 140 141 } else if (matches(*argv, "src") == 0) { 142 NEXT_ARG(); 143 saddr = *argv; 144 if (sscanf(saddr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", 145 sbuf, sbuf + 1, sbuf + 2, 146 sbuf + 3, sbuf + 4, sbuf + 5) != 6) { 147 fprintf(stderr, "Invalid mac address %s\n", 148 saddr); 149 } 150 fprintf(stderr, "src MAC address <%s>\n", saddr); 151 } else if (matches(*argv, "help") == 0) { 152 ife_usage(); 153 } else { 154 break; 155 } 156 157 argc--; 158 argv++; 159 } 160 161 parse_action_control_dflt(&argc, &argv, &p.action, false, TC_ACT_PIPE); 162 163 if (argc) { 164 if (matches(*argv, "index") == 0) { 165 NEXT_ARG(); 166 if (get_u32(&p.index, *argv, 0)) { 167 fprintf(stderr, "ife: Illegal \"index\"\n"); 168 return -1; 169 } 170 ok++; 171 argc--; 172 argv++; 173 } 174 } 175 176 if (!ok) { 177 fprintf(stderr, "IFE requires decode/encode specified\n"); 178 ife_usage(); 179 } 180 181 tail = NLMSG_TAIL(n); 182 addattr_l(n, MAX_MSG, tca_id, NULL, 0); 183 addattr_l(n, MAX_MSG, TCA_IFE_PARMS, &p, sizeof(p)); 184 185 if (!(p.flags & IFE_ENCODE)) 186 goto skip_encode; 187 188 if (daddr) 189 addattr_l(n, MAX_MSG, TCA_IFE_DMAC, dbuf, ETH_ALEN); 190 if (user_type) 191 addattr_l(n, MAX_MSG, TCA_IFE_TYPE, &ife_type, 2); 192 else 193 fprintf(stderr, "IFE type 0x%04X\n", ETH_P_IFE); 194 if (saddr) 195 addattr_l(n, MAX_MSG, TCA_IFE_SMAC, sbuf, ETH_ALEN); 196 197 tail2 = NLMSG_TAIL(n); 198 addattr_l(n, MAX_MSG, TCA_IFE_METALST, NULL, 0); 199 if (ife_mark || ife_mark_v) { 200 if (ife_mark_v) 201 addattr_l(n, MAX_MSG, IFE_META_SKBMARK, &ife_mark_v, 4); 202 else 203 addattr_l(n, MAX_MSG, IFE_META_SKBMARK, NULL, 0); 204 } 205 if (ife_prio || ife_prio_v) { 206 if (ife_prio_v) 207 addattr_l(n, MAX_MSG, IFE_META_PRIO, &ife_prio_v, 4); 208 else 209 addattr_l(n, MAX_MSG, IFE_META_PRIO, NULL, 0); 210 } 211 if (ife_tcindex || ife_tcindex_v) { 212 if (ife_tcindex_v) 213 addattr_l(n, MAX_MSG, IFE_META_TCINDEX, &ife_tcindex_v, 214 2); 215 else 216 addattr_l(n, MAX_MSG, IFE_META_TCINDEX, NULL, 0); 217 } 218 219 tail2->rta_len = (void *)NLMSG_TAIL(n) - (void *)tail2; 220 221 skip_encode: 222 tail->rta_len = (void *)NLMSG_TAIL(n) - (void *)tail; 223 224 *argc_p = argc; 225 *argv_p = argv; 226 return 0; 227 } 228 229 static int print_ife(struct action_util *au, FILE *f, struct rtattr *arg) 230 { 231 struct tc_ife *p = NULL; 232 struct rtattr *tb[TCA_IFE_MAX + 1]; 233 __u16 ife_type = 0; 234 __u32 mmark = 0; 235 __u16 mtcindex = 0; 236 __u32 mprio = 0; 237 int has_optional = 0; 238 SPRINT_BUF(b2); 239 240 if (arg == NULL) 241 return -1; 242 243 parse_rtattr_nested(tb, TCA_IFE_MAX, arg); 244 245 if (tb[TCA_IFE_PARMS] == NULL) { 246 fprintf(f, "[NULL ife parameters]"); 247 return -1; 248 } 249 p = RTA_DATA(tb[TCA_IFE_PARMS]); 250 251 fprintf(f, "ife %s ", p->flags & IFE_ENCODE ? "encode" : "decode"); 252 print_action_control(f, "action ", p->action, " "); 253 254 if (tb[TCA_IFE_TYPE]) { 255 ife_type = rta_getattr_u16(tb[TCA_IFE_TYPE]); 256 has_optional = 1; 257 fprintf(f, "type 0x%X ", ife_type); 258 } 259 260 if (has_optional) 261 fprintf(f, "\n\t "); 262 263 if (tb[TCA_IFE_METALST]) { 264 struct rtattr *metalist[IFE_META_MAX + 1]; 265 int len = 0; 266 267 parse_rtattr_nested(metalist, IFE_META_MAX, 268 tb[TCA_IFE_METALST]); 269 270 if (metalist[IFE_META_SKBMARK]) { 271 len = RTA_PAYLOAD(metalist[IFE_META_SKBMARK]); 272 if (len) { 273 mmark = rta_getattr_u32(metalist[IFE_META_SKBMARK]); 274 fprintf(f, "use mark %u ", mmark); 275 } else 276 fprintf(f, "allow mark "); 277 } 278 279 if (metalist[IFE_META_TCINDEX]) { 280 len = RTA_PAYLOAD(metalist[IFE_META_TCINDEX]); 281 if (len) { 282 mtcindex = 283 rta_getattr_u16(metalist[IFE_META_TCINDEX]); 284 fprintf(f, "use tcindex %d ", mtcindex); 285 } else 286 fprintf(f, "allow tcindex "); 287 } 288 289 if (metalist[IFE_META_PRIO]) { 290 len = RTA_PAYLOAD(metalist[IFE_META_PRIO]); 291 if (len) { 292 mprio = rta_getattr_u32(metalist[IFE_META_PRIO]); 293 fprintf(f, "use prio %u ", mprio); 294 } else 295 fprintf(f, "allow prio "); 296 } 297 298 } 299 300 if (tb[TCA_IFE_DMAC]) { 301 has_optional = 1; 302 fprintf(f, "dst %s ", 303 ll_addr_n2a(RTA_DATA(tb[TCA_IFE_DMAC]), 304 RTA_PAYLOAD(tb[TCA_IFE_DMAC]), 0, b2, 305 sizeof(b2))); 306 307 } 308 309 if (tb[TCA_IFE_SMAC]) { 310 has_optional = 1; 311 fprintf(f, "src %s ", 312 ll_addr_n2a(RTA_DATA(tb[TCA_IFE_SMAC]), 313 RTA_PAYLOAD(tb[TCA_IFE_SMAC]), 0, b2, 314 sizeof(b2))); 315 } 316 317 fprintf(f, "\n\t index %u ref %d bind %d", p->index, p->refcnt, 318 p->bindcnt); 319 if (show_stats) { 320 if (tb[TCA_IFE_TM]) { 321 struct tcf_t *tm = RTA_DATA(tb[TCA_IFE_TM]); 322 323 print_tm(f, tm); 324 } 325 } 326 327 fprintf(f, "\n"); 328 329 return 0; 330 } 331 332 struct action_util ife_action_util = { 333 .id = "ife", 334 .parse_aopt = parse_ife, 335 .print_aopt = print_ife, 336 }; 337