libxt_physdev.c revision 03d99486d8283552705b58dc55b6085dffc38792
11254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer/* Shared library add-on to iptables to add bridge port matching support. */ 21254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer#include <stdio.h> 31254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer#include <string.h> 41254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer#include <stdlib.h> 51254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer#include <getopt.h> 61254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer#include <ctype.h> 7fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI#include <xtables.h> 8fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI#include <linux/netfilter/xt_physdev.h> 91254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer#if defined(__GLIBC__) && __GLIBC__ == 2 101254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer#include <net/ethernet.h> 111254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer#else 121254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer#include <linux/if_ether.h> 131254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer#endif 141254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer 15181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void physdev_help(void) 161254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer{ 171254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer printf( 188b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt"physdev match options:\n" 19967279231a9ecfa99f26694a954afc535c63db1dJan Engelhardt" [!] --physdev-in inputname[+] bridge port name ([+] for wildcard)\n" 20967279231a9ecfa99f26694a954afc535c63db1dJan Engelhardt" [!] --physdev-out outputname[+] bridge port name ([+] for wildcard)\n" 2130596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer" [!] --physdev-is-in arrived on a bridge device\n" 2230596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer" [!] --physdev-is-out will leave on a bridge device\n" 238b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt" [!] --physdev-is-bridged it's a bridged packet\n"); 241254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer} 251254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer 26181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic const struct option physdev_opts[] = { 27500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy { "physdev-in", 1, NULL, '1' }, 28500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy { "physdev-out", 1, NULL, '2' }, 29500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy { "physdev-is-in", 0, NULL, '3' }, 30500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy { "physdev-is-out", 0, NULL, '4' }, 31500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy { "physdev-is-bridged", 0, NULL, '5' }, 329ee386a1b6d7704b259460152c959ab0e79e02aaMax Kellermann { .name = NULL } 331254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer}; 341254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer 351254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymerstatic int 36181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtphysdev_parse(int c, char **argv, int invert, unsigned int *flags, 37181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt const void *entry, struct xt_entry_match **match) 381254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer{ 39fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI struct xt_physdev_info *info = 40fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI (struct xt_physdev_info*)(*match)->data; 411254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer 421254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer switch (c) { 431254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer case '1': 44fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI if (*flags & XT_PHYSDEV_OP_IN) 4530596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer goto multiple_use; 461254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer check_inverse(optarg, &invert, &optind, 0); 47efa8fc2123a2a9fc229ab471edd2b2688ce1da3aHarald Welte parse_interface(argv[optind-1], info->physindev, 48efa8fc2123a2a9fc229ab471edd2b2688ce1da3aHarald Welte (unsigned char *)info->in_mask); 491254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer if (invert) 50fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI info->invert |= XT_PHYSDEV_OP_IN; 51fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI info->bitmask |= XT_PHYSDEV_OP_IN; 52fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI *flags |= XT_PHYSDEV_OP_IN; 531254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer break; 541254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer 551254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer case '2': 56fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI if (*flags & XT_PHYSDEV_OP_OUT) 5730596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer goto multiple_use; 581254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer check_inverse(optarg, &invert, &optind, 0); 591254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer parse_interface(argv[optind-1], info->physoutdev, 60efa8fc2123a2a9fc229ab471edd2b2688ce1da3aHarald Welte (unsigned char *)info->out_mask); 611254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer if (invert) 62fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI info->invert |= XT_PHYSDEV_OP_OUT; 63fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI info->bitmask |= XT_PHYSDEV_OP_OUT; 64fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI *flags |= XT_PHYSDEV_OP_OUT; 6530596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer break; 6630596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer 6730596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer case '3': 68fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI if (*flags & XT_PHYSDEV_OP_ISIN) 6930596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer goto multiple_use; 7030596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer check_inverse(optarg, &invert, &optind, 0); 71fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI info->bitmask |= XT_PHYSDEV_OP_ISIN; 7230596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer if (invert) 73fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI info->invert |= XT_PHYSDEV_OP_ISIN; 74fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI *flags |= XT_PHYSDEV_OP_ISIN; 7530596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer break; 7630596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer 7730596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer case '4': 78fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI if (*flags & XT_PHYSDEV_OP_ISOUT) 7930596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer goto multiple_use; 8030596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer check_inverse(optarg, &invert, &optind, 0); 81fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI info->bitmask |= XT_PHYSDEV_OP_ISOUT; 8230596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer if (invert) 83fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI info->invert |= XT_PHYSDEV_OP_ISOUT; 84fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI *flags |= XT_PHYSDEV_OP_ISOUT; 8530596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer break; 8630596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer 8730596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer case '5': 88fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI if (*flags & XT_PHYSDEV_OP_BRIDGED) 8930596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer goto multiple_use; 9030596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer check_inverse(optarg, &invert, &optind, 0); 9130596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer if (invert) 92fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI info->invert |= XT_PHYSDEV_OP_BRIDGED; 93fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI *flags |= XT_PHYSDEV_OP_BRIDGED; 94fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI info->bitmask |= XT_PHYSDEV_OP_BRIDGED; 951254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer break; 961254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer 971254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer default: 981254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer return 0; 991254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer } 1001254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer 1011254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer return 1; 10230596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymermultiple_use: 10330596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer exit_error(PARAMETER_PROBLEM, 10430596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer "multiple use of the same physdev option is not allowed"); 1051254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer 1061254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer} 1071254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer 108181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void physdev_check(unsigned int flags) 1091254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer{ 11030596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer if (flags == 0) 11130596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer exit_error(PARAMETER_PROBLEM, "PHYSDEV: no physdev option specified"); 1121254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer} 1131254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer 1141254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymerstatic void 115181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtphysdev_print(const void *ip, const struct xt_entry_match *match, int numeric) 1161254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer{ 117fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI struct xt_physdev_info *info = 118fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI (struct xt_physdev_info*)match->data; 1191254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer 1201254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer printf("PHYSDEV match"); 121fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI if (info->bitmask & XT_PHYSDEV_OP_ISIN) 12230596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer printf("%s --physdev-is-in", 123fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI info->invert & XT_PHYSDEV_OP_ISIN ? " !":""); 124fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI if (info->bitmask & XT_PHYSDEV_OP_IN) 12530596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer printf("%s --physdev-in %s", 126fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI (info->invert & XT_PHYSDEV_OP_IN) ? " !":"", info->physindev); 12730596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer 128fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI if (info->bitmask & XT_PHYSDEV_OP_ISOUT) 12930596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer printf("%s --physdev-is-out", 130fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI info->invert & XT_PHYSDEV_OP_ISOUT ? " !":""); 131fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI if (info->bitmask & XT_PHYSDEV_OP_OUT) 13230596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer printf("%s --physdev-out %s", 133fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI (info->invert & XT_PHYSDEV_OP_OUT) ? " !":"", info->physoutdev); 134fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI if (info->bitmask & XT_PHYSDEV_OP_BRIDGED) 13530596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer printf("%s --physdev-is-bridged", 136fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI info->invert & XT_PHYSDEV_OP_BRIDGED ? " !":""); 1371254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer printf(" "); 1381254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer} 1391254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer 140181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic void physdev_save(const void *ip, const struct xt_entry_match *match) 1411254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer{ 142fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI struct xt_physdev_info *info = 143fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI (struct xt_physdev_info*)match->data; 1441254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer 145fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI if (info->bitmask & XT_PHYSDEV_OP_ISIN) 146d38eaf488dcd9c78d1ea7c1b9613d210688114afJan Engelhardt printf("%s--physdev-is-in ", 147d38eaf488dcd9c78d1ea7c1b9613d210688114afJan Engelhardt (info->invert & XT_PHYSDEV_OP_ISIN) ? "! " : ""); 148fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI if (info->bitmask & XT_PHYSDEV_OP_IN) 149d38eaf488dcd9c78d1ea7c1b9613d210688114afJan Engelhardt printf("%s--physdev-in %s ", 150d38eaf488dcd9c78d1ea7c1b9613d210688114afJan Engelhardt (info->invert & XT_PHYSDEV_OP_IN) ? "! " : "", 151d38eaf488dcd9c78d1ea7c1b9613d210688114afJan Engelhardt info->physindev); 15230596a5e7ae8c518a8a0bbf3aa891728e9f9ec1bBart De Schuymer 153fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI if (info->bitmask & XT_PHYSDEV_OP_ISOUT) 154d38eaf488dcd9c78d1ea7c1b9613d210688114afJan Engelhardt printf("%s--physdev-is-out ", 155d38eaf488dcd9c78d1ea7c1b9613d210688114afJan Engelhardt (info->invert & XT_PHYSDEV_OP_ISOUT) ? "! " : ""); 156fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI if (info->bitmask & XT_PHYSDEV_OP_OUT) 157d38eaf488dcd9c78d1ea7c1b9613d210688114afJan Engelhardt printf("%s--physdev-out %s ", 158d38eaf488dcd9c78d1ea7c1b9613d210688114afJan Engelhardt (info->invert & XT_PHYSDEV_OP_OUT) ? "! " : "", 159d38eaf488dcd9c78d1ea7c1b9613d210688114afJan Engelhardt info->physoutdev); 160fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI if (info->bitmask & XT_PHYSDEV_OP_BRIDGED) 161d38eaf488dcd9c78d1ea7c1b9613d210688114afJan Engelhardt printf("%s--physdev-is-bridged ", 162d38eaf488dcd9c78d1ea7c1b9613d210688114afJan Engelhardt (info->invert & XT_PHYSDEV_OP_BRIDGED) ? "! " : ""); 1631254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer} 1641254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer 165181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic struct xtables_match physdev_match = { 16603d99486d8283552705b58dc55b6085dffc38792Jan Engelhardt .family = NFPROTO_IPV4, 1678caee8b9e34fed4562fcff553197c161fc9d9979Pablo Neira .name = "physdev", 1688b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt .version = XTABLES_VERSION, 169fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI .size = XT_ALIGN(sizeof(struct xt_physdev_info)), 170fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI .userspacesize = XT_ALIGN(sizeof(struct xt_physdev_info)), 171181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .help = physdev_help, 172181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .parse = physdev_parse, 173181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .final_check = physdev_check, 174181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .print = physdev_print, 175181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .save = physdev_save, 176181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .extra_opts = physdev_opts, 177fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI}; 178fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI 179181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardtstatic struct xtables_match physdev_match6 = { 18003d99486d8283552705b58dc55b6085dffc38792Jan Engelhardt .family = NFPROTO_IPV6, 181fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI .name = "physdev", 1828b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt .version = XTABLES_VERSION, 183fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI .size = XT_ALIGN(sizeof(struct xt_physdev_info)), 184fec77fed67feb55aba4c33ae2367178c57ce83deYasuyuki KOZAKAI .userspacesize = XT_ALIGN(sizeof(struct xt_physdev_info)), 185181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .help = physdev_help, 186181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .parse = physdev_parse, 187181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .final_check = physdev_check, 188181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .print = physdev_print, 189181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .save = physdev_save, 190181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt .extra_opts = physdev_opts, 1911254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer}; 1921254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer 1931254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymervoid _init(void) 1941254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer{ 195181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt xtables_register_match(&physdev_match); 196181dead3f13befe02769ef479bcbb51801b7fc4eJan Engelhardt xtables_register_match(&physdev_match6); 1971254871c88483cc1a0adc448a83cab6a9d4510a1Bart De Schuymer} 198