/* validates a port option (must be positive) */ int conf_validate_port(cfg_t *cfg, cfg_opt_t *opt) { int value = cfg_opt_getnint(opt, 0); if(value <= 0) { cfg_error(cfg, "invalid port %d in section '%s'", value, cfg_name(cfg)); return -1; } return 0; }
/** * Check if the given opt value is non-negative */ static gint cf_validate_num(cfg_t *cfg, cfg_opt_t *opt) { gint value = cfg_opt_getnint(opt, 0); if (value < 0) { cfg_error(cfg, "'%s' in section '%s' must be a non-negative value", cfg_opt_name(opt), cfg_name(cfg)); return -1; } return 0; }
static gint cf_validate_num_zero(cfg_t *cfg, cfg_opt_t *opt) { gint value = cfg_opt_getnint(opt, 0); if (value < 0) { cfg_error(cfg, "'%s' in section '%s' cannot be a negative " "value.", cfg_opt_name(opt), cfg_name(cfg)); return -1; } return 0; }
int main(int argc, char *argv[]) { struct stat sb; // To check if config file exist. struct in_addr iaddrf, iaddrl; // To validate IP addresses struct in6_addr i6addrf; // also cfg_t *cfg, *cfg_ipv4, *cfg_ipv6; const char *sect_name; char *addr_first, *addr_last; unsigned char addr_maskbits; int port_first, port_last; char which[sizeof("ABC")]; struct config_struct cs; struct nl_sock *nls; int ret; if (argc != 2) { printf("Usage: %s <config-file>\n", argv[0]); exit(EXIT_FAILURE); } if ( stat(argv[1], &sb) == -1 ) { printf("Error: Can not open configuration file: %s\n", argv[1]); exit(EXIT_FAILURE); } cfg_opt_t ipv4_opts[] = { CFG_STR("ipv4_addr_net", IPV4_DEF_NET, CFGF_NONE), CFG_INT("ipv4_addr_net_mask_bits", IPV4_DEF_MASKBITS, CFGF_NONE), CFG_STR("ipv4_pool_range_first", IPV4_DEF_POOL_FIRST, CFGF_NONE), CFG_STR("ipv4_pool_range_last", IPV4_DEF_POOL_LAST, CFGF_NONE), CFG_INT("ipv4_tcp_port_range_first", IPV4_DEF_TCP_POOL_FIRST, CFGF_NONE), CFG_INT("ipv4_tcp_port_range_last", IPV4_DEF_TCP_POOL_LAST, CFGF_NONE), CFG_INT("ipv4_udp_port_range_first", IPV4_DEF_UDP_POOL_FIRST, CFGF_NONE), CFG_INT("ipv4_udp_port_range_last", IPV4_DEF_UDP_POOL_LAST, CFGF_NONE), CFG_END() }; cfg_opt_t ipv6_opts[] = { CFG_STR("ipv6_net_prefix", IPV6_DEF_PREFIX, CFGF_NONE), CFG_INT("ipv6_net_mask_bits", IPV6_DEF_MASKBITS, CFGF_NONE), CFG_INT("ipv6_tcp_port_range_first", IPV6_DEF_TCP_POOL_FIRST, CFGF_NONE), CFG_INT("ipv6_tcp_port_range_last", IPV6_DEF_TCP_POOL_LAST, CFGF_NONE), CFG_INT("ipv6_udp_port_range_first", IPV6_DEF_UDP_POOL_FIRST, CFGF_NONE), CFG_INT("ipv6_udp_port_range_last", IPV6_DEF_UDP_POOL_LAST, CFGF_NONE), CFG_END() }; cfg_opt_t opts[] = { CFG_SEC("ipv4", ipv4_opts, CFGF_NONE), CFG_SEC("ipv6", ipv6_opts, CFGF_NONE), CFG_END() }; cfg = cfg_init(opts, CFGF_NONE); if(cfg_parse(cfg, argv[1]) == CFG_PARSE_ERROR) { printf("Error parsing configuration file: %s\n", argv[1]); exit_error_conf(cfg); } /* Loading IPv4 configuration */ { cfg_ipv4 = cfg_getsec(cfg, "ipv4"); sect_name = cfg_name(cfg_ipv4); printf ("Section: %s\n", sect_name); addr_first = cfg_getstr(cfg_ipv4, "ipv4_addr_net"); if ( inet_aton(addr_first, &iaddrf) == 0 ) // Validate ipv4 addr { printf("Error: Invalid IPv4 address net: %s\n", addr_first); exit_error_conf(cfg); } addr_maskbits = cfg_getint(cfg_ipv4, "ipv4_addr_net_mask_bits"); if (addr_maskbits > 32 || addr_maskbits < 0) { printf("Error: Bad IPv4 network mask bits value: %d\n", addr_maskbits); exit_error_conf(cfg); } cs.ipv4_addr_net = iaddrf; cs.ipv4_addr_net_mask_bits = addr_maskbits; printf("\tPool Network: %s/%d\n", addr_first, addr_maskbits); // addr_first = cfg_getstr(cfg_ipv4, "ipv4_pool_range_first"); addr_last = cfg_getstr(cfg_ipv4, "ipv4_pool_range_last"); if ( inet_aton(addr_first, &iaddrf) == 0 ) // Validate ipv4 addr { printf("Error: Malformed ipv4_pool_range_first: %s\n", addr_first); exit_error_conf(cfg); } if ( inet_aton(addr_last, &iaddrl) == 0 ) // Validate ipv4 addr { printf("Error: Malformed ipv4_pool_range_last: %s\n", addr_last); exit_error_conf(cfg); } if (iaddrf.s_addr > iaddrl.s_addr) // Validate that: first < last { printf("Error: First pool address is greater than last pool address.\n"); exit_error_conf(cfg); } cs.ipv4_pool_range_first = iaddrf; cs.ipv4_pool_range_last = iaddrl; printf("\t\t- First address: %s\n", inet_ntoa(iaddrf)); printf("\t\t- Last address: %s\n", inet_ntoa(iaddrl)); // port_first = cfg_getint(cfg_ipv4, "ipv4_tcp_port_range_first"); port_last = cfg_getint(cfg_ipv4, "ipv4_tcp_port_range_last"); sprintf(which, "TCP"); if (port_first < 0 || port_first > 65535) { printf("Error: Invalid first %s port: %d\n", which, port_first); exit_error_conf(cfg); } if (port_last < 0 || port_last > 65535) { printf("Error: Invalid last %s port: %d\n", which, port_last); exit_error_conf(cfg); } if (port_first > port_last) { printf("Error: First %s port is greater than last port.\n", which); exit_error_conf(cfg); } cs.ipv4_tcp_port_first = port_first; cs.ipv4_tcp_port_last = port_last; printf("\t%s pool port range: %d-%d\n", which, port_first, port_last); // port_first = cfg_getint(cfg_ipv4, "ipv4_udp_port_range_first"); port_last = cfg_getint(cfg_ipv4, "ipv4_udp_port_range_last"); sprintf(which, "UDP"); if (port_first < 0 || port_first > 65535) { printf("Error: Invalid first %s port: %d\n", which, port_first); exit_error_conf(cfg); } if (port_last < 0 || port_last > 65535) { printf("Error: Invalid last %s port: %d\n", which, port_last); exit_error_conf(cfg); } if (port_first > port_last) { printf("Error: First %s port is greater than last port.\n", which); exit_error_conf(cfg); } cs.ipv4_udp_port_first = port_first; cs.ipv4_udp_port_last = port_last; printf("\t%s pool port range: %d-%d\n", which, port_first, port_last); printf ("\n" ); } /* Loading IPv6 configuration */ { cfg_ipv6 = cfg_getsec(cfg, "ipv6"); sect_name = cfg_name(cfg_ipv6); printf ("Section: %s\n", sect_name ); addr_first = cfg_getstr(cfg_ipv6, "ipv6_net_prefix"); if ( inet_pton(AF_INET6, addr_first, &i6addrf) < 1 ) // Validate ipv6 addr { printf("Error: Invalid IPv6 address net: %s\n", addr_first); exit_error_conf(cfg); } addr_maskbits = cfg_getint(cfg_ipv6, "ipv6_net_mask_bits"); if (addr_maskbits > 128 || addr_maskbits < 0) { printf("Error: Bad IPv6 network mask bits value: %d\n", addr_maskbits); exit_error_conf(cfg); } cs.ipv6_net_prefix = i6addrf; cs.ipv6_net_mask_bits = addr_maskbits; printf("\tPrefix: %s/%d\n", addr_first, addr_maskbits); // port_first = cfg_getint(cfg_ipv6, "ipv6_tcp_port_range_first"); port_last = cfg_getint(cfg_ipv6, "ipv6_tcp_port_range_last"); sprintf(which, "TCP"); if (port_first < 0 || port_first > 65535) { printf("Error: Invalid first %s port: %d\n", which, port_first); exit_error_conf(cfg); } if (port_last < 0 || port_last > 65535) { printf("Error: Invalid last %s port: %d\n", which, port_last); exit_error_conf(cfg); } if (port_first > port_last) { printf("Error: First %s port is greater than last port.\n", which); exit_error_conf(cfg); } cs.ipv6_tcp_port_range_first = port_first; cs.ipv6_tcp_port_range_last = port_last; printf("\t%s pool port range: %d-%d\n", which, port_first, port_last); // port_first = cfg_getint(cfg_ipv6, "ipv6_udp_port_range_first"); port_last = cfg_getint(cfg_ipv6, "ipv6_udp_port_range_last"); sprintf(which, "UDP"); if (port_first < 0 || port_first > 65535) { printf("Error: Invalid first %s port: %d\n", which, port_first); exit_error_conf(cfg); } if (port_last < 0 || port_last > 65535) { printf("Error: Invalid last %s port: %d\n", which, port_last); exit_error_conf(cfg); } if (port_first > port_last) { printf("Error: First %s port is greater than last port.\n", which); exit_error_conf(cfg); } cs.ipv6_udp_port_range_first = port_first; cs.ipv6_udp_port_range_last = port_last; printf("\t%s pool port range: %d-%d\n", which, port_first, port_last); printf ("\n" ); } cfg_free(cfg); /* We got the configuration structure, now send it to the module * using netlink sockets. */ // Reserve memory for netlink socket nls = nl_socket_alloc(); if (!nls) { printf("bad nl_socket_alloc\n"); return EXIT_FAILURE; } // Bind and connect the socket to a protocol ret = nl_connect(nls, NETLINK_USERSOCK); if (ret < 0) { nl_perror(ret, "nl_connect"); nl_socket_free(nls); return EXIT_FAILURE; } ret = nl_send_simple(nls, MY_MSG_TYPE, 0, &(cs), sizeof(cs)); if (ret < 0) { nl_perror(ret, "nl_send_simple"); printf("Error sending message, is module loaded?\n"); nl_close(nls); nl_socket_free(nls); return EXIT_FAILURE; } else { printf("Message sent (%d bytes):\n", ret); //print_nat64_run_conf(nrc); } nl_close(nls); nl_socket_free(nls); exit(EXIT_SUCCESS); }
/** * Main function of the user app that parses configuration file and sends it to * NAT64 kernel module. * * @param argc Qty of arguments in command line call. * @param argv Array of arguments in command line call. */ int main(int argc, char *argv[]) { struct stat sb; // To check if config file exist. struct in_addr iaddrn, iaddrf, iaddrl; // To validate IP addresses struct in6_addr i6addrf; // also cfg_t *cfg, *cfg_ipv4, *cfg_ipv6; const char *sect_name; char *addr_first, *addr_last; unsigned char addr_maskbits; int port_first, port_last; char which[sizeof("ABC")]; char str[INET_ADDRSTRLEN]; struct config_struct cs; struct nl_sock *nls; int ret; int i = 0; struct ipv6_prefixes **ipv6_pref = NULL; unsigned char ipv6_pref_qty; char ipv6_def_prefix64[sizeof("1111:2222:3333:4444:5555:6666::/128")]; char *ipv6_buf; char *ipv6_check_addr; char *ipv6_check_maskbits; if (argc != 2) { printf("Usage: %s <config-file>\n", argv[0]); exit(EXIT_FAILURE); } if ( stat(argv[1], &sb) == -1 ) { printf("Error: Can not open configuration file: %s\n", argv[1]); exit(EXIT_FAILURE); } // Load default configuration values for each config option, just in case // they were not included in the config file. cfg_opt_t ipv4_opts[] = { CFG_STR("ipv4_addr_net", IPV4_DEF_NET, CFGF_NONE), CFG_INT("ipv4_addr_net_mask_bits", IPV4_DEF_MASKBITS, CFGF_NONE), CFG_STR("ipv4_pool_range_first", IPV4_DEF_POOL_FIRST, CFGF_NONE), CFG_STR("ipv4_pool_range_last", IPV4_DEF_POOL_LAST, CFGF_NONE), CFG_INT("ipv4_tcp_port_range_first", IPV4_DEF_TCP_PORTS_FIRST, CFGF_NONE), CFG_INT("ipv4_tcp_port_range_last", IPV4_DEF_TCP_PORTS_LAST, CFGF_NONE), CFG_INT("ipv4_udp_port_range_first", IPV4_DEF_UDP_PORTS_FIRST, CFGF_NONE), CFG_INT("ipv4_udp_port_range_last", IPV4_DEF_UDP_PORTS_LAST, CFGF_NONE), CFG_END() }; // Load default configuration values for each config option, just in case // they were not included in the config file. sprintf(ipv6_def_prefix64, "%s/%d", IPV6_DEF_PREFIX, IPV6_DEF_MASKBITS ); cfg_opt_t ipv6_opts[] = { CFG_STR_LIST("ipv6_net_prefixes", ipv6_def_prefix64, CFGF_NONE), CFG_INT("ipv6_tcp_port_range_first", IPV6_DEF_TCP_PORTS_FIRST, CFGF_NONE), CFG_INT("ipv6_tcp_port_range_last", IPV6_DEF_TCP_PORTS_LAST, CFGF_NONE), CFG_INT("ipv6_udp_port_range_first", IPV6_DEF_UDP_PORTS_FIRST, CFGF_NONE), CFG_INT("ipv6_udp_port_range_last", IPV6_DEF_UDP_PORTS_LAST, CFGF_NONE), CFG_END() }; // Define two sections in config file cfg_opt_t opts[] = { CFG_SEC("ipv4", ipv4_opts, CFGF_NONE), CFG_SEC("ipv6", ipv6_opts, CFGF_NONE), CFG_END() }; // Parse config file cfg = cfg_init(opts, CFGF_NONE); if(cfg_parse(cfg, argv[1]) == CFG_PARSE_ERROR) { printf("Error parsing configuration file: %s\n", argv[1]); exit_error_conf(cfg); } /* * Loading IPv4 configuration * */ { cfg_ipv4 = cfg_getsec(cfg, "ipv4"); sect_name = cfg_name(cfg_ipv4); printf ("Section: %s\n", sect_name); // Validate IPv4 pool address addr_first = cfg_getstr(cfg_ipv4, "ipv4_addr_net"); if ( convert_ipv4_addr(addr_first, &iaddrn) == EXIT_FAILURE ) { printf("Error: Invalid IPv4 address net: %s\n", addr_first); exit_error_conf(cfg); } // Validate netmask bits addr_maskbits = cfg_getint(cfg_ipv4, "ipv4_addr_net_mask_bits"); if ( validate_ipv4_netmask_bits(addr_maskbits) == EXIT_FAILURE ) { printf("Error: Bad IPv4 network mask bits value: %d\n", addr_maskbits); exit_error_conf(cfg); } // Store values in config struct cs.ipv4_addr_net = iaddrn; cs.ipv4_addr_net_mask_bits = addr_maskbits; printf("\tPool Network: %s/%d\n", addr_first, addr_maskbits); // Validate pool addresses range addr_first = cfg_getstr(cfg_ipv4, "ipv4_pool_range_first"); addr_last = cfg_getstr(cfg_ipv4, "ipv4_pool_range_last"); if ( convert_ipv4_addr(addr_first, &iaddrf) == EXIT_FAILURE ) // Validate ipv4 addr { printf("Error: Malformed ipv4_pool_range_first: %s\n", addr_first); exit_error_conf(cfg); } if ( convert_ipv4_addr(addr_last, &iaddrl) == EXIT_FAILURE ) // Validate ipv4 addr { printf("Error: Malformed ipv4_pool_range_last: %s\n", addr_last); exit_error_conf(cfg); } if ( validate_ipv4_pool_range(&iaddrn, addr_maskbits, &iaddrf, &iaddrl) == EXIT_FAILURE ) // Validate that: first < last { printf("Error: Pool addresses badly defined.\n"); exit_error_conf(cfg); } // Store values in config struct cs.ipv4_pool_range_first = iaddrf; cs.ipv4_pool_range_last = iaddrl; inet_ntop(AF_INET, &(iaddrf.s_addr), str, INET_ADDRSTRLEN); printf("\t\t- First address: %s\n", str); inet_ntop(AF_INET, &(iaddrl.s_addr), str, INET_ADDRSTRLEN); printf("\t\t- Last address: %s\n", str); // Validate port ranges port_first = cfg_getint(cfg_ipv4, "ipv4_tcp_port_range_first"); port_last = cfg_getint(cfg_ipv4, "ipv4_tcp_port_range_last"); sprintf(which, "TCP"); if ( validate_ports_range(port_first, port_last) == EXIT_FAILURE ) { //~ printf("Error: Invalid first %s port: %d\n", which, port_first); printf("Error: Invalid %s ports range.\n", which); exit_error_conf(cfg); } cs.ipv4_tcp_port_first = port_first; cs.ipv4_tcp_port_last = port_last; printf("\t%s pool port range: %d-%d\n", which, port_first, port_last); // port_first = cfg_getint(cfg_ipv4, "ipv4_udp_port_range_first"); port_last = cfg_getint(cfg_ipv4, "ipv4_udp_port_range_last"); sprintf(which, "UDP"); if ( validate_ports_range(port_first, port_last) == EXIT_FAILURE ) { printf("Error: Invalid %s ports range.\n", which); exit_error_conf(cfg); } cs.ipv4_udp_port_first = port_first; cs.ipv4_udp_port_last = port_last; printf("\t%s pool port range: %d-%d\n", which, port_first, port_last); printf ("\n" ); } /* * Loading IPv6 configuration * */ { cfg_ipv6 = cfg_getsec(cfg, "ipv6"); sect_name = cfg_name(cfg_ipv6); printf ("Section: %s\n", sect_name ); // Get number of IPv6 prefixes. ipv6_pref_qty = cfg_size(cfg_ipv6, "ipv6_net_prefixes"); // Allocate memory for the array of prefixes. ipv6_pref = (struct ipv6_prefixes **) malloc(ipv6_pref_qty * sizeof(struct ipv6_prefixes *)); for(i = 0; i < ipv6_pref_qty; i++) { // Split prefix and netmask bits ipv6_buf = cfg_getnstr(cfg_ipv6, "ipv6_net_prefixes", i); ipv6_check_addr = strtok(ipv6_buf, "/"); ipv6_check_maskbits = strtok(NULL, "/"); // Validate IPv6 addr if ( convert_ipv6_addr(ipv6_check_addr, &i6addrf) == EXIT_FAILURE ) { printf("Error: Invalid IPv6 address net: %s\n", ipv6_check_addr); exit_error_conf(cfg); } // Validate netmask bits addr_maskbits = atoi(ipv6_check_maskbits); if ( validate_ipv6_netmask_bits(addr_maskbits) == EXIT_FAILURE ) { printf("Error: Bad IPv6 network mask bits value: %d\n", addr_maskbits); exit_error_conf(cfg); } // Allocate memory for each IPv6 prefix ipv6_pref[i] = (struct ipv6_prefixes *) malloc(sizeof(struct ipv6_prefixes)); ipv6_pref[i]->addr = (i6addrf); ipv6_pref[i]->maskbits = addr_maskbits; } // Store prefixes in the config struct cs.ipv6_net_prefixes = ipv6_pref; cs.ipv6_net_prefixes_qty = ipv6_pref_qty; // Validate port ranges port_first = cfg_getint(cfg_ipv6, "ipv6_tcp_port_range_first"); port_last = cfg_getint(cfg_ipv6, "ipv6_tcp_port_range_last"); sprintf(which, "TCP"); if ( validate_ports_range(port_first, port_last) == EXIT_FAILURE ) { printf("Error: Invalid %s ports range.\n", which); exit_error_conf(cfg); } cs.ipv6_tcp_port_range_first = port_first; cs.ipv6_tcp_port_range_last = port_last; printf("\t%s pool port range: %d-%d\n", which, port_first, port_last); // port_first = cfg_getint(cfg_ipv6, "ipv6_udp_port_range_first"); port_last = cfg_getint(cfg_ipv6, "ipv6_udp_port_range_last"); sprintf(which, "UDP"); if ( validate_ports_range(port_first, port_last) == EXIT_FAILURE ) { printf("Error: Invalid %s ports range.\n", which); exit_error_conf(cfg); } cs.ipv6_udp_port_range_first = port_first; cs.ipv6_udp_port_range_last = port_last; printf("\t%s pool port range: %d-%d\n", which, port_first, port_last); printf ("\n" ); } cfg_free(cfg); /* We got the configuration structure, now send it to the module * using netlink sockets. */ // Reserve memory for netlink socket nls = nl_socket_alloc(); if (!nls) { printf("bad nl_socket_alloc\n"); return EXIT_FAILURE; } // Bind and connect the socket to kernel ret = nl_connect(nls, NETLINK_USERSOCK); if (ret < 0) { nl_perror(ret, "nl_connect"); nl_socket_free(nls); return EXIT_FAILURE; } // Send socket to module ret = nl_send_simple(nls, MSG_TYPE_CONF, 0, &(cs), sizeof(cs)); if (ret < 0) { nl_perror(ret, "nl_send_simple"); printf("Error sending message, is module loaded?\n"); nl_close(nls); nl_socket_free(nls); return EXIT_FAILURE; } else { printf("Message sent (%d bytes):\n", ret); //print_nat64_run_conf(nrc); } nl_close(nls); nl_socket_free(nls); exit(EXIT_SUCCESS); }
void cfg_dump_inline(cfg_t cfg, write_stream_t stream) { struct cfg_it it; cfg_t child; int c; if(cfg == 0) return; switch(cfg->m_type) { case CPE_CFG_TYPE_SEQUENCE: { stream_putc(stream, '['); c = 0; cfg_it_init(&it, cfg); if ((child = cfg_it_next(&it))) { stream_putc(stream, ' '); cfg_dump_inline(child, stream); ++c; } while((child = cfg_it_next(&it))) { stream_putc(stream, ','); stream_putc(stream, ' '); cfg_dump_inline(child, stream); ++c; } if (c > 0) { stream_putc(stream, ' '); } stream_putc(stream, ']'); break; } case CPE_CFG_TYPE_STRUCT: { stream_putc(stream, '{'); c = 0; cfg_it_init(&it, cfg); if ((child = cfg_it_next(&it))) { stream_printf(stream, " %s=", cfg_name(child)); cfg_dump_inline(child, stream); ++c; } while((child = cfg_it_next(&it))) { stream_printf(stream, ", %s=", cfg_name(child)); cfg_dump_inline(child, stream); ++c; } if (c > 0) { stream_putc(stream, ' '); } stream_putc(stream, '}'); break; } default: dr_ctype_print_to_stream(stream, cfg_data(cfg), cfg->m_type, 0); break; } }