diff --git a/Platform/user/configm/config-server/include/configm.h b/Platform/user/configm/config-server/include/configm.h index 99b645f82..4dbde3aa0 100755 --- a/Platform/user/configm/config-server/include/configm.h +++ b/Platform/user/configm/config-server/include/configm.h @@ -1,228 +1,242 @@ -#ifndef CONFIGM_H_ -#define CONFIGM_H_ - -#include "s2j/s2j.h" -#include "../../../../common/rpc/rpc_common.h" -#include "ipconfig.h" -#include "../../../../../Common/commuapinl.h" -#include "../user_manager_config/user_group_config.h" -#include "../user_manager_config/user_account_config.h" -#include "log_config.h" -#include "authfree.h" -#include "localportal.h" -#include "jumppage.h" -#include "userlock.h" -#include "agingtime.h" -#include "brconfig.h" - -/* 类型定义 */ - -/* IP CONFIG */ -#define NETCONFIG_MODULE 0x00000001 - -/* USER MANAGER CONFIG */ -#define USER_MANAGER_CONFIG_MODULE 0x00000002 - -/*PORTAL SERVER CONFIG */ -#define LOCALAUTH_CONFIG_MODULE 0x00000003 - -#define LOG_CONFIG_MODULE 0x00000004 - - - -/* config id define*/ -#define IPCONFIG_V4 (uint64)((uint64)NETCONFIG_MODULE<<32|1) -#define BR_CONFIG (uint64)((uint64)NETCONFIG_MODULE<<32|2) -#define BRIF_CONFIG (uint64)((uint64)NETCONFIG_MODULE<<32|3) -#define BRFDB_CONFIG (uint64)((uint64)NETCONFIG_MODULE<<32|4) - - -#define USER_MANAGER_CONFIG_GROUP (uint64)((uint64)USER_MANAGER_CONFIG_MODULE<<32|1) -#define USER_MANAGER_CONFIG_USER (uint64)((uint64)USER_MANAGER_CONFIG_MODULE<<32|2) - -#define PORTALSERVER_CONFIG (uint64)((uint64)LOCALAUTH_CONFIG_MODULE<<32|1) -#define AUTHFREE_CONFIG (uint64)((uint64)LOCALAUTH_CONFIG_MODULE<<32|2) -#define USERLOCK_CONFIG (uint64)((uint64)LOCALAUTH_CONFIG_MODULE<<32|3) -#define JUMPPAGE_CONFIG (uint64)((uint64)LOCALAUTH_CONFIG_MODULE<<32|4) -#define AGINGTIME_CONFIG (uint64)((uint64)LOCALAUTH_CONFIG_MODULE<<32|5) - -#define LOG_CONFIG_CONSOLE (uint64)((uint64)LOG_CONFIG_MODULE<<32|1) - -#define CONFIG_INIT_ARRAY \ -{\ - { \ - NETCONFIG_MODULE, \ - br_bridge_init \ - }, \ - { \ - LOG_CONFIG_MODULE, \ - log_config_init \ - } \ -} - -/* - 1、配置ID,全局唯一,用于寻找对应的配置业务 - 2、配置源检查,全局唯一,用于寻找对应的配置业务, - 从低位到高位,第一位表示WEB,后续配置扩展 - 3、是否配置恢复 - 4、是否是多实例 - 5、配置校验回调函数 - 6、配置处理接口 - 7、配置获取接口 - 8、配置全部获取接口 -*/ -#define CONFIG_SERVICE_ARRAY \ -{ \ - {\ - IPCONFIG_V4, \ - CONFIG_FROM_WEB|CONFIG_FROM_NETOPEER, \ - FALSE, \ - ip_config_chk, \ - ip_config_proc, \ - ip_config_get, \ - ip_config_get_all \ - },\ - {\ - BR_CONFIG, \ - CONFIG_FROM_WEB|CONFIG_FROM_NETOPEER, \ - FALSE, \ - br_config_chk, \ - br_config_proc, \ - NULL, \ - NULL \ - },\ - {\ - BRIF_CONFIG, \ - CONFIG_FROM_WEB|CONFIG_FROM_NETOPEER, \ - FALSE, \ - br_if_config_chk, \ - br_if_config_proc, \ - br_if_config_get, \ - br_if_config_get_all \ - },\ - {\ - BRFDB_CONFIG, \ - CONFIG_FROM_WEB|CONFIG_FROM_NETOPEER, \ - FALSE, \ - br_fdb_config_chk, \ - NULL, \ - br_fdb_config_get, \ - NULL \ - },\ - {\ - USER_MANAGER_CONFIG_GROUP, \ - CONFIG_FROM_WEB, \ - FALSE, \ - usergroup_config_chk, \ - usergroup_config_proc, \ - usergroup_config_get, \ - usergroup_config_get_all \ - },\ - {\ - PORTALSERVER_CONFIG, \ - CONFIG_FROM_WEB|CONFIG_FROM_NETOPEER, \ - FALSE, \ - portalserver_config_chk, \ - portalserver_config_proc, \ - NULL, \ - NULL \ - }, \ - { \ - AUTHFREE_CONFIG, \ - CONFIG_FROM_WEB|CONFIG_FROM_NETOPEER, \ - FALSE, \ - freeauth_config_chk, \ - freeauth_config_proc, \ - NULL, \ - NULL \ - },\ - {\ - USERLOCK_CONFIG, \ - CONFIG_FROM_WEB|CONFIG_FROM_NETOPEER, \ - FALSE, \ - userlock_config_chk, \ - userlock_config_proc, \ - NULL, \ - NULL \ - },\ - {\ - JUMPPAGE_CONFIG, \ - CONFIG_FROM_WEB|CONFIG_FROM_NETOPEER, \ - FALSE, \ - NULL, \ - jumppage_config_proc, \ - NULL, \ - NULL \ - }, \ - {\ - AGINGTIME_CONFIG, \ - CONFIG_FROM_WEB|CONFIG_FROM_NETOPEER, \ - FALSE, \ - agingtime_config_chk, \ - agingtime_config_proc, \ - agingtime_config_get, \ - agingtime_config_get_all \ - }, \ - {\ - USER_MANAGER_CONFIG_USER, \ - CONFIG_FROM_WEB, \ - FALSE, \ - user_config_chk, \ - user_config_proc, \ - user_config_get, \ - user_config_get_all \ - },\ - {\ - LOG_CONFIG_CONSOLE, \ - CONFIG_FROM_WEB, \ - FALSE, \ - log_console_config_chk, \ - log_console_config_proc, \ - NULL, \ - NULL \ - }\ -} - -typedef ret_code (*cm_config_init)(); - -typedef ret_code (*cm_config_chk)(uint source, uint *config_type, - pointer input, int *input_len, - pointer output, int *output_len); - -typedef ret_code (*cm_config_proc)(uint source, uint config_type, - pointer input, int input_len, - pointer output, int *output_len); - -typedef ret_code (*cm_config_get)(uint source, - pointer input, int input_len, - pointer output, int *output_len); - -typedef ret_code (*cm_config_get_all)(uint source, - pointer output, int *output_len); - -/* 配置注册 */ -struct _config_init { - uint config_mudlue; - cm_config_init init_callback; -}; -typedef struct _config_init config_init_t; - - -/* 配置注册 */ -struct _config_service { - uint64 config_id; /* 配置ID,全局唯一,用于寻找对应的配置业务*/ - uint config_src; /* 配置源检查,全局唯一,用于寻找对应的配置业务,从低位到高位,第一位表示web,后续配置扩展 */ - boolean recovery; /* 配置恢复处理函数,如果为FALSE则不进行配置恢复 */ - cm_config_chk chk_callback; /* 配置校验回调函数 */ - cm_config_proc proc_callback; /* 配置接口 */ - cm_config_get get_callback; /* 获取配置接口 */ - cm_config_get_all getall_callback; /* 获取所有配置接口 */ -}; - -typedef struct _config_service config_service_t; - - - - -#endif /* RPC_COMMON_H_ */ - +#ifndef CONFIGM_H_ +#define CONFIGM_H_ + +#include "s2j/s2j.h" +#include "../../../../common/rpc/rpc_common.h" +#include "ipconfig.h" +#include "../../../../../Common/commuapinl.h" +#include "../user_manager_config/user_group_config.h" +#include "../user_manager_config/user_account_config.h" +#include "log_config.h" +#include "authfree.h" +#include "localportal.h" +#include "jumppage.h" +#include "userlock.h" +#include "agingtime.h" +#include "brconfig.h" + +/* 类型定义 */ + +/* IP CONFIG */ +#define NETCONFIG_MODULE 0x00000001 + +/* USER MANAGER CONFIG */ +#define USER_MANAGER_CONFIG_MODULE 0x00000002 + +/*PORTAL SERVER CONFIG */ +#define LOCALAUTH_CONFIG_MODULE 0x00000003 + +#define LOG_CONFIG_MODULE 0x00000004 + +/*nat config */ +#define NAT_CONFIG_MODULE 0x00000008 + + + +/* config id define*/ +#define IPCONFIG_V4 (uint64)((uint64)NETCONFIG_MODULE<<32|1) +#define BR_CONFIG (uint64)((uint64)NETCONFIG_MODULE<<32|2) +#define BRIF_CONFIG (uint64)((uint64)NETCONFIG_MODULE<<32|3) +#define BRFDB_CONFIG (uint64)((uint64)NETCONFIG_MODULE<<32|4) + + +#define USER_MANAGER_CONFIG_GROUP (uint64)((uint64)USER_MANAGER_CONFIG_MODULE<<32|1) +#define USER_MANAGER_CONFIG_USER (uint64)((uint64)USER_MANAGER_CONFIG_MODULE<<32|2) + +#define PORTALSERVER_CONFIG (uint64)((uint64)LOCALAUTH_CONFIG_MODULE<<32|1) +#define AUTHFREE_CONFIG (uint64)((uint64)LOCALAUTH_CONFIG_MODULE<<32|2) +#define USERLOCK_CONFIG (uint64)((uint64)LOCALAUTH_CONFIG_MODULE<<32|3) +#define JUMPPAGE_CONFIG (uint64)((uint64)LOCALAUTH_CONFIG_MODULE<<32|4) +#define AGINGTIME_CONFIG (uint64)((uint64)LOCALAUTH_CONFIG_MODULE<<32|5) + +#define LOG_CONFIG_CONSOLE (uint64)((uint64)LOG_CONFIG_MODULE<<32|1) +#define NAT4_CONFIG (uint64)((uint64)NAT_CONFIG_MODULE<<32|1) + +#define CONFIG_INIT_ARRAY \ +{\ + { \ + NETCONFIG_MODULE, \ + br_bridge_init \ + }, \ + { \ + LOG_CONFIG_MODULE, \ + log_config_init \ + } \ +} + +/* + 1、配置ID,全局唯一,用于寻找对应的配置业务 + 2、配置源检查,全局唯一,用于寻找对应的配置业务, + 从低位到高位,第一位表示WEB,后续配置扩展 + 3、是否配置恢复 + 4、是否是多实例 + 5、配置校验回调函数 + 6、配置处理接口 + 7、配置获取接口 + 8、配置全部获取接口 +*/ +#define CONFIG_SERVICE_ARRAY \ +{ \ + {\ + IPCONFIG_V4, \ + CONFIG_FROM_WEB|CONFIG_FROM_NETOPEER, \ + FALSE, \ + ip_config_chk, \ + ip_config_proc, \ + ip_config_get, \ + ip_config_get_all \ + },\ + {\ + BR_CONFIG, \ + CONFIG_FROM_WEB|CONFIG_FROM_NETOPEER, \ + FALSE, \ + br_config_chk, \ + br_config_proc, \ + NULL, \ + NULL \ + },\ + {\ + BRIF_CONFIG, \ + CONFIG_FROM_WEB|CONFIG_FROM_NETOPEER, \ + FALSE, \ + br_if_config_chk, \ + br_if_config_proc, \ + br_if_config_get, \ + br_if_config_get_all \ + },\ + {\ + BRFDB_CONFIG, \ + CONFIG_FROM_WEB|CONFIG_FROM_NETOPEER, \ + FALSE, \ + br_fdb_config_chk, \ + NULL, \ + br_fdb_config_get, \ + NULL \ + },\ + {\ + USER_MANAGER_CONFIG_GROUP, \ + CONFIG_FROM_WEB, \ + FALSE, \ + usergroup_config_chk, \ + usergroup_config_proc, \ + usergroup_config_get, \ + usergroup_config_get_all \ + },\ + {\ + PORTALSERVER_CONFIG, \ + CONFIG_FROM_WEB|CONFIG_FROM_NETOPEER, \ + FALSE, \ + portalserver_config_chk, \ + portalserver_config_proc, \ + NULL, \ + NULL \ + }, \ + { \ + AUTHFREE_CONFIG, \ + CONFIG_FROM_WEB|CONFIG_FROM_NETOPEER, \ + FALSE, \ + freeauth_config_chk, \ + freeauth_config_proc, \ + NULL, \ + NULL \ + },\ + {\ + USERLOCK_CONFIG, \ + CONFIG_FROM_WEB|CONFIG_FROM_NETOPEER, \ + FALSE, \ + userlock_config_chk, \ + userlock_config_proc, \ + NULL, \ + NULL \ + },\ + {\ + JUMPPAGE_CONFIG, \ + CONFIG_FROM_WEB|CONFIG_FROM_NETOPEER, \ + FALSE, \ + NULL, \ + jumppage_config_proc, \ + NULL, \ + NULL \ + }, \ + {\ + AGINGTIME_CONFIG, \ + CONFIG_FROM_WEB|CONFIG_FROM_NETOPEER, \ + FALSE, \ + agingtime_config_chk, \ + agingtime_config_proc, \ + agingtime_config_get, \ + agingtime_config_get_all \ + }, \ + {\ + USER_MANAGER_CONFIG_USER, \ + CONFIG_FROM_WEB, \ + FALSE, \ + user_config_chk, \ + user_config_proc, \ + user_config_get, \ + user_config_get_all \ + },\ + {\ + LOG_CONFIG_CONSOLE, \ + CONFIG_FROM_WEB, \ + FALSE, \ + log_console_config_chk, \ + log_console_config_proc, \ + NULL, \ + NULL \ + },\ + {\ + NAT4_CONFIG, \ + CONFIG_FROM_WEB|CONFIG_FROM_NETOPEER, \ + FALSE, \ + FALSE, \ + nat_config_chk, \ + nat_config_proc, \ + NULL, \ + nat_config_get_all \ + }\ +} + +typedef ret_code (*cm_config_init)(); + +typedef ret_code (*cm_config_chk)(uint source, uint *config_type, + pointer input, int *input_len, + pointer output, int *output_len); + +typedef ret_code (*cm_config_proc)(uint source, uint config_type, + pointer input, int input_len, + pointer output, int *output_len); + +typedef ret_code (*cm_config_get)(uint source, + pointer input, int input_len, + pointer output, int *output_len); + +typedef ret_code (*cm_config_get_all)(uint source, + pointer output, int *output_len); + +/* 配置注册 */ +struct _config_init { + uint config_mudlue; + cm_config_init init_callback; +}; +typedef struct _config_init config_init_t; + + +/* 配置注册 */ +struct _config_service { + uint64 config_id; /* 配置ID,全局唯一,用于寻找对应的配置业务*/ + uint config_src; /* 配置源检查,全局唯一,用于寻找对应的配置业务,从低位到高位,第一位表示web,后续配置扩展 */ + boolean recovery; /* 配置恢复处理函数,如果为FALSE则不进行配置恢复 */ + cm_config_chk chk_callback; /* 配置校验回调函数 */ + cm_config_proc proc_callback; /* 配置接口 */ + cm_config_get get_callback; /* 获取配置接口 */ + cm_config_get_all getall_callback; /* 获取所有配置接口 */ +}; + +typedef struct _config_service config_service_t; + + + + +#endif /* RPC_COMMON_H_ */ + diff --git a/Platform/user/configm/config-server/nat_config/natconfig.c b/Platform/user/configm/config-server/nat_config/natconfig.c new file mode 100644 index 000000000..6492bc4d3 --- /dev/null +++ b/Platform/user/configm/config-server/nat_config/natconfig.c @@ -0,0 +1,610 @@ +#include "configm.h" +#include "ipconfig.h" +#include "rpc.h" +#include "parsefile.h" + +uchar ip_masklen(struct in_addr netmask) +{ + uint tmp = ~ntohl(netmask.s_addr); + if (tmp) + /* clz: count leading zeroes. sadly, the behaviour of this + * builtin + * is undefined for a 0 argument, even though most CPUs give 32 + */ + return __builtin_clz(tmp); + else + return 32; +} + + +/* Convert masklen into IP address's netmask (network byte order). */ +void masklen2ip(const int masklen, struct in_addr *netmask) +{ + if(masklen < 0 || masklen > IPV4_MAX_BITLEN) + { + return; + } + + /* left shift is only defined for less than the size of the type. + * we unconditionally use long long in case the target platform + * has defined behaviour for << 32 (or has a 64-bit left shift) */ + + if (sizeof(unsigned long long) > 4) + netmask->s_addr = htonl(0xffffffffULL << (32 - masklen)); + else + netmask->s_addr = + htonl(masklen ? 0xffffffffU << (32 - masklen) : 0); +} + +void ip_save_file(ip_config_t *ip_conf, uint config_type) +{ + char *addr_name = "address"; + char *mask_name = "netmask"; + struct in_addr netmask; + char addr_buff[IF_BUFF_LEN] = {0}; + char mask_buff[IF_BUFF_LEN] = {0}; + + if(config_type == CM_CONFIG_SET) + { + sprintf(addr_buff, "address %s\n", inet_ntoa(ip_conf->prefix)); + masklen2ip(ip_conf->prefixlen, &netmask); + sprintf(mask_buff, "netmask %s\n", inet_ntoa(netmask)); + rpc_log_info("%s %s",addr_buff, mask_buff); + + ip_conf_file_set(ip_conf->ifname, addr_name, addr_buff); + ip_conf_file_set(ip_conf->ifname, mask_name, mask_buff); + } + else if(config_type == CM_CONFIG_DEL) + { + ip_conf_file_del(ip_conf->ifname, addr_name); + ip_conf_file_del(ip_conf->ifname, mask_name); + } +} + +/* call ioctl system call */ +ret_code if_ioctl(unsigned long request, caddr_t ifreq, int *ret) +{ + int sock; + int err = 0; + + *ret = 0; + + sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) + { + rpc_log_error("Cannot create UDP socket"); + return RET_SOCKERR; + } + if ((*ret = ioctl(sock, request, ifreq)) < 0) + { + err = errno; + rpc_log_error("Ioctl error: %s\n", strerror(errno)); + + } + + close(sock); + + if (*ret < 0) + { + errno = err; + *ret = err; + return RET_SYSERR; + } + + return RET_OK; +} + + +ret_code ip_config_json_parse(pointer input, uint *conf_type, ip_config_t *config_buff) +{ + //ip_config_string_t *ip_config; + cJSON *json_obj; + + json_obj = cJSON_Parse(input); + if(!json_obj) + { + return RET_INPUTERR; + } + + rpc_log_info("json input:\n %s \n", cJSON_Print(json_obj)); + + s2j_create_struct_obj(ip_config, ip_config_string_t); + + if(ip_config == NULL) + { + cJSON_Delete(json_obj); + return RET_NOMEM; + } + + s2j_struct_get_basic_element(ip_config, json_obj, int, config_type); + S2J_STRUCT_GET_STRING_ELEMENT_N(ip_config, json_obj, ifname, INTERFACE_NAMSIZ); + s2j_struct_get_basic_element(ip_config, json_obj, int, family); + S2J_STRUCT_GET_STRING_ELEMENT_N(ip_config, json_obj, ipaddr, DOT_IP_STR); + s2j_struct_get_basic_element(ip_config, json_obj, int, prefixlen); + + strncpy(config_buff->ifname, ip_config->ifname, INTERFACE_NAMSIZ - 1); + + config_buff->family = (uchar)ip_config->family; + config_buff->prefixlen = (uchar)ip_config->prefixlen; + config_buff->prefix.s_addr = inet_addr(ip_config->ipaddr); + + *conf_type = ip_config->config_type; + + s2j_delete_struct_obj(ip_config); + cJSON_Delete(json_obj); + + return RET_OK; +} + +ret_code ip_config_json_parse_array(pointer input, uint *conf_type, + ip_config_t *config_buff, int *cnt) +{ + //ip_config_string_t *ip_config; + cJSON *json_obj; + cJSON* pArrayItem; + int iCount = 0, i = 0; + + json_obj = cJSON_Parse(input); + if(!json_obj) + { + return RET_INPUTERR; + } + + rpc_log_info("json input:%s \n", cJSON_Print(json_obj)); + + iCount = cJSON_GetArraySize(json_obj); /*ȡ鳤*/ + + config_buff = rpc_new0(ip_config_t, iCount); + conf_type = rpc_new0(uint, iCount); + if(!config_buff || !conf_type) + { + return RET_NOMEM; + } + + s2j_create_struct_obj(ip_config, ip_config_string_t); + if(ip_config == NULL) + { + cJSON_Delete(json_obj); + rpc_free(config_buff); + return RET_NOMEM; + } + + *cnt = 0; + for(i = 0; i < iCount; i++) + { + pArrayItem = cJSON_GetArrayItem(json_obj, i); + if(pArrayItem) + { + memset(ip_config, 0, sizeof(ip_config_string_t)); + + s2j_struct_get_basic_element(ip_config, json_obj, int, config_type); + s2j_struct_get_basic_element(ip_config, json_obj, string, ifname); + s2j_struct_get_basic_element(ip_config, json_obj, int, family); + s2j_struct_get_basic_element(ip_config, json_obj, string, ipaddr); + s2j_struct_get_basic_element(ip_config, json_obj, int, prefixlen); + + strncpy(config_buff[*cnt].ifname, ip_config->ifname, INTERFACE_NAMSIZ - 1); + config_buff[*cnt].family = (uchar)ip_config->family; + config_buff[*cnt].prefixlen = (uchar)ip_config->prefixlen; + config_buff[*cnt].prefix.s_addr = inet_addr(ip_config->ipaddr); + conf_type[*cnt] = ip_config->config_type; + + (*cnt)++; + } + } + + s2j_delete_struct_obj(ip_config); + cJSON_Delete(json_obj); + + return RET_OK; +} + + +ret_code ip_config_format_json(int config_type, ip_config_t *config_buff, + pointer output, int *outlen) +{ + ip_config_string_t tem_buff = {0}; + ip_config_string_t *ip_config = &tem_buff; + //cJSON *json_obj = NULL; + char *json_ip; + + ip_config->config_type = config_type; + ip_config->family = AF_INET; + ip_config->prefixlen = config_buff->prefixlen; + + strncpy(ip_config->ifname, config_buff->ifname, INTERFACE_NAMSIZ - 1); + strncpy(ip_config->ipaddr, inet_ntoa(config_buff->prefix), DOT_IP_STR - 1); + + /* create Student JSON object */ + s2j_create_json_obj(json_obj); + if(json_obj == NULL) + { + return RET_NOMEM; + } + + s2j_json_set_basic_element(json_obj, ip_config, int, config_type); + s2j_json_set_basic_element(json_obj, ip_config, string, ifname); + s2j_json_set_basic_element(json_obj, ip_config, int, family); + s2j_json_set_basic_element(json_obj, ip_config, string, ipaddr); + s2j_json_set_basic_element(json_obj, ip_config, int, prefixlen); + + json_ip = cJSON_PrintUnformatted(json_obj); + *outlen = strlen(json_ip) + 1; + memcpy(output, json_ip, *outlen); + + free(json_ip); + cJSON_Delete(json_obj); + + return RET_OK; +} + +ret_code ip_config_format_json_array(int config_type, ip_config_t *config_buff, + int count, pointer output, int *outlen) +{ + ip_config_string_t tem_buff = {0}; + ip_config_string_t *ip_config = &tem_buff; + cJSON *json_array = NULL; + //cJSON *json_obj = NULL; + char *json_ip; + int i; + + json_array = cJSON_CreateArray(); + if(json_array == NULL) + { + return RET_NOMEM; + } + + for(i = 0; i < count; i++) + { + memset(ip_config, 0, sizeof(ip_config_string_t)); + + ip_config->config_type = config_type; + ip_config->family = AF_INET; + ip_config->prefixlen = config_buff[i].prefixlen; + strncpy(ip_config->ifname, config_buff[i].ifname, INTERFACE_NAMSIZ - 1); + strncpy(ip_config->ipaddr, inet_ntoa(config_buff[i].prefix), DOT_IP_STR - 1); + + /* create Student JSON object */ + s2j_create_json_obj(json_obj); + if(json_obj == NULL) + { + return RET_NOMEM; + } + + cJSON_AddItemToArray(json_array, json_obj); + + s2j_json_set_basic_element(json_obj, ip_config, int, config_type); + s2j_json_set_basic_element(json_obj, ip_config, string, ifname); + s2j_json_set_basic_element(json_obj, ip_config, int, family); + s2j_json_set_basic_element(json_obj, ip_config, string, ipaddr); + s2j_json_set_basic_element(json_obj, ip_config, int, prefixlen); + } + + json_ip = cJSON_PrintUnformatted(json_array); + *outlen = strlen(json_ip) + 1; + memcpy(output, json_ip, *outlen); + + free(json_ip); + cJSON_Delete(json_array); + + return RET_OK; +} + + +ret_code if_set_prefix(ip_config_t *ip_conf, int *code) +{ + ret_code ret; + struct ifreq ifreq = {0}; + struct sockaddr_in addr; + struct sockaddr_in mask; + + strncpy(ifreq.ifr_name, ip_conf->ifname, sizeof(ifreq.ifr_name) - 1); + addr.sin_addr = ip_conf->prefix; + addr.sin_family = ip_conf->family; + memcpy(&ifreq.ifr_addr, &addr, sizeof(struct sockaddr_in)); + + ret = if_ioctl(SIOCSIFADDR, (caddr_t)&ifreq, code); + ASSERT_RET(ret); + + if(ip_conf->prefix.s_addr != 0) + { + masklen2ip(ip_conf->prefixlen, &mask.sin_addr); + mask.sin_family = ip_conf->family; + memcpy(&ifreq.ifr_netmask, &mask, sizeof(struct sockaddr_in)); + + ret = if_ioctl(SIOCSIFNETMASK, (caddr_t)&ifreq, code); + ASSERT_RET(ret); + } + + + return 0; +} + +ret_code if_get_prefix_all(pointer output, int *output_len, int *code) +{ + struct ifreq ifreq[MAX_IF_NUM]; + struct sockaddr_in *addr; + struct ifreq netmask; + ip_config_t *ip_conf; + struct ifconf ifc; + int if_count = 0; + ret_code ret; + int mask_ret; + int i; + + memset(&ifc, 0, sizeof(struct ifconf)); + memset(&ifreq, 0, MAX_IF_NUM * sizeof(struct ifreq)); + + ifc.ifc_len = MAX_IF_NUM * sizeof(struct ifreq); + ifc.ifc_buf = (char *)ifreq; + + ret = if_ioctl(SIOCGIFCONF, (caddr_t)&ifc, code); + ASSERT_RET(ret); + + if_count = ifc.ifc_len / (sizeof(struct ifreq)); + + rpc_log_info("if num is %d\n", if_count); + + if((if_count * sizeof(ip_config_t) > CM_BUFF_SIZE) + || (if_count == 0)) + { + ret = RET_NOMEM; + ASSERT_RET(ret); + } + + ip_conf = rpc_new(ip_config_t, MAX_IF_NUM); + if(ip_conf == NULL) + { + return RET_NOMEM; + } + memset(ip_conf, 0, MAX_IF_NUM * sizeof(ip_config_t)); + + for(i = 0; i < if_count; i++) + { + rpc_log_info("get interface %s info\n", ifreq[i].ifr_name); + strncpy(ip_conf[i].ifname, ifreq[i].ifr_name, INTERFACE_NAMSIZ - 1); + ip_conf[i].family = AF_INET; + ip_conf[i].prefix = ((struct sockaddr_in *)&(ifreq[i].ifr_addr))->sin_addr; + + memset(&netmask, 0, sizeof(netmask)); + strncpy(netmask.ifr_name, ifreq[i].ifr_name, sizeof(netmask.ifr_name) - 1); + + ret = if_ioctl(SIOCGIFNETMASK, (caddr_t)&netmask, &mask_ret); + ASSERT_RET_NO(ret); + + addr = ( struct sockaddr_in * )&(netmask.ifr_netmask ); + ip_conf[i].prefixlen = ip_masklen(addr->sin_addr); + } + + ip_config_format_json_array(CM_CONFIG_GET, ip_conf, if_count, output, output_len); + + rpc_free(ip_conf); + return RET_OK; +} + +ret_code nat_get_prefix(ip_config_t *ip_conf, int *code) +{ + struct sockaddr_in *addr; + struct ifreq netmask; + struct ifreq ifreq; + ret_code ret = RET_OK; + int mask_ret; + int i; + + if(ip_conf->family != AF_INET) + { + ret = RET_INPUTERR; + } + + ASSERT_RET(ret); + + memset(&ifreq, 0, sizeof(struct ifreq)); + + rpc_log_info("get interface %s info\n", ip_conf->ifname); + + strncpy(ifreq.ifr_name, ip_conf->ifname, sizeof(ifreq.ifr_name) - 1); + + ret = if_ioctl(SIOCGIFADDR, (caddr_t)&ifreq, code); + ASSERT_RET(ret); + + + ip_conf->prefix = ((struct sockaddr_in *)&(ifreq.ifr_addr))->sin_addr; + + memset(&ifreq, 0, sizeof(ifreq)); + strncpy(ifreq.ifr_name, ip_conf->ifname, sizeof(ifreq.ifr_name) - 1); + + ret = if_ioctl(SIOCGIFNETMASK, (caddr_t)&ifreq, &mask_ret); + ASSERT_RET_NO(ret); + + addr = ( struct sockaddr_in * )&(ifreq.ifr_netmask); + ip_conf->prefixlen = ip_masklen(addr->sin_addr); + + return ret; +} + +ret_code nat_config_set_chk(uint source,uint config_type, + pointer input, int input_len, + pointer output, int *output_len) +{ + ret_code ret = RET_OK; + ip_config_t *ip_conf; + + ip_conf = (ip_config_t *)input; + + if(input_len < sizeof(ip_config_t) + || strlen(ip_conf->ifname) == 0) + { + ret = RET_INPUTERR; + } + + if (config_type != CM_CONFIG_DEL && ipv4_martian(&ip_conf->prefix)) + { + ret = RET_IPINVALID; + } + + + ASSERT_RET(ret); + + if(ip_conf->prefixlen == 0 || ip_conf->prefixlen > IPV4_MAX_PREFIXLEN) + { + ip_conf->prefixlen = IPV4_DEFAULT_PREFIXLEN; + } + + return RET_OK; +} + +ret_code nat_config_get_chk(uint source,uint config_type, + pointer input, int input_len, + pointer output, int *output_len) +{ + ret_code ret = RET_OK; + ip_config_t *ip_conf; + + ip_conf = (ip_config_t *)input; + + if(input_len < sizeof(ip_config_t) + || strlen(ip_conf->ifname) == 0 ) + { + ret = RET_INPUTERR; + } + + return ret; +} + +ret_code nat_config_getall_chk(uint source,uint config_type, + pointer input, int input_len, + pointer output, int *output_len) +{ + ret_code ret = RET_OK; + + if(*output_len < MAX_IF_NUM * sizeof(ip_config_t)) + { + ret = RET_INPUTERR; + } + + return ret; +} + + +ret_code nat_config_chk(uint source,uint *config_type, + pointer input, int *input_len, + pointer output, int *output_len) + +{ + int config_len = sizeof(ip_config_t); + uint conf_type = CM_CONFIG_GET; + ip_config_t ip_config = {0}; + ret_code ret = RET_OK; + int code = 0; + + ip_config_json_parse(input, &conf_type, &ip_config); + + switch (conf_type) + { + case CM_CONFIG_SET: + case CM_CONFIG_DEL: + ret = ip_config_set_chk(source, conf_type, + &ip_config, config_len, + output, output_len); + break; + case CM_CONFIG_GET: + ret = ip_config_get_chk(source, conf_type, + &ip_config, config_len, + output, output_len); + break; + case CM_CONFIG_GET_ALL: + ret = ip_config_getall_chk(source, conf_type, + &ip_config, config_len, + output, output_len); + break; + default: + ret = RET_NOTSUPPORT; + } + + /* 将传入的json数据转换成结构体,便于后续处理 */ + if(config_len <= CM_BUFF_SIZE) + { + memset(input, 0, *input_len); + memcpy(input, &ip_config, config_len); + *config_type = conf_type; + *input_len = config_len; + } + else + { + ret = RET_NOMEM; + } + + RET_ERR_FORMART(ret, code, output, *output_len); + + return ret; +} + +ret_code nat_config_proc(uint source, uint config_type, + pointer input, int input_len, + pointer output, int *output_len) +{ + uint conf_type = config_type; + ip_config_t conf_buff = {0}; + ip_config_t *ip_conf = &conf_buff; + ret_code ret = RET_OK; + int code; + + ip_conf = (ip_config_t *)input; + + if(conf_type == CM_CONFIG_DEL) + { + ip_conf->prefix.s_addr = 0; + ip_conf->prefixlen = IPV4_DEFAULT_PREFIXLEN; + } + + rpc_log_info("config type is %d, if %s ip %s prefixlen %d\n", + conf_type, ip_conf->ifname, + inet_ntoa(ip_conf->prefix), + ip_conf->prefixlen); + + ret = if_set_prefix(ip_conf, &code); + + RET_ERR_FORMART(ret, code, output, *output_len); + ASSERT_RET(ret); + + ip_save_file(ip_conf, conf_type); + + return RET_OK; +} + +ret_code nat_config_get(uint source, + pointer input, int input_len, + pointer output, int *output_len) +{ + ip_config_t *ip_conf; + ret_code ret = RET_OK; + int code, conf_type; + + ip_conf = (ip_config_t *)input; + + ret = if_get_prefix(ip_conf, &code); + + RET_ERR_FORMART(ret, code, output, *output_len); + ASSERT_RET(ret); + + ip_config_format_json(CM_CONFIG_GET, ip_conf, output, output_len); + + return ret; +} + +ret_code nat_config_get_all(uint source, pointer output, int *output_len) +{ + ret_code ret = RET_OK; + int code = 0; + + *output_len = 0; + ret = if_get_prefix_all(output, output_len, &code); + + rpc_log_info("ip_config_get_all: %s\n", output); + + RET_ERR_FORMART(ret, code, output, *output_len); + ASSERT_RET(ret); + + return RET_OK; + +} diff --git a/kernel/linux-4.14.83/include/uapi/linux/netfilter/xt_CONNMARK.h b/kernel/linux-4.14.83/include/uapi/linux/netfilter/xt_CONNMARK.h index 36cc956ea..408a9654f 100755 --- a/kernel/linux-4.14.83/include/uapi/linux/netfilter/xt_CONNMARK.h +++ b/kernel/linux-4.14.83/include/uapi/linux/netfilter/xt_CONNMARK.h @@ -1,7 +1,32 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef _XT_CONNMARK_H_target -#define _XT_CONNMARK_H_target +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ +#ifndef _XT_CONNMARK_H +#define _XT_CONNMARK_H -#include +#include -#endif /*_XT_CONNMARK_H_target*/ +/* Copyright (C) 2002,2004 MARA Systems AB + * by Henrik Nordstrom + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +enum { + XT_CONNMARK_SET = 0, + XT_CONNMARK_SAVE, + XT_CONNMARK_RESTORE +}; + +struct xt_connmark_tginfo1 { + __u32 ctmark, ctmask, nfmask; + __u8 mode; +}; + +struct xt_connmark_mtinfo1 { + __u32 mark, mask; + __u8 invert; +}; + +#endif /*_XT_CONNMARK_H*/ diff --git a/kernel/linux-4.14.83/include/uapi/linux/netfilter/xt_DSCP.h b/kernel/linux-4.14.83/include/uapi/linux/netfilter/xt_DSCP.h index 223d635e8..7594e4df8 100755 --- a/kernel/linux-4.14.83/include/uapi/linux/netfilter/xt_DSCP.h +++ b/kernel/linux-4.14.83/include/uapi/linux/netfilter/xt_DSCP.h @@ -1,27 +1,32 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* x_tables module for setting the IPv4/IPv6 DSCP field +/* x_tables module for matching the IPv4/IPv6 DSCP field * * (C) 2002 Harald Welte - * based on ipt_FTOS.c (C) 2000 by Matthew G. Marsh * This software is distributed under GNU GPL v2, 1991 * * See RFC2474 for a description of the DSCP field within the IP Header. * - * xt_DSCP.h,v 1.7 2002/03/14 12:03:13 laforge Exp + * xt_dscp.h,v 1.3 2002/08/05 19:00:21 laforge Exp */ -#ifndef _XT_DSCP_TARGET_H -#define _XT_DSCP_TARGET_H -#include +#ifndef _XT_DSCP_H +#define _XT_DSCP_H + #include -/* target info */ -struct xt_DSCP_info { +#define XT_DSCP_MASK 0xfc /* 11111100 */ +#define XT_DSCP_SHIFT 2 +#define XT_DSCP_MAX 0x3f /* 00111111 */ + +/* match info */ +struct xt_dscp_info { __u8 dscp; + __u8 invert; }; -struct xt_tos_target_info { - __u8 tos_value; +struct xt_tos_match_info { __u8 tos_mask; + __u8 tos_value; + __u8 invert; }; -#endif /* _XT_DSCP_TARGET_H */ +#endif /* _XT_DSCP_H */ diff --git a/kernel/linux-4.14.83/include/uapi/linux/netfilter/xt_MARK.h b/kernel/linux-4.14.83/include/uapi/linux/netfilter/xt_MARK.h index f1fe2b4be..9d0526ced 100755 --- a/kernel/linux-4.14.83/include/uapi/linux/netfilter/xt_MARK.h +++ b/kernel/linux-4.14.83/include/uapi/linux/netfilter/xt_MARK.h @@ -1,7 +1,16 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef _XT_MARK_H_target -#define _XT_MARK_H_target +#ifndef _XT_MARK_H +#define _XT_MARK_H -#include +#include -#endif /*_XT_MARK_H_target */ +struct xt_mark_tginfo2 { + __u32 mark, mask; +}; + +struct xt_mark_mtinfo1 { + __u32 mark, mask; + __u8 invert; +}; + +#endif /*_XT_MARK_H*/ diff --git a/kernel/linux-4.14.83/include/uapi/linux/netfilter/xt_RATEEST.h b/kernel/linux-4.14.83/include/uapi/linux/netfilter/xt_RATEEST.h index 2b87a71e6..52a37bdc1 100755 --- a/kernel/linux-4.14.83/include/uapi/linux/netfilter/xt_RATEEST.h +++ b/kernel/linux-4.14.83/include/uapi/linux/netfilter/xt_RATEEST.h @@ -1,17 +1,39 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef _XT_RATEEST_TARGET_H -#define _XT_RATEEST_TARGET_H +#ifndef _XT_RATEEST_MATCH_H +#define _XT_RATEEST_MATCH_H #include #include -struct xt_rateest_target_info { - char name[IFNAMSIZ]; - __s8 interval; - __u8 ewma_log; - - /* Used internally by the kernel */ - struct xt_rateest *est __attribute__((aligned(8))); +enum xt_rateest_match_flags { + XT_RATEEST_MATCH_INVERT = 1<<0, + XT_RATEEST_MATCH_ABS = 1<<1, + XT_RATEEST_MATCH_REL = 1<<2, + XT_RATEEST_MATCH_DELTA = 1<<3, + XT_RATEEST_MATCH_BPS = 1<<4, + XT_RATEEST_MATCH_PPS = 1<<5, }; -#endif /* _XT_RATEEST_TARGET_H */ +enum xt_rateest_match_mode { + XT_RATEEST_MATCH_NONE, + XT_RATEEST_MATCH_EQ, + XT_RATEEST_MATCH_LT, + XT_RATEEST_MATCH_GT, +}; + +struct xt_rateest_match_info { + char name1[IFNAMSIZ]; + char name2[IFNAMSIZ]; + __u16 flags; + __u16 mode; + __u32 bps1; + __u32 pps1; + __u32 bps2; + __u32 pps2; + + /* Used internally by the kernel */ + struct xt_rateest *est1 __attribute__((aligned(8))); + struct xt_rateest *est2 __attribute__((aligned(8))); +}; + +#endif /* _XT_RATEEST_MATCH_H */ diff --git a/kernel/linux-4.14.83/include/uapi/linux/netfilter/xt_TCPMSS.h b/kernel/linux-4.14.83/include/uapi/linux/netfilter/xt_TCPMSS.h index 65ea6c9da..2268f58b4 100755 --- a/kernel/linux-4.14.83/include/uapi/linux/netfilter/xt_TCPMSS.h +++ b/kernel/linux-4.14.83/include/uapi/linux/netfilter/xt_TCPMSS.h @@ -1,13 +1,12 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef _XT_TCPMSS_H -#define _XT_TCPMSS_H +#ifndef _XT_TCPMSS_MATCH_H +#define _XT_TCPMSS_MATCH_H #include -struct xt_tcpmss_info { - __u16 mss; +struct xt_tcpmss_match_info { + __u16 mss_min, mss_max; + __u8 invert; }; -#define XT_TCPMSS_CLAMP_PMTU 0xffff - -#endif /* _XT_TCPMSS_H */ +#endif /*_XT_TCPMSS_MATCH_H*/ diff --git a/kernel/linux-4.14.83/include/uapi/linux/netfilter_ipv4/ipt_ECN.h b/kernel/linux-4.14.83/include/uapi/linux/netfilter_ipv4/ipt_ECN.h index e3630fd04..8121bec47 100755 --- a/kernel/linux-4.14.83/include/uapi/linux/netfilter_ipv4/ipt_ECN.h +++ b/kernel/linux-4.14.83/include/uapi/linux/netfilter_ipv4/ipt_ECN.h @@ -1,34 +1,16 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* Header file for iptables ipt_ECN target - * - * (C) 2002 by Harald Welte - * - * This software is distributed under GNU GPL v2, 1991 - * - * ipt_ECN.h,v 1.3 2002/05/29 12:17:40 laforge Exp -*/ -#ifndef _IPT_ECN_TARGET_H -#define _IPT_ECN_TARGET_H +#ifndef _IPT_ECN_H +#define _IPT_ECN_H -#include -#include +#include +#define ipt_ecn_info xt_ecn_info -#define IPT_ECN_IP_MASK (~XT_DSCP_MASK) - -#define IPT_ECN_OP_SET_IP 0x01 /* set ECN bits of IPv4 header */ -#define IPT_ECN_OP_SET_ECE 0x10 /* set ECE bit of TCP header */ -#define IPT_ECN_OP_SET_CWR 0x20 /* set CWR bit of TCP header */ - -#define IPT_ECN_OP_MASK 0xce - -struct ipt_ECN_info { - __u8 operation; /* bitset of operations */ - __u8 ip_ect; /* ECT codepoint of IPv4 header, pre-shifted */ - union { - struct { - __u8 ece:1, cwr:1; /* TCP ECT bits */ - } tcp; - } proto; +enum { + IPT_ECN_IP_MASK = XT_ECN_IP_MASK, + IPT_ECN_OP_MATCH_IP = XT_ECN_OP_MATCH_IP, + IPT_ECN_OP_MATCH_ECE = XT_ECN_OP_MATCH_ECE, + IPT_ECN_OP_MATCH_CWR = XT_ECN_OP_MATCH_CWR, + IPT_ECN_OP_MATCH_MASK = XT_ECN_OP_MATCH_MASK, }; -#endif /* _IPT_ECN_TARGET_H */ +#endif /* IPT_ECN_H */ diff --git a/kernel/linux-4.14.83/include/uapi/linux/netfilter_ipv4/ipt_TTL.h b/kernel/linux-4.14.83/include/uapi/linux/netfilter_ipv4/ipt_TTL.h index 57d2fc67a..ad0226a86 100755 --- a/kernel/linux-4.14.83/include/uapi/linux/netfilter_ipv4/ipt_TTL.h +++ b/kernel/linux-4.14.83/include/uapi/linux/netfilter_ipv4/ipt_TTL.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* TTL modification module for IP tables - * (C) 2000 by Harald Welte */ +/* IP tables module for matching the value of the TTL + * (C) 2000 by Harald Welte */ #ifndef _IPT_TTL_H #define _IPT_TTL_H @@ -8,14 +8,14 @@ #include enum { - IPT_TTL_SET = 0, - IPT_TTL_INC, - IPT_TTL_DEC + IPT_TTL_EQ = 0, /* equals */ + IPT_TTL_NE, /* not equals */ + IPT_TTL_LT, /* less than */ + IPT_TTL_GT, /* greater than */ }; -#define IPT_TTL_MAXMODE IPT_TTL_DEC -struct ipt_TTL_info { +struct ipt_ttl_info { __u8 mode; __u8 ttl; }; diff --git a/kernel/linux-4.14.83/include/uapi/linux/netfilter_ipv6/ip6t_HL.h b/kernel/linux-4.14.83/include/uapi/linux/netfilter_ipv6/ip6t_HL.h index eaed56a28..6b62f9418 100755 --- a/kernel/linux-4.14.83/include/uapi/linux/netfilter_ipv6/ip6t_HL.h +++ b/kernel/linux-4.14.83/include/uapi/linux/netfilter_ipv6/ip6t_HL.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -/* Hop Limit modification module for ip6tables +/* ip6tables module for matching the Hop Limit value * Maciej Soltysiak - * Based on HW's TTL module */ + * Based on HW's ttl module */ #ifndef _IP6T_HL_H #define _IP6T_HL_H @@ -9,14 +9,14 @@ #include enum { - IP6T_HL_SET = 0, - IP6T_HL_INC, - IP6T_HL_DEC + IP6T_HL_EQ = 0, /* equals */ + IP6T_HL_NE, /* not equals */ + IP6T_HL_LT, /* less than */ + IP6T_HL_GT, /* greater than */ }; -#define IP6T_HL_MAXMODE IP6T_HL_DEC -struct ip6t_HL_info { +struct ip6t_hl_info { __u8 mode; __u8 hop_limit; }; diff --git a/kernel/linux-4.14.83/net/netfilter/xt_DSCP.c b/kernel/linux-4.14.83/net/netfilter/xt_DSCP.c index 3f83d38c4..236ac8008 100755 --- a/kernel/linux-4.14.83/net/netfilter/xt_DSCP.c +++ b/kernel/linux-4.14.83/net/netfilter/xt_DSCP.c @@ -1,14 +1,11 @@ -/* x_tables module for setting the IPv4/IPv6 DSCP field, Version 1.8 +/* IP tables module for matching the value of the IPv4/IPv6 DSCP field * * (C) 2002 by Harald Welte - * based on ipt_FTOS.c (C) 2000 by Matthew G. Marsh * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. - * - * See RFC2474 for a description of the DSCP field within the IP Header. -*/ + */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include #include @@ -17,150 +14,102 @@ #include #include -#include +#include MODULE_AUTHOR("Harald Welte "); -MODULE_DESCRIPTION("Xtables: DSCP/TOS field modification"); +MODULE_DESCRIPTION("Xtables: DSCP/TOS field match"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("ipt_DSCP"); -MODULE_ALIAS("ip6t_DSCP"); -MODULE_ALIAS("ipt_TOS"); -MODULE_ALIAS("ip6t_TOS"); +MODULE_ALIAS("ipt_dscp"); +MODULE_ALIAS("ip6t_dscp"); +MODULE_ALIAS("ipt_tos"); +MODULE_ALIAS("ip6t_tos"); -static unsigned int -dscp_tg(struct sk_buff *skb, const struct xt_action_param *par) +static bool +dscp_mt(const struct sk_buff *skb, struct xt_action_param *par) { - const struct xt_DSCP_info *dinfo = par->targinfo; + const struct xt_dscp_info *info = par->matchinfo; u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT; - if (dscp != dinfo->dscp) { - if (!skb_make_writable(skb, sizeof(struct iphdr))) - return NF_DROP; - - ipv4_change_dsfield(ip_hdr(skb), - (__force __u8)(~XT_DSCP_MASK), - dinfo->dscp << XT_DSCP_SHIFT); - - } - return XT_CONTINUE; + return (dscp == info->dscp) ^ !!info->invert; } -static unsigned int -dscp_tg6(struct sk_buff *skb, const struct xt_action_param *par) +static bool +dscp_mt6(const struct sk_buff *skb, struct xt_action_param *par) { - const struct xt_DSCP_info *dinfo = par->targinfo; + const struct xt_dscp_info *info = par->matchinfo; u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT; - if (dscp != dinfo->dscp) { - if (!skb_make_writable(skb, sizeof(struct ipv6hdr))) - return NF_DROP; - - ipv6_change_dsfield(ipv6_hdr(skb), - (__force __u8)(~XT_DSCP_MASK), - dinfo->dscp << XT_DSCP_SHIFT); - } - return XT_CONTINUE; + return (dscp == info->dscp) ^ !!info->invert; } -static int dscp_tg_check(const struct xt_tgchk_param *par) +static int dscp_mt_check(const struct xt_mtchk_param *par) { - const struct xt_DSCP_info *info = par->targinfo; + const struct xt_dscp_info *info = par->matchinfo; if (info->dscp > XT_DSCP_MAX) { pr_info("dscp %x out of range\n", info->dscp); return -EDOM; } + return 0; } -static unsigned int -tos_tg(struct sk_buff *skb, const struct xt_action_param *par) +static bool tos_mt(const struct sk_buff *skb, struct xt_action_param *par) { - const struct xt_tos_target_info *info = par->targinfo; - struct iphdr *iph = ip_hdr(skb); - u_int8_t orig, nv; + const struct xt_tos_match_info *info = par->matchinfo; - orig = ipv4_get_dsfield(iph); - nv = (orig & ~info->tos_mask) ^ info->tos_value; - - if (orig != nv) { - if (!skb_make_writable(skb, sizeof(struct iphdr))) - return NF_DROP; - iph = ip_hdr(skb); - ipv4_change_dsfield(iph, 0, nv); - } - - return XT_CONTINUE; + if (xt_family(par) == NFPROTO_IPV4) + return ((ip_hdr(skb)->tos & info->tos_mask) == + info->tos_value) ^ !!info->invert; + else + return ((ipv6_get_dsfield(ipv6_hdr(skb)) & info->tos_mask) == + info->tos_value) ^ !!info->invert; } -static unsigned int -tos_tg6(struct sk_buff *skb, const struct xt_action_param *par) -{ - const struct xt_tos_target_info *info = par->targinfo; - struct ipv6hdr *iph = ipv6_hdr(skb); - u_int8_t orig, nv; - - orig = ipv6_get_dsfield(iph); - nv = (orig & ~info->tos_mask) ^ info->tos_value; - - if (orig != nv) { - if (!skb_make_writable(skb, sizeof(struct iphdr))) - return NF_DROP; - iph = ipv6_hdr(skb); - ipv6_change_dsfield(iph, 0, nv); - } - - return XT_CONTINUE; -} - -static struct xt_target dscp_tg_reg[] __read_mostly = { +static struct xt_match dscp_mt_reg[] __read_mostly = { { - .name = "DSCP", + .name = "dscp", .family = NFPROTO_IPV4, - .checkentry = dscp_tg_check, - .target = dscp_tg, - .targetsize = sizeof(struct xt_DSCP_info), - .table = "mangle", + .checkentry = dscp_mt_check, + .match = dscp_mt, + .matchsize = sizeof(struct xt_dscp_info), .me = THIS_MODULE, }, { - .name = "DSCP", + .name = "dscp", .family = NFPROTO_IPV6, - .checkentry = dscp_tg_check, - .target = dscp_tg6, - .targetsize = sizeof(struct xt_DSCP_info), - .table = "mangle", + .checkentry = dscp_mt_check, + .match = dscp_mt6, + .matchsize = sizeof(struct xt_dscp_info), .me = THIS_MODULE, }, { - .name = "TOS", + .name = "tos", .revision = 1, .family = NFPROTO_IPV4, - .table = "mangle", - .target = tos_tg, - .targetsize = sizeof(struct xt_tos_target_info), + .match = tos_mt, + .matchsize = sizeof(struct xt_tos_match_info), .me = THIS_MODULE, }, { - .name = "TOS", + .name = "tos", .revision = 1, .family = NFPROTO_IPV6, - .table = "mangle", - .target = tos_tg6, - .targetsize = sizeof(struct xt_tos_target_info), + .match = tos_mt, + .matchsize = sizeof(struct xt_tos_match_info), .me = THIS_MODULE, }, }; -static int __init dscp_tg_init(void) +static int __init dscp_mt_init(void) { - return xt_register_targets(dscp_tg_reg, ARRAY_SIZE(dscp_tg_reg)); + return xt_register_matches(dscp_mt_reg, ARRAY_SIZE(dscp_mt_reg)); } -static void __exit dscp_tg_exit(void) +static void __exit dscp_mt_exit(void) { - xt_unregister_targets(dscp_tg_reg, ARRAY_SIZE(dscp_tg_reg)); + xt_unregister_matches(dscp_mt_reg, ARRAY_SIZE(dscp_mt_reg)); } -module_init(dscp_tg_init); -module_exit(dscp_tg_exit); +module_init(dscp_mt_init); +module_exit(dscp_mt_exit); diff --git a/kernel/linux-4.14.83/net/netfilter/xt_HL.c b/kernel/linux-4.14.83/net/netfilter/xt_HL.c index 1535e87ed..003951149 100755 --- a/kernel/linux-4.14.83/net/netfilter/xt_HL.c +++ b/kernel/linux-4.14.83/net/netfilter/xt_HL.c @@ -1,169 +1,96 @@ /* - * TTL modification target for IP tables - * (C) 2000,2005 by Harald Welte + * IP tables module for matching the value of the TTL + * (C) 2000,2001 by Harald Welte * - * Hop Limit modification target for ip6tables - * Maciej Soltysiak + * Hop Limit matching module + * (C) 2001-2002 Maciej Soltysiak * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include -#include + #include #include -#include +#include +#include #include -#include -#include +#include +#include -MODULE_AUTHOR("Harald Welte "); MODULE_AUTHOR("Maciej Soltysiak "); -MODULE_DESCRIPTION("Xtables: Hoplimit/TTL Limit field modification target"); +MODULE_DESCRIPTION("Xtables: Hoplimit/TTL field match"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("ipt_ttl"); +MODULE_ALIAS("ip6t_hl"); -static unsigned int -ttl_tg(struct sk_buff *skb, const struct xt_action_param *par) +static bool ttl_mt(const struct sk_buff *skb, struct xt_action_param *par) { - struct iphdr *iph; - const struct ipt_TTL_info *info = par->targinfo; - int new_ttl; - - if (!skb_make_writable(skb, skb->len)) - return NF_DROP; - - iph = ip_hdr(skb); + const struct ipt_ttl_info *info = par->matchinfo; + const u8 ttl = ip_hdr(skb)->ttl; switch (info->mode) { - case IPT_TTL_SET: - new_ttl = info->ttl; - break; - case IPT_TTL_INC: - new_ttl = iph->ttl + info->ttl; - if (new_ttl > 255) - new_ttl = 255; - break; - case IPT_TTL_DEC: - new_ttl = iph->ttl - info->ttl; - if (new_ttl < 0) - new_ttl = 0; - break; - default: - new_ttl = iph->ttl; - break; + case IPT_TTL_EQ: + return ttl == info->ttl; + case IPT_TTL_NE: + return ttl != info->ttl; + case IPT_TTL_LT: + return ttl < info->ttl; + case IPT_TTL_GT: + return ttl > info->ttl; } - if (new_ttl != iph->ttl) { - csum_replace2(&iph->check, htons(iph->ttl << 8), - htons(new_ttl << 8)); - iph->ttl = new_ttl; - } - - return XT_CONTINUE; + return false; } -static unsigned int -hl_tg6(struct sk_buff *skb, const struct xt_action_param *par) +static bool hl_mt6(const struct sk_buff *skb, struct xt_action_param *par) { - struct ipv6hdr *ip6h; - const struct ip6t_HL_info *info = par->targinfo; - int new_hl; - - if (!skb_make_writable(skb, skb->len)) - return NF_DROP; - - ip6h = ipv6_hdr(skb); + const struct ip6t_hl_info *info = par->matchinfo; + const struct ipv6hdr *ip6h = ipv6_hdr(skb); switch (info->mode) { - case IP6T_HL_SET: - new_hl = info->hop_limit; - break; - case IP6T_HL_INC: - new_hl = ip6h->hop_limit + info->hop_limit; - if (new_hl > 255) - new_hl = 255; - break; - case IP6T_HL_DEC: - new_hl = ip6h->hop_limit - info->hop_limit; - if (new_hl < 0) - new_hl = 0; - break; - default: - new_hl = ip6h->hop_limit; - break; + case IP6T_HL_EQ: + return ip6h->hop_limit == info->hop_limit; + case IP6T_HL_NE: + return ip6h->hop_limit != info->hop_limit; + case IP6T_HL_LT: + return ip6h->hop_limit < info->hop_limit; + case IP6T_HL_GT: + return ip6h->hop_limit > info->hop_limit; } - ip6h->hop_limit = new_hl; - - return XT_CONTINUE; + return false; } -static int ttl_tg_check(const struct xt_tgchk_param *par) -{ - const struct ipt_TTL_info *info = par->targinfo; - - if (info->mode > IPT_TTL_MAXMODE) { - pr_info("TTL: invalid or unknown mode %u\n", info->mode); - return -EINVAL; - } - if (info->mode != IPT_TTL_SET && info->ttl == 0) - return -EINVAL; - return 0; -} - -static int hl_tg6_check(const struct xt_tgchk_param *par) -{ - const struct ip6t_HL_info *info = par->targinfo; - - if (info->mode > IP6T_HL_MAXMODE) { - pr_info("invalid or unknown mode %u\n", info->mode); - return -EINVAL; - } - if (info->mode != IP6T_HL_SET && info->hop_limit == 0) { - pr_info("increment/decrement does not " - "make sense with value 0\n"); - return -EINVAL; - } - return 0; -} - -static struct xt_target hl_tg_reg[] __read_mostly = { +static struct xt_match hl_mt_reg[] __read_mostly = { { - .name = "TTL", + .name = "ttl", .revision = 0, .family = NFPROTO_IPV4, - .target = ttl_tg, - .targetsize = sizeof(struct ipt_TTL_info), - .table = "mangle", - .checkentry = ttl_tg_check, + .match = ttl_mt, + .matchsize = sizeof(struct ipt_ttl_info), .me = THIS_MODULE, }, { - .name = "HL", + .name = "hl", .revision = 0, .family = NFPROTO_IPV6, - .target = hl_tg6, - .targetsize = sizeof(struct ip6t_HL_info), - .table = "mangle", - .checkentry = hl_tg6_check, + .match = hl_mt6, + .matchsize = sizeof(struct ip6t_hl_info), .me = THIS_MODULE, }, }; -static int __init hl_tg_init(void) +static int __init hl_mt_init(void) { - return xt_register_targets(hl_tg_reg, ARRAY_SIZE(hl_tg_reg)); + return xt_register_matches(hl_mt_reg, ARRAY_SIZE(hl_mt_reg)); } -static void __exit hl_tg_exit(void) +static void __exit hl_mt_exit(void) { - xt_unregister_targets(hl_tg_reg, ARRAY_SIZE(hl_tg_reg)); + xt_unregister_matches(hl_mt_reg, ARRAY_SIZE(hl_mt_reg)); } -module_init(hl_tg_init); -module_exit(hl_tg_exit); -MODULE_ALIAS("ipt_TTL"); -MODULE_ALIAS("ip6t_HL"); +module_init(hl_mt_init); +module_exit(hl_mt_exit); diff --git a/kernel/linux-4.14.83/net/netfilter/xt_RATEEST.c b/kernel/linux-4.14.83/net/netfilter/xt_RATEEST.c index 141c29519..755d2f669 100755 --- a/kernel/linux-4.14.83/net/netfilter/xt_RATEEST.c +++ b/kernel/linux-4.14.83/net/netfilter/xt_RATEEST.c @@ -8,196 +8,149 @@ #include #include #include -#include -#include -#include -#include -#include -#include #include -#include +#include #include -static DEFINE_MUTEX(xt_rateest_mutex); -#define RATEEST_HSIZE 16 -static struct hlist_head rateest_hash[RATEEST_HSIZE] __read_mostly; -static unsigned int jhash_rnd __read_mostly; - -static unsigned int xt_rateest_hash(const char *name) +static bool +xt_rateest_mt(const struct sk_buff *skb, struct xt_action_param *par) { - return jhash(name, FIELD_SIZEOF(struct xt_rateest, name), jhash_rnd) & - (RATEEST_HSIZE - 1); -} + const struct xt_rateest_match_info *info = par->matchinfo; + struct gnet_stats_rate_est64 sample = {0}; + u_int32_t bps1, bps2, pps1, pps2; + bool ret = true; -static void xt_rateest_hash_insert(struct xt_rateest *est) -{ - unsigned int h; + gen_estimator_read(&info->est1->rate_est, &sample); - h = xt_rateest_hash(est->name); - hlist_add_head(&est->list, &rateest_hash[h]); -} + if (info->flags & XT_RATEEST_MATCH_DELTA) { + bps1 = info->bps1 >= sample.bps ? info->bps1 - sample.bps : 0; + pps1 = info->pps1 >= sample.pps ? info->pps1 - sample.pps : 0; + } else { + bps1 = sample.bps; + pps1 = sample.pps; + } -static struct xt_rateest *__xt_rateest_lookup(const char *name) -{ - struct xt_rateest *est; - unsigned int h; + if (info->flags & XT_RATEEST_MATCH_ABS) { + bps2 = info->bps2; + pps2 = info->pps2; + } else { + gen_estimator_read(&info->est2->rate_est, &sample); - h = xt_rateest_hash(name); - hlist_for_each_entry(est, &rateest_hash[h], list) { - if (strcmp(est->name, name) == 0) { - est->refcnt++; - return est; + if (info->flags & XT_RATEEST_MATCH_DELTA) { + bps2 = info->bps2 >= sample.bps ? info->bps2 - sample.bps : 0; + pps2 = info->pps2 >= sample.pps ? info->pps2 - sample.pps : 0; + } else { + bps2 = sample.bps; + pps2 = sample.pps; } } - return NULL; -} - -struct xt_rateest *xt_rateest_lookup(const char *name) -{ - struct xt_rateest *est; - - mutex_lock(&xt_rateest_mutex); - est = __xt_rateest_lookup(name); - mutex_unlock(&xt_rateest_mutex); - return est; -} -EXPORT_SYMBOL_GPL(xt_rateest_lookup); - -void xt_rateest_put(struct xt_rateest *est) -{ - mutex_lock(&xt_rateest_mutex); - if (--est->refcnt == 0) { - hlist_del(&est->list); - gen_kill_estimator(&est->rate_est); - /* - * gen_estimator est_timer() might access est->lock or bstats, - * wait a RCU grace period before freeing 'est' - */ - kfree_rcu(est, rcu); - } - mutex_unlock(&xt_rateest_mutex); -} -EXPORT_SYMBOL_GPL(xt_rateest_put); - -static unsigned int -xt_rateest_tg(struct sk_buff *skb, const struct xt_action_param *par) -{ - const struct xt_rateest_target_info *info = par->targinfo; - struct gnet_stats_basic_packed *stats = &info->est->bstats; - - spin_lock_bh(&info->est->lock); - stats->bytes += skb->len; - stats->packets++; - spin_unlock_bh(&info->est->lock); - - return XT_CONTINUE; -} - -static int xt_rateest_tg_checkentry(const struct xt_tgchk_param *par) -{ - struct xt_rateest_target_info *info = par->targinfo; - struct xt_rateest *est; - struct { - struct nlattr opt; - struct gnet_estimator est; - } cfg; - int ret; - - net_get_random_once(&jhash_rnd, sizeof(jhash_rnd)); - - mutex_lock(&xt_rateest_mutex); - est = __xt_rateest_lookup(info->name); - if (est) { - mutex_unlock(&xt_rateest_mutex); - /* - * If estimator parameters are specified, they must match the - * existing estimator. - */ - if ((!info->interval && !info->ewma_log) || - (info->interval != est->params.interval || - info->ewma_log != est->params.ewma_log)) { - xt_rateest_put(est); - return -EINVAL; - } - info->est = est; - return 0; + switch (info->mode) { + case XT_RATEEST_MATCH_LT: + if (info->flags & XT_RATEEST_MATCH_BPS) + ret &= bps1 < bps2; + if (info->flags & XT_RATEEST_MATCH_PPS) + ret &= pps1 < pps2; + break; + case XT_RATEEST_MATCH_GT: + if (info->flags & XT_RATEEST_MATCH_BPS) + ret &= bps1 > bps2; + if (info->flags & XT_RATEEST_MATCH_PPS) + ret &= pps1 > pps2; + break; + case XT_RATEEST_MATCH_EQ: + if (info->flags & XT_RATEEST_MATCH_BPS) + ret &= bps1 == bps2; + if (info->flags & XT_RATEEST_MATCH_PPS) + ret &= pps1 == pps2; + break; } - ret = -ENOMEM; - est = kzalloc(sizeof(*est), GFP_KERNEL); - if (!est) - goto err1; - - strlcpy(est->name, info->name, sizeof(est->name)); - spin_lock_init(&est->lock); - est->refcnt = 1; - est->params.interval = info->interval; - est->params.ewma_log = info->ewma_log; - - cfg.opt.nla_len = nla_attr_size(sizeof(cfg.est)); - cfg.opt.nla_type = TCA_STATS_RATE_EST; - cfg.est.interval = info->interval; - cfg.est.ewma_log = info->ewma_log; - - ret = gen_new_estimator(&est->bstats, NULL, &est->rate_est, - &est->lock, NULL, &cfg.opt); - if (ret < 0) - goto err2; - - info->est = est; - xt_rateest_hash_insert(est); - mutex_unlock(&xt_rateest_mutex); - return 0; - -err2: - kfree(est); -err1: - mutex_unlock(&xt_rateest_mutex); + ret ^= info->flags & XT_RATEEST_MATCH_INVERT ? true : false; return ret; } -static void xt_rateest_tg_destroy(const struct xt_tgdtor_param *par) +static int xt_rateest_mt_checkentry(const struct xt_mtchk_param *par) { - struct xt_rateest_target_info *info = par->targinfo; + struct xt_rateest_match_info *info = par->matchinfo; + struct xt_rateest *est1, *est2; + int ret = -EINVAL; - xt_rateest_put(info->est); + if (hweight32(info->flags & (XT_RATEEST_MATCH_ABS | + XT_RATEEST_MATCH_REL)) != 1) + goto err1; + + if (!(info->flags & (XT_RATEEST_MATCH_BPS | XT_RATEEST_MATCH_PPS))) + goto err1; + + switch (info->mode) { + case XT_RATEEST_MATCH_EQ: + case XT_RATEEST_MATCH_LT: + case XT_RATEEST_MATCH_GT: + break; + default: + goto err1; + } + + ret = -ENOENT; + est1 = xt_rateest_lookup(info->name1); + if (!est1) + goto err1; + + est2 = NULL; + if (info->flags & XT_RATEEST_MATCH_REL) { + est2 = xt_rateest_lookup(info->name2); + if (!est2) + goto err2; + } + + info->est1 = est1; + info->est2 = est2; + return 0; + +err2: + xt_rateest_put(est1); +err1: + return ret; } -static struct xt_target xt_rateest_tg_reg __read_mostly = { - .name = "RATEEST", +static void xt_rateest_mt_destroy(const struct xt_mtdtor_param *par) +{ + struct xt_rateest_match_info *info = par->matchinfo; + + xt_rateest_put(info->est1); + if (info->est2) + xt_rateest_put(info->est2); +} + +static struct xt_match xt_rateest_mt_reg __read_mostly = { + .name = "rateest", .revision = 0, .family = NFPROTO_UNSPEC, - .target = xt_rateest_tg, - .checkentry = xt_rateest_tg_checkentry, - .destroy = xt_rateest_tg_destroy, - .targetsize = sizeof(struct xt_rateest_target_info), - .usersize = offsetof(struct xt_rateest_target_info, est), + .match = xt_rateest_mt, + .checkentry = xt_rateest_mt_checkentry, + .destroy = xt_rateest_mt_destroy, + .matchsize = sizeof(struct xt_rateest_match_info), + .usersize = offsetof(struct xt_rateest_match_info, est1), .me = THIS_MODULE, }; -static int __init xt_rateest_tg_init(void) +static int __init xt_rateest_mt_init(void) { - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(rateest_hash); i++) - INIT_HLIST_HEAD(&rateest_hash[i]); - - return xt_register_target(&xt_rateest_tg_reg); + return xt_register_match(&xt_rateest_mt_reg); } -static void __exit xt_rateest_tg_fini(void) +static void __exit xt_rateest_mt_fini(void) { - xt_unregister_target(&xt_rateest_tg_reg); + xt_unregister_match(&xt_rateest_mt_reg); } - MODULE_AUTHOR("Patrick McHardy "); MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Xtables: packet rate estimator"); -MODULE_ALIAS("ipt_RATEEST"); -MODULE_ALIAS("ip6t_RATEEST"); -module_init(xt_rateest_tg_init); -module_exit(xt_rateest_tg_fini); +MODULE_DESCRIPTION("xtables rate estimator match"); +MODULE_ALIAS("ipt_rateest"); +MODULE_ALIAS("ip6t_rateest"); +module_init(xt_rateest_mt_init); +module_exit(xt_rateest_mt_fini); diff --git a/kernel/linux-4.14.83/net/netfilter/xt_TCPMSS.c b/kernel/linux-4.14.83/net/netfilter/xt_TCPMSS.c index 9dae4d665..c53d4d18e 100755 --- a/kernel/linux-4.14.83/net/netfilter/xt_TCPMSS.c +++ b/kernel/linux-4.14.83/net/netfilter/xt_TCPMSS.c @@ -1,353 +1,110 @@ -/* - * This is a module which is used for setting the MSS option in TCP packets. - * - * Copyright (C) 2000 Marc Boucher - * Copyright (C) 2007 Patrick McHardy +/* Kernel module to match TCP MSS values. */ + +/* Copyright (C) 2000 Marc Boucher + * Portions (C) 2005 by Harald Welte * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include -#include -#include -#include -#include -#include -#include -#include -#include #include +#include +#include + #include #include -#include -#include -#include MODULE_LICENSE("GPL"); MODULE_AUTHOR("Marc Boucher "); -MODULE_DESCRIPTION("Xtables: TCP Maximum Segment Size (MSS) adjustment"); -MODULE_ALIAS("ipt_TCPMSS"); -MODULE_ALIAS("ip6t_TCPMSS"); +MODULE_DESCRIPTION("Xtables: TCP MSS match"); +MODULE_ALIAS("ipt_tcpmss"); +MODULE_ALIAS("ip6t_tcpmss"); -static inline unsigned int -optlen(const u_int8_t *opt, unsigned int offset) +static bool +tcpmss_mt(const struct sk_buff *skb, struct xt_action_param *par) { - /* Beware zero-length options: make finite progress */ - if (opt[offset] <= TCPOPT_NOP || opt[offset+1] == 0) - return 1; - else - return opt[offset+1]; -} + const struct xt_tcpmss_match_info *info = par->matchinfo; + const struct tcphdr *th; + struct tcphdr _tcph; + /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */ + const u_int8_t *op; + u8 _opt[15 * 4 - sizeof(_tcph)]; + unsigned int i, optlen; -static u_int32_t tcpmss_reverse_mtu(struct net *net, - const struct sk_buff *skb, - unsigned int family) -{ - struct flowi fl; - const struct nf_afinfo *ai; - struct rtable *rt = NULL; - u_int32_t mtu = ~0U; + /* If we don't have the whole header, drop packet. */ + th = skb_header_pointer(skb, par->thoff, sizeof(_tcph), &_tcph); + if (th == NULL) + goto dropit; - if (family == PF_INET) { - struct flowi4 *fl4 = &fl.u.ip4; - memset(fl4, 0, sizeof(*fl4)); - fl4->daddr = ip_hdr(skb)->saddr; - } else { - struct flowi6 *fl6 = &fl.u.ip6; + /* Malformed. */ + if (th->doff*4 < sizeof(*th)) + goto dropit; - memset(fl6, 0, sizeof(*fl6)); - fl6->daddr = ipv6_hdr(skb)->saddr; - } - ai = nf_get_afinfo(family); - if (ai != NULL) - ai->route(net, (struct dst_entry **)&rt, &fl, false); + optlen = th->doff*4 - sizeof(*th); + if (!optlen) + goto out; - if (rt != NULL) { - mtu = dst_mtu(&rt->dst); - dst_release(&rt->dst); - } - return mtu; -} + /* Truncated options. */ + op = skb_header_pointer(skb, par->thoff + sizeof(*th), optlen, _opt); + if (op == NULL) + goto dropit; -static int -tcpmss_mangle_packet(struct sk_buff *skb, - const struct xt_action_param *par, - unsigned int family, - unsigned int tcphoff, - unsigned int minlen) -{ - const struct xt_tcpmss_info *info = par->targinfo; - struct tcphdr *tcph; - int len, tcp_hdrlen; - unsigned int i; - __be16 oldval; - u16 newmss; - u8 *opt; + for (i = 0; i < optlen; ) { + if (op[i] == TCPOPT_MSS + && (optlen - i) >= TCPOLEN_MSS + && op[i+1] == TCPOLEN_MSS) { + u_int16_t mssval; - /* This is a fragment, no TCP header is available */ - if (par->fragoff != 0) - return 0; + mssval = (op[i+2] << 8) | op[i+3]; - if (!skb_make_writable(skb, skb->len)) - return -1; - - len = skb->len - tcphoff; - if (len < (int)sizeof(struct tcphdr)) - return -1; - - tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); - tcp_hdrlen = tcph->doff * 4; - - if (len < tcp_hdrlen || tcp_hdrlen < sizeof(struct tcphdr)) - return -1; - - if (info->mss == XT_TCPMSS_CLAMP_PMTU) { - struct net *net = xt_net(par); - unsigned int in_mtu = tcpmss_reverse_mtu(net, skb, family); - unsigned int min_mtu = min(dst_mtu(skb_dst(skb)), in_mtu); - - if (min_mtu <= minlen) { - net_err_ratelimited("unknown or invalid path-MTU (%u)\n", - min_mtu); - return -1; - } - newmss = min_mtu - minlen; - } else - newmss = info->mss; - - opt = (u_int8_t *)tcph; - for (i = sizeof(struct tcphdr); i <= tcp_hdrlen - TCPOLEN_MSS; i += optlen(opt, i)) { - if (opt[i] == TCPOPT_MSS && opt[i+1] == TCPOLEN_MSS) { - u_int16_t oldmss; - - oldmss = (opt[i+2] << 8) | opt[i+3]; - - /* Never increase MSS, even when setting it, as - * doing so results in problems for hosts that rely - * on MSS being set correctly. - */ - if (oldmss <= newmss) - return 0; - - opt[i+2] = (newmss & 0xff00) >> 8; - opt[i+3] = newmss & 0x00ff; - - inet_proto_csum_replace2(&tcph->check, skb, - htons(oldmss), htons(newmss), - false); - return 0; + return (mssval >= info->mss_min && + mssval <= info->mss_max) ^ info->invert; } + if (op[i] < 2) + i++; + else + i += op[i+1] ? : 1; } +out: + return info->invert; - /* There is data after the header so the option can't be added - * without moving it, and doing so may make the SYN packet - * itself too large. Accept the packet unmodified instead. - */ - if (len > tcp_hdrlen) - return 0; - - /* tcph->doff has 4 bits, do not wrap it to 0 */ - if (tcp_hdrlen >= 15 * 4) - return 0; - - /* - * MSS Option not found ?! add it.. - */ - if (skb_tailroom(skb) < TCPOLEN_MSS) { - if (pskb_expand_head(skb, 0, - TCPOLEN_MSS - skb_tailroom(skb), - GFP_ATOMIC)) - return -1; - tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); - } - - skb_put(skb, TCPOLEN_MSS); - - /* - * IPv4: RFC 1122 states "If an MSS option is not received at - * connection setup, TCP MUST assume a default send MSS of 536". - * IPv6: RFC 2460 states IPv6 has a minimum MTU of 1280 and a minimum - * length IPv6 header of 60, ergo the default MSS value is 1220 - * Since no MSS was provided, we must use the default values - */ - if (xt_family(par) == NFPROTO_IPV4) - newmss = min(newmss, (u16)536); - else - newmss = min(newmss, (u16)1220); - - opt = (u_int8_t *)tcph + sizeof(struct tcphdr); - memmove(opt + TCPOLEN_MSS, opt, len - sizeof(struct tcphdr)); - - inet_proto_csum_replace2(&tcph->check, skb, - htons(len), htons(len + TCPOLEN_MSS), true); - opt[0] = TCPOPT_MSS; - opt[1] = TCPOLEN_MSS; - opt[2] = (newmss & 0xff00) >> 8; - opt[3] = newmss & 0x00ff; - - inet_proto_csum_replace4(&tcph->check, skb, 0, *((__be32 *)opt), false); - - oldval = ((__be16 *)tcph)[6]; - tcph->doff += TCPOLEN_MSS/4; - inet_proto_csum_replace2(&tcph->check, skb, - oldval, ((__be16 *)tcph)[6], false); - return TCPOLEN_MSS; -} - -static unsigned int -tcpmss_tg4(struct sk_buff *skb, const struct xt_action_param *par) -{ - struct iphdr *iph = ip_hdr(skb); - __be16 newlen; - int ret; - - ret = tcpmss_mangle_packet(skb, par, - PF_INET, - iph->ihl * 4, - sizeof(*iph) + sizeof(struct tcphdr)); - if (ret < 0) - return NF_DROP; - if (ret > 0) { - iph = ip_hdr(skb); - newlen = htons(ntohs(iph->tot_len) + ret); - csum_replace2(&iph->check, iph->tot_len, newlen); - iph->tot_len = newlen; - } - return XT_CONTINUE; -} - -#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) -static unsigned int -tcpmss_tg6(struct sk_buff *skb, const struct xt_action_param *par) -{ - struct ipv6hdr *ipv6h = ipv6_hdr(skb); - u8 nexthdr; - __be16 frag_off, oldlen, newlen; - int tcphoff; - int ret; - - nexthdr = ipv6h->nexthdr; - tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr, &frag_off); - if (tcphoff < 0) - return NF_DROP; - ret = tcpmss_mangle_packet(skb, par, - PF_INET6, - tcphoff, - sizeof(*ipv6h) + sizeof(struct tcphdr)); - if (ret < 0) - return NF_DROP; - if (ret > 0) { - ipv6h = ipv6_hdr(skb); - oldlen = ipv6h->payload_len; - newlen = htons(ntohs(oldlen) + ret); - if (skb->ip_summed == CHECKSUM_COMPLETE) - skb->csum = csum_add(csum_sub(skb->csum, oldlen), - newlen); - ipv6h->payload_len = newlen; - } - return XT_CONTINUE; -} -#endif - -/* Must specify -p tcp --syn */ -static inline bool find_syn_match(const struct xt_entry_match *m) -{ - const struct xt_tcp *tcpinfo = (const struct xt_tcp *)m->data; - - if (strcmp(m->u.kernel.match->name, "tcp") == 0 && - tcpinfo->flg_cmp & TCPHDR_SYN && - !(tcpinfo->invflags & XT_TCP_INV_FLAGS)) - return true; - +dropit: + par->hotdrop = true; return false; } -static int tcpmss_tg4_check(const struct xt_tgchk_param *par) -{ - const struct xt_tcpmss_info *info = par->targinfo; - const struct ipt_entry *e = par->entryinfo; - const struct xt_entry_match *ematch; - - if (info->mss == XT_TCPMSS_CLAMP_PMTU && - (par->hook_mask & ~((1 << NF_INET_FORWARD) | - (1 << NF_INET_LOCAL_OUT) | - (1 << NF_INET_POST_ROUTING))) != 0) { - pr_info("path-MTU clamping only supported in " - "FORWARD, OUTPUT and POSTROUTING hooks\n"); - return -EINVAL; - } - if (par->nft_compat) - return 0; - - xt_ematch_foreach(ematch, e) - if (find_syn_match(ematch)) - return 0; - pr_info("Only works on TCP SYN packets\n"); - return -EINVAL; -} - -#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) -static int tcpmss_tg6_check(const struct xt_tgchk_param *par) -{ - const struct xt_tcpmss_info *info = par->targinfo; - const struct ip6t_entry *e = par->entryinfo; - const struct xt_entry_match *ematch; - - if (info->mss == XT_TCPMSS_CLAMP_PMTU && - (par->hook_mask & ~((1 << NF_INET_FORWARD) | - (1 << NF_INET_LOCAL_OUT) | - (1 << NF_INET_POST_ROUTING))) != 0) { - pr_info("path-MTU clamping only supported in " - "FORWARD, OUTPUT and POSTROUTING hooks\n"); - return -EINVAL; - } - if (par->nft_compat) - return 0; - - xt_ematch_foreach(ematch, e) - if (find_syn_match(ematch)) - return 0; - pr_info("Only works on TCP SYN packets\n"); - return -EINVAL; -} -#endif - -static struct xt_target tcpmss_tg_reg[] __read_mostly = { +static struct xt_match tcpmss_mt_reg[] __read_mostly = { { + .name = "tcpmss", .family = NFPROTO_IPV4, - .name = "TCPMSS", - .checkentry = tcpmss_tg4_check, - .target = tcpmss_tg4, - .targetsize = sizeof(struct xt_tcpmss_info), + .match = tcpmss_mt, + .matchsize = sizeof(struct xt_tcpmss_match_info), .proto = IPPROTO_TCP, .me = THIS_MODULE, }, -#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) { + .name = "tcpmss", .family = NFPROTO_IPV6, - .name = "TCPMSS", - .checkentry = tcpmss_tg6_check, - .target = tcpmss_tg6, - .targetsize = sizeof(struct xt_tcpmss_info), + .match = tcpmss_mt, + .matchsize = sizeof(struct xt_tcpmss_match_info), .proto = IPPROTO_TCP, .me = THIS_MODULE, }, -#endif }; -static int __init tcpmss_tg_init(void) +static int __init tcpmss_mt_init(void) { - return xt_register_targets(tcpmss_tg_reg, ARRAY_SIZE(tcpmss_tg_reg)); + return xt_register_matches(tcpmss_mt_reg, ARRAY_SIZE(tcpmss_mt_reg)); } -static void __exit tcpmss_tg_exit(void) +static void __exit tcpmss_mt_exit(void) { - xt_unregister_targets(tcpmss_tg_reg, ARRAY_SIZE(tcpmss_tg_reg)); + xt_unregister_matches(tcpmss_mt_reg, ARRAY_SIZE(tcpmss_mt_reg)); } -module_init(tcpmss_tg_init); -module_exit(tcpmss_tg_exit); +module_init(tcpmss_mt_init); +module_exit(tcpmss_mt_exit);