12ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó#include <stdio.h> 22ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó#include <string.h> 32ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó#include <stdlib.h> 42ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó#include <errno.h> 55d9678ad3eabc34ac40dfe055d7f6a8e44445a5aJan Engelhardt#include <xtables.h> 62ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó#include <linux/netfilter_ipv6/ip6t_opts.h> 7ddac6c5bc636003d664d25c08ea3fe176565096cJan Engelhardt 82ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó#define DEBUG 0 92ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó 107a969bb06cef93b6b0dadbb784c30d33856445d1Jan Engelhardtenum { 117a969bb06cef93b6b0dadbb784c30d33856445d1Jan Engelhardt O_HBH_LEN = 0, 127a969bb06cef93b6b0dadbb784c30d33856445d1Jan Engelhardt O_HBH_OPTS, 137a969bb06cef93b6b0dadbb784c30d33856445d1Jan Engelhardt}; 147a969bb06cef93b6b0dadbb784c30d33856445d1Jan Engelhardt 15997045f536026c0d643bf884da5ff5de2605197fJan Engelhardtstatic void hbh_help(void) 162ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó{ 172ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó printf( 188b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt"hbh match options:\n" 19967279231a9ecfa99f26694a954afc535c63db1dJan Engelhardt"[!] --hbh-len length total length of this header\n" 20e2f588ab7481760f069cd30d3146569f074721aaJan Engelhardt" --hbh-opts TYPE[:LEN][,TYPE[:LEN]...] \n" 21e2f588ab7481760f069cd30d3146569f074721aaJan Engelhardt" Options and its length (list, max: %d)\n", 228b7c64d6ba156a99008fcd810cba874c73294333Jan EngelhardtIP6T_OPTS_OPTSNR); 232ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó} 242ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó 257a969bb06cef93b6b0dadbb784c30d33856445d1Jan Engelhardtstatic const struct xt_option_entry hbh_opts[] = { 267a969bb06cef93b6b0dadbb784c30d33856445d1Jan Engelhardt {.name = "hbh-len", .id = O_HBH_LEN, .type = XTTYPE_UINT32, 277a969bb06cef93b6b0dadbb784c30d33856445d1Jan Engelhardt .flags = XTOPT_INVERT | XTOPT_PUT, 287a969bb06cef93b6b0dadbb784c30d33856445d1Jan Engelhardt XTOPT_POINTER(struct ip6t_opts, hdrlen)}, 297a969bb06cef93b6b0dadbb784c30d33856445d1Jan Engelhardt {.name = "hbh-opts", .id = O_HBH_OPTS, .type = XTTYPE_STRING}, 307a969bb06cef93b6b0dadbb784c30d33856445d1Jan Engelhardt XTOPT_TABLEEND, 312ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó}; 322ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó 337ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtstatic uint32_t 342ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabóparse_opts_num(const char *idstr, const char *typestr) 352ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó{ 362ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó unsigned long int id; 372ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó char* ep; 382ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó 392ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó id = strtoul(idstr,&ep,0) ; 402ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó 412ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó if ( idstr == ep ) { 421829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, 43e2f588ab7481760f069cd30d3146569f074721aaJan Engelhardt "hbh: no valid digits in %s `%s'", typestr, idstr); 442ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó } 452ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó if ( id == ULONG_MAX && errno == ERANGE ) { 461829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, 472ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó "%s `%s' specified too big: would overflow", 482ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó typestr, idstr); 492ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó } 502ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó if ( *idstr != '\0' && *ep != '\0' ) { 511829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, 52e2f588ab7481760f069cd30d3146569f074721aaJan Engelhardt "hbh: error parsing %s `%s'", typestr, idstr); 532ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó } 54213e185afbb298e6708881e4c2adffdc47a8b6daJan Engelhardt return id; 552ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó} 562ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó 572ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabóstatic int 587ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtparse_options(const char *optsstr, uint16_t *opts) 592ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó{ 602ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó char *buffer, *cp, *next, *range; 612ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó unsigned int i; 622ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó 632ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó buffer = strdup(optsstr); 641829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt if (!buffer) xtables_error(OTHER_PROBLEM, "strdup failed"); 652ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó 662ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó for (cp=buffer, i=0; cp && i<IP6T_OPTS_OPTSNR; cp=next,i++) 672ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó { 682ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó next=strchr(cp, ','); 692ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó if (next) *next++='\0'; 702ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó range = strchr(cp, ':'); 712ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó if (range) { 722ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó if (i == IP6T_OPTS_OPTSNR-1) 731829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, 742ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó "too many ports specified"); 752ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó *range++ = '\0'; 762ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó } 77213e185afbb298e6708881e4c2adffdc47a8b6daJan Engelhardt opts[i] = (parse_opts_num(cp, "opt") & 0xFF) << 8; 782ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó if (range) { 792ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó if (opts[i] == 0) 801829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt xtables_error(PARAMETER_PROBLEM, "PAD0 has not got length"); 81213e185afbb298e6708881e4c2adffdc47a8b6daJan Engelhardt opts[i] |= parse_opts_num(range, "length") & 0xFF; 822ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó } else { 832ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó opts[i] |= (0x00FF); 842ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó } 852ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó 862ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó#if DEBUG 872ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó printf("opts str: %s %s\n", cp, range); 882ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó printf("opts opt: %04X\n", opts[i]); 892ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó#endif 902ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó } 911829ed482efbc8b390cc760d012b3a4450494e1aJan Engelhardt if (cp) xtables_error(PARAMETER_PROBLEM, "too many addresses specified"); 922ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó 932ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó free(buffer); 942ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó 952ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó#if DEBUG 962ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó printf("addr nr: %d\n", i); 972ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó#endif 982ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó 992ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó return i; 1002ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó} 1012ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó 1027a969bb06cef93b6b0dadbb784c30d33856445d1Jan Engelhardtstatic void hbh_parse(struct xt_option_call *cb) 1032ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó{ 1047a969bb06cef93b6b0dadbb784c30d33856445d1Jan Engelhardt struct ip6t_opts *optinfo = cb->data; 1057a969bb06cef93b6b0dadbb784c30d33856445d1Jan Engelhardt 1067a969bb06cef93b6b0dadbb784c30d33856445d1Jan Engelhardt xtables_option_parse(cb); 1077a969bb06cef93b6b0dadbb784c30d33856445d1Jan Engelhardt switch (cb->entry->id) { 1087a969bb06cef93b6b0dadbb784c30d33856445d1Jan Engelhardt case O_HBH_LEN: 1097a969bb06cef93b6b0dadbb784c30d33856445d1Jan Engelhardt if (cb->invert) 1102ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó optinfo->invflags |= IP6T_OPTS_INV_LEN; 111975aeec7d34419fece8710997b6ec88cc0abb580Jan Engelhardt optinfo->flags |= IP6T_OPTS_LEN; 1122ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó break; 1137a969bb06cef93b6b0dadbb784c30d33856445d1Jan Engelhardt case O_HBH_OPTS: 1147a969bb06cef93b6b0dadbb784c30d33856445d1Jan Engelhardt optinfo->optsnr = parse_options(cb->arg, optinfo->opts); 1152ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó optinfo->flags |= IP6T_OPTS_OPTS; 1162ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó break; 1172ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó } 1182ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó} 1192ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó 1202ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabóstatic void 1217ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardtprint_options(unsigned int optsnr, uint16_t *optsp) 1222ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó{ 1232ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó unsigned int i; 1242ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó 1252ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó for(i=0; i<optsnr; i++){ 12673866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf("%c", (i==0)?' ':','); 1272ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó printf("%d", (optsp[i] & 0xFF00)>>8); 1282ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó if ((optsp[i] & 0x00FF) != 0x00FF){ 1292ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó printf(":%d", (optsp[i] & 0x00FF)); 1302ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó } 1312ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó } 1322ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó} 1332ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó 134997045f536026c0d643bf884da5ff5de2605197fJan Engelhardtstatic void hbh_print(const void *ip, const struct xt_entry_match *match, 135997045f536026c0d643bf884da5ff5de2605197fJan Engelhardt int numeric) 1362ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó{ 1372ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó const struct ip6t_opts *optinfo = (struct ip6t_opts *)match->data; 1382ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó 13973866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" hbh"); 1402ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó if (optinfo->flags & IP6T_OPTS_LEN) { 14173866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" length"); 1422ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó printf(":%s", optinfo->invflags & IP6T_OPTS_INV_LEN ? "!" : ""); 1432ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó printf("%u", optinfo->hdrlen); 1442ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó } 14573866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt if (optinfo->flags & IP6T_OPTS_OPTS) printf(" opts"); 1467ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardt print_options(optinfo->optsnr, (uint16_t *)optinfo->opts); 1472ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó if (optinfo->invflags & ~IP6T_OPTS_INV_MASK) 14873866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" Unknown invflags: 0x%X", 1492ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó optinfo->invflags & ~IP6T_OPTS_INV_MASK); 1502ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó} 1512ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó 152997045f536026c0d643bf884da5ff5de2605197fJan Engelhardtstatic void hbh_save(const void *ip, const struct xt_entry_match *match) 1532ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó{ 1542ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó const struct ip6t_opts *optinfo = (struct ip6t_opts *)match->data; 1552ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó 1562ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó if (optinfo->flags & IP6T_OPTS_LEN) { 15773866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf("%s --hbh-len %u", 15873866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt (optinfo->invflags & IP6T_OPTS_INV_LEN) ? " !" : "", 1592ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó optinfo->hdrlen); 1602ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó } 1612ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó 162e2f588ab7481760f069cd30d3146569f074721aaJan Engelhardt if (optinfo->flags & IP6T_OPTS_OPTS) 16373866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt printf(" --hbh-opts"); 1647ac405297ec38449b30e3b05fd6bf2082fd3d803Jan Engelhardt print_options(optinfo->optsnr, (uint16_t *)optinfo->opts); 1652ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó} 1662ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó 1678b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardtstatic struct xtables_match hbh_mt6_reg = { 16802aa73312d6078b6de26757d5a558e0085ec20b5Harald Welte .name = "hbh", 1698b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt .version = XTABLES_VERSION, 17003d99486d8283552705b58dc55b6085dffc38792Jan Engelhardt .family = NFPROTO_IPV6, 1718b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt .size = XT_ALIGN(sizeof(struct ip6t_opts)), 1728b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt .userspacesize = XT_ALIGN(sizeof(struct ip6t_opts)), 173997045f536026c0d643bf884da5ff5de2605197fJan Engelhardt .help = hbh_help, 174997045f536026c0d643bf884da5ff5de2605197fJan Engelhardt .print = hbh_print, 175997045f536026c0d643bf884da5ff5de2605197fJan Engelhardt .save = hbh_save, 1767a969bb06cef93b6b0dadbb784c30d33856445d1Jan Engelhardt .x6_parse = hbh_parse, 1777a969bb06cef93b6b0dadbb784c30d33856445d1Jan Engelhardt .x6_options = hbh_opts, 1782ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó}; 1792ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó 1802ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabóvoid 1812ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó_init(void) 1822ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó{ 1838b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt xtables_register_match(&hbh_mt6_reg); 1842ea56498b07506c00a511ddee39cb1c4bd85457dAndrás Kis-Szabó} 185