diff options
author | Stephen Hemminger <stephen.hemminger@vyatta.com> | 2009-04-15 15:39:34 -0700 |
---|---|---|
committer | Stephen Hemminger <stephen.hemminger@vyatta.com> | 2009-04-15 15:39:34 -0700 |
commit | b4d41f41b6d601f876f442ae19ccdb4f0c3552c5 (patch) | |
tree | 8032e8f020268126fc615616191e59b61ce02c33 /tc/f_u32.c | |
parent | b9ab720e33748cd022f095620e75ca7eba24a965 (diff) | |
download | iproute2-b4d41f41b6d601f876f442ae19ccdb4f0c3552c5.tar.gz |
Add u32 extension to match on ether source/destination
Use existing u32 mechanism to match based on Ethernet header.
No need for protocol that already exists.
Diffstat (limited to 'tc/f_u32.c')
-rw-r--r-- | tc/f_u32.c | 70 |
1 files changed, 70 insertions, 0 deletions
@@ -405,6 +405,48 @@ static int parse_ip6_addr(int *argc_p, char ***argv_p, return res; } +static int parse_ether_addr(int *argc_p, char ***argv_p, + struct tc_u32_sel *sel, int off) +{ + int res = -1; + int argc = *argc_p; + char **argv = *argv_p; + __u8 addr[6]; + int offmask = 0; + __u32 key; + int i; + + if (argc < 1) + return -1; + + if (sscanf(*argv, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", + addr + 0, addr + 1, addr + 2, + addr + 3, addr + 4, addr + 5) != 6) { + fprintf(stderr, "parse_ether_addr: improperly formed address '%s'\n", + *argv); + return -1; + } + + argc--; argv++; + if (argc > 0 && strcmp(argv[0], "at") == 0) { + NEXT_ARG(); + if (parse_at(&argc, &argv, &off, &offmask)) + return -1; + } + + for (i = 0; i < 6; i += 2) { + key = *(__u16 *) (addr + i); + + res = pack_key16(sel, key, 0xFFFF, off + i, offmask); + if (res < 0) + return -1; + } + + *argc_p = argc; + *argv_p = argv; + return res; +} + static int parse_ip(int *argc_p, char ***argv_p, struct tc_u32_sel *sel) { int res = -1; @@ -509,6 +551,31 @@ static int parse_ip6(int *argc_p, char ***argv_p, struct tc_u32_sel *sel) return res; } +static int parse_ether(int *argc_p, char ***argv_p, struct tc_u32_sel *sel) +{ + int res = -1; + int argc = *argc_p; + char **argv = *argv_p; + + if (argc < 2) + return -1; + + if (strcmp(*argv, "src") == 0) { + NEXT_ARG(); + res = parse_ether_addr(&argc, &argv, sel, -8); + } else if (strcmp(*argv, "dst") == 0) { + NEXT_ARG(); + res = parse_ether_addr(&argc, &argv, sel, -14); + } else { + fprintf(stderr, "Unknown match: ether %s\n", *argv); + return -1; + } + + *argc_p = argc; + *argv_p = argv; + return res; +} + #define parse_tcp parse_udp static int parse_udp(int *argc_p, char ***argv_p, struct tc_u32_sel *sel) { @@ -629,6 +696,9 @@ static int parse_selector(int *argc_p, char ***argv_p, } else if (matches(*argv, "mark") == 0) { NEXT_ARG(); res = parse_mark(&argc, &argv, n); + } else if (matches(*argv, "ether") == 0) { + NEXT_ARG(); + res = parse_ether(&argc, &argv, sel); } else return -1; |