├── .gitattributes ├── Makefile ├── Makefile-gcc ├── Makefile-n6 ├── Makefile-rtl819x ├── advconfparse.c ├── advconfparse.h ├── advhash.c ├── advhash.h ├── advkill-conf.sh ├── advkill.c ├── advkill.h ├── advproc.c ├── advproc.h ├── pkgoper.c ├── pkgoper.h ├── readme.txt ├── strcmd.c └── strcmd.h /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Project: advkill 3 | # Author: Aaron 4 | # Time: 20131008 5 | # Compile and run in BoTong router 6 | 7 | RR_MODULE_NAME = adv-kill 8 | RR_MODULE_OBJ = $(RR_MODULE_NAME).o 9 | RR_MODULE_OBJS = advkill.o strcmd.o pkgoper.o advproc.o advhash.o advconfparse.o 10 | PWD = `pwd` 11 | GCC_PATH = /home/botong/hndtools-mipsel-uclibc-4.2.4/bin 12 | 13 | obj-m := $(RR_MODULE_OBJ) 14 | $(RR_MODULE_NAME)-objs := $(RR_MODULE_OBJS) 15 | 16 | KDIR := /home/botong/linux-2.6 17 | 18 | default: 19 | make CC=mipsel-linux-linux26-gcc LD=mipsel-linux-linux26-ld AR=mipsel-linux-linux26-ar RANLIB=mipsel-linux-linux26-ranlib -C $(KDIR) M=$(PWD) modules 20 | 21 | clean: 22 | rm -rf *.ko *.ko.unsigned *.mod.c *.mod.o *.o *.order *.symvers *.markers -------------------------------------------------------------------------------- /Makefile-gcc: -------------------------------------------------------------------------------- 1 | # 2 | # Project: rr 3 | # Author: Aaron 4 | # Time: 20130927 5 | # 6 | 7 | RR_MODULE_NAME = advkill-gcc 8 | RR_MODULE_OBJ = $(RR_MODULE_NAME).o 9 | RR_MODULE_OBJS = advkill.o strcmd.o pkgoper.o advproc.o advhash.o advconfparse.o 10 | 11 | obj-m := $(RR_MODULE_OBJ) 12 | $(RR_MODULE_NAME)-objs := $(RR_MODULE_OBJS) 13 | 14 | KERNELBUILD := /lib/modules/`uname -r`/build 15 | 16 | default: 17 | make -C $(KERNELBUILD) M=$(shell pwd) modules 18 | 19 | clean: 20 | rm -rf *.ko *.ko.unsigned *.mod.c *.mod.o *.o *.order *.symvers *.markers -------------------------------------------------------------------------------- /Makefile-n6: -------------------------------------------------------------------------------- 1 | # 2 | # Project: advkill 3 | # Author: Aaron 4 | # Time: 20130927 5 | # 6 | 7 | RR_MODULE_NAME = advkill-n6 8 | RR_MODULE_OBJ = $(RR_MODULE_NAME).o 9 | RR_MODULE_OBJS = advkill.o strcmd.o pkgoper.o advproc.o advhash.o advconfparse.o 10 | PWD = /home/advkill 11 | 12 | obj-m := $(RR_MODULE_OBJ) 13 | $(RR_MODULE_NAME)-objs := $(RR_MODULE_OBJS) 14 | 15 | KDIR := /home/botong/linux-2.6 16 | 17 | default: 18 | make CC=mipsel-linux-linux26-gcc LD=mipsel-linux-linux26-ld AR=mipsel-linux-linux26-ar RANLIB=mipsel-linux-linux26-ranlib -C $(KDIR) M=$(PWD) modules 19 | 20 | clean: 21 | rm -rf *.ko *.ko.unsigned *.mod.c *.mod.o *.o *.order *.symvers *.markers 22 | 23 | -------------------------------------------------------------------------------- /Makefile-rtl819x: -------------------------------------------------------------------------------- 1 | # 2 | # Project: advkill 3 | # Author: Aaron 4 | # Time: 20130927 5 | # 6 | 7 | RR_MODULE_NAME = advkill-rtl819x 8 | RR_MODULE_OBJ = $(RR_MODULE_NAME).o 9 | RR_MODULE_OBJS = advkill.o strcmd.o pkgoper.o advproc.o advhash.o advconfparse.o 10 | PWD = /home/advkill 11 | 12 | obj-m := $(RR_MODULE_OBJ) 13 | $(RR_MODULE_NAME)-objs := $(RR_MODULE_OBJS) 14 | 15 | KDIR := /home/rtl819x/ 16 | 17 | default: 18 | make CC=rsdk-linux-gcc LD=rsdk-linux-ld AR=rsdk-linux-ar RANLIB=rsdk-linux-ranlib -C $(KDIR) M=$(PWD) modules 19 | 20 | clean: 21 | rm -rf *.ko *.ko.unsigned *.mod.c *.mod.o *.o *.order *.symvers *.markers 22 | 23 | -------------------------------------------------------------------------------- /advconfparse.c: -------------------------------------------------------------------------------- 1 | /** 2 | @file advconfparse.c 3 | @date 2014/07/31 4 | @author WangChunyan 5 | @version 1.0.0 6 | @brief 去广告配置解析接口 7 | 8 | @note 9 | 去广告配置应用中解析用户配置的相关接口 10 | */ 11 | 12 | #include 13 | 14 | #include "advconfparse.h" 15 | #include "advhash.h" 16 | 17 | extern struct mutex g_advconf_mutex; 18 | 19 | #ifdef ADVKILL_CHECK_MEM 20 | extern unsigned long long int g_calloc_times; 21 | extern unsigned long long int g_calloc_size; 22 | extern unsigned long long int g_free_times; 23 | extern unsigned long long int g_free_size; 24 | #endif 25 | 26 | /** 27 | 配置行内容结构体,临时保存配置行中的每一个字段 28 | 29 | */ 30 | struct adv_conf_data 31 | { 32 | char field1; ///< 操作类型 33 | char field2[ADV_CONF_FIELD_2_LEN]; ///< 第二个字段 34 | char field3[ADV_CONF_FIELD_3_LEN]; ///< 第三个字段 35 | char field4[ADV_CONF_FIELD_4_LEN]; ///< 第四个字段 36 | char field5[ADV_CONF_FIELD_5_LEN]; ///< 第五个字段 37 | char field6[ADV_CONF_FIELD_6_LEN]; ///< 第六个字段 38 | }; 39 | 40 | /** 41 | 将输入配置行转换到结构体 adv_conf_data 中 42 | 43 | @param linedata 输入配置行 44 | @param data 配置保存在变量data里 45 | @return 成功返回 ADV_KILL_OK,失败返回 ADV_KILL_FAIL 46 | */ 47 | static int get_advconf_line_data(char *linedata, struct adv_conf_data *data) 48 | { 49 | char *tmpdata = NULL; 50 | int index = 0; 51 | int sepnum = 0; 52 | 53 | EnterFunction(); 54 | if(!linedata || !data) 55 | return ADV_KILL_FAIL; 56 | tmpdata = linedata; 57 | 58 | while (*tmpdata != '\n' && *tmpdata != '\0') 59 | { 60 | if (( *tmpdata == ADV_CONF_DATA_SEPC_CHAR )&&( sepnum<5 )) 61 | { 62 | sepnum++; 63 | index = 0; 64 | tmpdata++; 65 | continue; 66 | } 67 | switch(sepnum) 68 | { 69 | case 0: 70 | data->field1 = (*tmpdata); 71 | break; 72 | case 1: 73 | data->field2[index] = (*tmpdata); 74 | break; 75 | case 2: 76 | data->field3[index] = (*tmpdata); 77 | break; 78 | case 3: 79 | data->field4[index] = (*tmpdata); 80 | break; 81 | case 4: 82 | data->field5[index] = (*tmpdata); 83 | break; 84 | case 5: 85 | data->field6[index] = (*tmpdata); 86 | break; 87 | default: 88 | break; 89 | } 90 | tmpdata++; 91 | index++; 92 | } 93 | LeaveFunction(); 94 | return ADV_KILL_OK; 95 | } 96 | 97 | /** 98 | 解析配置操作标识 99 | 100 | @param oper 操作字段(一个字符) 101 | @return 返回相应的操作类型(枚举值) 102 | */ 103 | static int get_oper_flag(char oper) 104 | { 105 | switch(oper) 106 | { 107 | case ADV_CONF_REDIRECT_PLAYER: 108 | return adv_redirect_player; 109 | case ADV_CONF_DROP_REQUEST: 110 | return adv_drop_request; 111 | case ADV_CONF_MODIFY_URL: 112 | return adv_modify_url; 113 | case ADV_CONF_BAD_GW: 114 | return adv_bad_gw; 115 | case ADV_CONF_FAKE_PACK: 116 | return adv_fake_pack; 117 | default: 118 | return adv_redirect_player; 119 | } 120 | } 121 | 122 | static int parse_str2int(char *str) 123 | { 124 | int number = 0; 125 | sscanf(str, "%d", &number); 126 | return number; 127 | } 128 | 129 | static int get_tag_num_from_tagdata(char *tagdata, int len) 130 | { 131 | char *tmpdata = tagdata; 132 | int i = 0; 133 | int num = 0; 134 | 135 | if(strlen(tmpdata) < 1) 136 | return 0; 137 | 138 | while(imapnum = get_tag_num_from_tagdata(data->field4, strlen(data->field4)); 169 | node->map = (struct advconf_hostmap *)ADVKILL_CALLOC(node->mapnum, sizeof(struct advconf_hostmap)); 170 | if (node->map == NULL) 171 | return ADV_KILL_FAIL; 172 | 173 | tmpsurlbegin = data->field4; 174 | tmpdurlbegin = data->field6; 175 | 176 | for (i=0; imapnum; i++) 177 | { 178 | //surl 179 | tmpsurlend = strchr(tmpsurlbegin, ADV_TAG_SEPARATIR_CHAR); 180 | if (tmpsurlend == NULL) 181 | node->map[i].surllen = strlen(tmpsurlbegin); 182 | else 183 | node->map[i].surllen = (tmpsurlend - tmpsurlbegin); 184 | if (node->map[i].surllen > 0) 185 | { 186 | node->map[i].surl = (char *)ADVKILL_CALLOC(1, node->map[i].surllen+1); 187 | if (node->map[i].surl == NULL) 188 | { 189 | return ADV_KILL_FAIL; 190 | } 191 | memcpy(node->map[i].surl, tmpsurlbegin, node->map[i].surllen); 192 | } 193 | tmpsurlbegin += (node->map[i].surllen + 1); 194 | //durl 195 | tmpdurlend = strchr(tmpdurlbegin, ADV_TAG_SEPARATIR_CHAR); 196 | if (tmpdurlend == NULL) 197 | node->map[i].durllen = strlen(tmpdurlbegin); 198 | else 199 | node->map[i].durllen = (tmpdurlend - tmpdurlbegin); 200 | if (node->map[i].durllen > 0) 201 | { 202 | node->map[i].durl = (char *)ADVKILL_CALLOC(1, node->map[i].durllen+1); 203 | if (node->map[i].durl == NULL) 204 | { 205 | return ADV_KILL_FAIL; 206 | } 207 | memcpy(node->map[i].durl, tmpdurlbegin, node->map[i].durllen); 208 | } 209 | tmpdurlbegin += (node->map[i].durllen + 1); 210 | } 211 | return ADV_KILL_OK; 212 | } 213 | 214 | /** 215 | 解析单条配置,并保存到哈希节点内 216 | 217 | @param data 配置临时结构体 218 | @param node 解析后保存的结构体地址 219 | @return 成功返回 ADV_KILL_OK,失败返回 ADV_KILL_FAIL。 220 | */ 221 | static int parse_advconf_node_from_adv_conf_data(struct adv_conf_data *data, struct advconf_hashnode **node) 222 | { 223 | struct advconf_hashnode *tmpnode = NULL; 224 | 225 | EnterFunction(); 226 | if(!data) 227 | return ADV_KILL_FAIL; 228 | tmpnode = (struct advconf_hashnode *)ADVKILL_CALLOC(1, sizeof(struct advconf_hashnode)); 229 | if(!tmpnode) 230 | return ADV_KILL_FAIL; 231 | //oper flag 232 | tmpnode->type = get_oper_flag(data->field1); 233 | //index 234 | tmpnode->index = parse_str2int(data->field2); 235 | //shost 236 | tmpnode->s_host_len = strlen(data->field3); 237 | tmpnode->s_host = (char *)ADVKILL_CALLOC(1, tmpnode->s_host_len+1); 238 | if (tmpnode->s_host == NULL) 239 | { 240 | goto exit_fail; 241 | } 242 | strcpy(tmpnode->s_host, data->field3); 243 | //dhost 244 | tmpnode->d_host_len = strlen(data->field5); 245 | tmpnode->d_host = (char *)ADVKILL_CALLOC(1, tmpnode->d_host_len+1); 246 | if (tmpnode->d_host == NULL) 247 | { 248 | goto exit_fail; 249 | } 250 | strcpy(tmpnode->d_host, data->field5); 251 | //surl durl 252 | if(tmpnode->type != adv_fake_pack) 253 | { 254 | if (parse_advconf_url(data, tmpnode) != ADV_KILL_OK) 255 | { 256 | goto exit_fail; 257 | } 258 | } else { 259 | tmpnode->mapnum = 1; 260 | tmpnode->map = (struct advconf_hostmap *)ADVKILL_CALLOC(1, sizeof(struct advconf_hostmap)); 261 | tmpnode->map[0].surllen = strlen(data->field4); 262 | tmpnode->map[0].surl = (char *)ADVKILL_CALLOC(1, tmpnode->map[0].surllen+1); 263 | if (tmpnode->map[0].surl == NULL) 264 | { 265 | ADVKILL_FREE(tmpnode->map, sizeof(struct advconf_hostmap)); 266 | return ADV_KILL_FAIL; 267 | } 268 | memcpy(tmpnode->map[0].surl, data->field4, tmpnode->map[0].surllen); 269 | tmpnode->map[0].durllen = strlen(data->field6); 270 | tmpnode->map[0].durl = (char *)ADVKILL_CALLOC(1, tmpnode->map[0].durllen+1); 271 | if (tmpnode->map[0].durl == NULL) 272 | { 273 | ADVKILL_FREE(tmpnode->map[0].surl, tmpnode->map[0].surllen+1); 274 | ADVKILL_FREE(tmpnode->map, sizeof(struct advconf_hostmap)); 275 | return ADV_KILL_FAIL; 276 | } 277 | memcpy(tmpnode->map[0].durl, data->field6, tmpnode->map[0].durllen); 278 | } 279 | *node = tmpnode; 280 | return ADV_KILL_OK; 281 | 282 | exit_fail: 283 | return ADV_KILL_FAIL; 284 | } 285 | 286 | #ifdef ADVKILL_PRINT_DEBUG_INFO 287 | static void print_adv_conf_data(struct adv_conf_data *data) 288 | { 289 | if(!data) 290 | return; 291 | printk(KERN_ALERT "field1[%c],field2[%s],field3[%s],field4[%s],field5[%s],field6[%s]\n\n", 292 | data->field1, data->field2, data->field3, data->field4, data->field5, data->field6); 293 | } 294 | #endif 295 | 296 | /** 297 | 解析一行配置,解析完成后配置存放在结构体 advconf_hashtable 里 298 | 299 | @param linedata 输入配置行 300 | @param table 配置哈希表首地址 301 | @param tablenum 配置哈希表大小 302 | @return 成功返回ADV_KILL_OK,失败返回ADV_KILL_FAIL 303 | */ 304 | int parse_advconf_line_data(char *linedata, struct advconf_hashtable *table, int tablenum) 305 | { 306 | struct advconf_hashnode *advconfnode = NULL; 307 | struct adv_conf_data *data = NULL; 308 | 309 | if(!linedata || !table) 310 | return ADV_KILL_FAIL; 311 | data = (struct adv_conf_data *)ADVKILL_CALLOC(1, sizeof(struct adv_conf_data)); 312 | if (data == NULL) 313 | { 314 | return ADV_KILL_FAIL; 315 | } 316 | get_advconf_line_data(linedata, data); 317 | 318 | #ifdef ADVKILL_PRINT_DEBUG_INFO 319 | print_adv_conf_data(data); 320 | #endif 321 | 322 | if (parse_advconf_node_from_adv_conf_data(data, &advconfnode) != ADV_KILL_OK) 323 | { 324 | ADVKILL_FREE(data, sizeof(struct adv_conf_data)); 325 | data = NULL; 326 | advconf_hashnode_free(advconfnode); 327 | return ADV_KILL_FAIL; 328 | } 329 | 330 | #ifdef ADVKILL_PRINT_DEBUG_INFO 331 | advconf_hashnode_print(advconfnode); 332 | #endif 333 | 334 | ADVKILL_MUTEX_LOCK(&g_advconf_mutex); 335 | advconf_hashnode_add(table, tablenum, advconfnode); 336 | ADVKILL_MUTEX_UNLOCK(&g_advconf_mutex); 337 | 338 | ADVKILL_FREE(data, sizeof(struct adv_conf_data)); 339 | data = NULL; 340 | return ADV_KILL_OK; 341 | } 342 | 343 | -------------------------------------------------------------------------------- /advconfparse.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file advconfparse.h 3 | @date 2014/07/31 4 | @author WangChunyan 5 | @version 1.0.0 6 | @brief 去广告配置解析接口 7 | 8 | @note 9 | 去广告配置应用中解析用户配置的相关接口 10 | */ 11 | #ifndef _ADV_CONF_PARSE_H_ 12 | #define _ADV_CONF_PARSE_H_ 13 | 14 | #include "advkill.h" 15 | 16 | #define ADV_CONF_FIELD_2_LEN 16 17 | #define ADV_CONF_FIELD_3_LEN 128 18 | #define ADV_CONF_FIELD_4_LEN 256 19 | #define ADV_CONF_FIELD_5_LEN 128 20 | #define ADV_CONF_FIELD_6_LEN 256 21 | 22 | #define ADV_CONF_DATA_SEPC_CHAR ' ' 23 | #define ADV_TAG_SEPARATIR_CHAR ',' 24 | #define ADV_CONF_REDIRECT_PLAYER 'R' ///< 重定向模式 302 25 | #define ADV_CONF_DROP_REQUEST 'D' ///< drop模式 404 26 | #define ADV_CONF_MODIFY_URL 'M' ///< 修改源数据包 27 | #define ADV_CONF_BAD_GW 'G' ///< 网关错误 502 28 | #define ADV_CONF_FAKE_PACK 'F' ///< 发送伪造数据包 29 | 30 | /** 31 | 解析一行配置,解析完成后配置存放在结构体 advconf_hashtable 里 32 | 33 | @param linedata 输入配置行 34 | @param table 配置哈希表首地址 35 | @param tablenum 配置哈希表大小 36 | @return 成功返回ADV_KILL_OK,失败返回ADV_KILL_FAIL 37 | */ 38 | int parse_advconf_line_data(char *linedata, struct advconf_hashtable *table, int tablenum); 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /advhash.c: -------------------------------------------------------------------------------- 1 | /** 2 | @file advhash.c 3 | @date 2014/07/31 4 | @author WangChunyan 5 | @version 1.0.0 6 | @brief 配置哈希表相关操作接口 7 | 8 | @note 9 | 哈希表相关操作,包括哈希算法,初始化,节点插入/删除,查找,释放等。 10 | */ 11 | 12 | #include "advhash.h" 13 | #include "strcmd.h" 14 | 15 | #ifdef ADVKILL_CHECK_MEM 16 | extern unsigned long long int g_calloc_times; 17 | extern unsigned long long int g_calloc_size; 18 | extern unsigned long long int g_free_times; 19 | extern unsigned long long int g_free_size; 20 | #endif 21 | 22 | /** 23 | 计算字符串的hash值,返回索引位置 24 | 25 | @param str 输入字符串 26 | @return 返回字符串在哈希表中的索引 27 | */ 28 | unsigned int host_bkdr_hash(unsigned char *str) 29 | { 30 | unsigned int seed = HOST_HASH_SEED; 31 | unsigned int hash = 0; 32 | 33 | while (*str) 34 | { 35 | hash = hash * seed + (*str++); 36 | } 37 | return (hash & HOST_HASH_SIZE_MASK); 38 | } 39 | 40 | /** 41 | 释放URL配置占用的内存空间 42 | 43 | @param map URL配置结构首地址 44 | @param mapnum URL配置个数 45 | */ 46 | void advconf_hostmap_free(struct advconf_hostmap *map, int mapnum) 47 | { 48 | int i = 0; 49 | if (!map || mapnum <=0 ) 50 | return; 51 | for (i=0; is_host != NULL) 77 | { 78 | ADVKILL_FREE(node->s_host, (node->s_host_len+1)); 79 | node->s_host = NULL; 80 | } 81 | if (node->d_host != NULL) 82 | { 83 | ADVKILL_FREE(node->d_host, (node->d_host_len+1)); 84 | node->d_host = NULL; 85 | } 86 | if (node->map != NULL) 87 | { 88 | advconf_hostmap_free(node->map, node->mapnum); 89 | } 90 | ADVKILL_FREE(node, sizeof(struct advconf_hashnode)); 91 | } 92 | 93 | /** 94 | 初始化配置哈希表 95 | 96 | @param table 哈希表首地址需要保存的地址 97 | @param tablenum 哈希表大小 98 | @return 成功返回 ADV_KILL_OK,失败返回 ADV_KILL_FAIL。 99 | */ 100 | int advconf_hashtable_init(struct advconf_hashtable **table, int tablenum) 101 | { 102 | struct advconf_hashtable *tmp = NULL; 103 | int i = 0; 104 | if(tablenum <= 0) 105 | return ADV_KILL_FAIL; 106 | tmp = ADVKILL_CALLOC(tablenum, sizeof(struct advconf_hashtable)); 107 | if(tmp == NULL) 108 | return ADV_KILL_FAIL; 109 | *table = tmp; 110 | 111 | for (i=0; is_host, HOST_EXCEPT_CHAR); 132 | if (tmp != NULL) 133 | { 134 | strncpy(tmphost, node->s_host, tmp - (node->s_host)); 135 | index = host_bkdr_hash(tmphost); 136 | } 137 | else 138 | index = host_bkdr_hash(node->s_host); 139 | 140 | hlist_add_head(&node->node, &table[index].head); 141 | } 142 | 143 | /** 144 | 根据URL从哈希表中查找配置节点 145 | 146 | @param table 配置哈希表首地址 147 | @param tablenum 哈希表大小 148 | @param url 源URL字符串 149 | @return 成功返回 配置项结构体地址,失败返回 NULL。 150 | */ 151 | struct advconf_hashnode * advconf_hashnode_find_by_url(struct advconf_hashtable *table, int tablenum, char *url) 152 | { 153 | struct hlist_node *pos = NULL; 154 | struct hlist_node *n = NULL; 155 | struct advconf_hashnode *info = NULL; 156 | int index = 0; 157 | int i = 0; 158 | 159 | EnterFunction(); 160 | if(!table || !url) 161 | return NULL; 162 | for (index=0; indexmapnum <= 0) 172 | continue; 173 | for (i=0; imapnum; i++) 174 | { 175 | if (strstr(url, info->map[i].surl) != NULL) 176 | { 177 | return info; 178 | } 179 | } 180 | } 181 | } 182 | } 183 | 184 | return NULL; 185 | } 186 | 187 | /** 188 | 根据Host从哈希表中查找配置节点 189 | 190 | @param table 配置哈希表首地址 191 | @param tablenum 哈希表大小 192 | @param host Host名称(字符串) 193 | @param referer HTTP协议中的referer字符串,若配置项中有例外选项,则host不在referer中的配置项才匹配 194 | @return 成功返回 配置项结构体地址,失败返回 NULL。 195 | */ 196 | struct advconf_hashnode * advconf_hashnode_find_by_host(struct advconf_hashtable *table, int tablenum, char *host, char *referer) 197 | { 198 | struct hlist_node *pos = NULL; 199 | struct hlist_node *n = NULL; 200 | struct advconf_hashnode *info = NULL; 201 | int index = 0; 202 | unsigned char *tmp = NULL; 203 | 204 | EnterFunction(); 205 | if(!table || !host) 206 | return NULL; 207 | 208 | index = host_bkdr_hash(host); 209 | if (hlist_empty(&table[index].head)) 210 | return NULL; 211 | 212 | hlist_for_each_safe(pos, n, &table[index].head) 213 | { 214 | if (pos != NULL) 215 | { 216 | info = (struct advconf_hashnode *)pos; 217 | if (referer == NULL) 218 | { 219 | if (strcmp(info->s_host, host) == 0) 220 | { 221 | LeaveFunction(); 222 | return info; 223 | } 224 | } 225 | 226 | tmp = strchr(info->s_host, HOST_EXCEPT_CHAR); 227 | if(tmp != NULL) 228 | { 229 | if (strncmp(info->s_host, host, tmp- (info->s_host)) == 0) 230 | { 231 | if (referer != NULL) 232 | { 233 | tmp++; 234 | if (strstr(referer, tmp) == NULL) 235 | { 236 | LeaveFunction(); 237 | return info; 238 | } 239 | } 240 | } 241 | } 242 | else 243 | { 244 | if (strcmp(info->s_host, host) == 0) 245 | { 246 | LeaveFunction(); 247 | return info; 248 | } 249 | } 250 | 251 | } 252 | } 253 | 254 | return NULL; 255 | } 256 | 257 | /** 258 | 根据Host从哈希表中删除配置节点 259 | 260 | @param table 配置哈希表首地址 261 | @param tablenum 哈希表大小 262 | @param host Host名称(字符串) 263 | @return 成功返回 ADV_KILL_FAIL,失败返回 ADV_KILL_OK。 264 | */ 265 | int advconf_hashnode_del_by_host(struct advconf_hashtable *table, int tablenum, char *host) 266 | { 267 | struct hlist_node *pos = NULL; 268 | struct hlist_node *n = NULL; 269 | struct advconf_hashnode *info = NULL; 270 | int index = 0; 271 | 272 | EnterFunction(); 273 | if(!table || !host) 274 | return ADV_KILL_FAIL; 275 | index = host_bkdr_hash(host); 276 | 277 | if (hlist_empty(&table[index].head)) 278 | return ADV_KILL_FAIL; 279 | hlist_for_each_safe(pos, n, &table[index].head) 280 | { 281 | if (pos != NULL) 282 | { 283 | info = (struct advconf_hashnode *)pos; 284 | if (strcmp(info->s_host, host) == 0) 285 | { 286 | hlist_del(pos); 287 | advconf_hashnode_free(info); 288 | LeaveFunction(); 289 | return ADV_KILL_OK; 290 | } 291 | } 292 | } 293 | 294 | return ADV_KILL_FAIL; 295 | } 296 | 297 | /** 298 | 删除一条哈希链表中的所有配置节点并释放内存 299 | 300 | @param table 配置哈希链表头 301 | */ 302 | void web_conf_data_hashtable_del_all(struct advconf_hashtable *table) 303 | { 304 | struct hlist_node *pos = NULL; 305 | struct hlist_node *n = NULL; 306 | struct advconf_hashnode *info = NULL; 307 | 308 | EnterFunction(); 309 | if(!table) 310 | return; 311 | 312 | if (hlist_empty(&table->head)) 313 | return; 314 | hlist_for_each_safe(pos, n, &table->head) 315 | { 316 | if (pos != NULL) 317 | { 318 | info = (struct advconf_hashnode *)pos; 319 | hlist_del(pos); 320 | advconf_hashnode_free(info); 321 | } 322 | } 323 | } 324 | 325 | /** 326 | 根据URL从哈希配置节点中查找URL配置 327 | 328 | @param node 配置节点地址 329 | @param surl 源URL字符串 330 | @return 成功返回 URL配置地址,失败返回 NULL。 331 | */ 332 | struct advconf_hostmap *advconf_hostmap_find_by_url(struct advconf_hashnode *node, char *surl) 333 | { 334 | int i = 0; 335 | if(!node || !surl || node->mapnum <= 0) 336 | return NULL; 337 | for (i=0; imapnum; i++) 338 | { 339 | if (strstr(surl, node->map[i].surl) != NULL) 340 | { 341 | return &node->map[i]; 342 | } 343 | } 344 | return NULL; 345 | } 346 | 347 | /** 348 | 释放配置哈希表 349 | 350 | @param table 哈希表首地址 351 | @param tablenum 哈希表大小 352 | */ 353 | void advconf_hashtable_release(struct advconf_hashtable *table, int tablenum) 354 | { 355 | int i = 0; 356 | EnterFunction(); 357 | if(!table || tablenum<=0 ) 358 | return; 359 | for (i=0; itype, node->index, node->s_host, node->s_host_len, node->d_host, node->d_host_len, node->mapnum); 395 | for (i=0; imapnum; i++) 396 | { 397 | printk(KERN_ALERT "\t[%d],surl[%s],durl[%s]\n", i, node->map[i].surl, node->map[i].durl); 398 | } 399 | return; 400 | } 401 | 402 | /** 403 | 打印一条哈希链表中所有配置信息 404 | 405 | @param table 配置哈希链表地址 406 | */ 407 | void advconf_hashtable_print(struct advconf_hashtable *table) 408 | { 409 | struct hlist_node *pos = NULL; 410 | struct hlist_node *n = NULL; 411 | struct advconf_hashnode *info = NULL; 412 | 413 | EnterFunction(); 414 | if(!table) 415 | { 416 | printk(KERN_ALERT "hashtable is null\n"); 417 | return; 418 | } 419 | if (hlist_empty(&table->head)) 420 | { 421 | //printk(KERN_ALERT "hashtable is empty\n"); 422 | return; 423 | } 424 | hlist_for_each_safe(pos, n, &table->head) 425 | { 426 | if (pos != NULL) 427 | { 428 | info = (struct advconf_hashnode *)pos; 429 | advconf_hashnode_print(info); 430 | } 431 | } 432 | } 433 | 434 | /** 435 | 根据Host从哈希表中查找配置节点并打印其信息 436 | 437 | @param table 哈希表首地址 438 | @param tablenum 哈希表大小 439 | @param host 要打印的Host字符串 440 | */ 441 | void advconf_hashnode_print_by_host(struct advconf_hashtable *table, int tablenum, char *host) 442 | { 443 | struct hlist_node *pos = NULL; 444 | struct hlist_node *n = NULL; 445 | struct advconf_hashnode *info = NULL; 446 | int index = 0; 447 | 448 | EnterFunction(); 449 | if(!table || !host) 450 | return; 451 | index = host_bkdr_hash(host); 452 | 453 | if (hlist_empty(&table[index].head)) 454 | return; 455 | hlist_for_each_safe(pos, n, &table[index].head) 456 | { 457 | if (pos != NULL) 458 | { 459 | info = (struct advconf_hashnode *)pos; 460 | if (strcmp(info->s_host, host) == 0) 461 | { 462 | advconf_hashnode_print(info); 463 | break; 464 | } 465 | } 466 | } 467 | 468 | return; 469 | } 470 | 471 | /** 472 | 打印配置哈希表中所有配置信息 473 | 474 | @param table 哈希表首地址 475 | @param tablenum 哈希表大小 476 | */ 477 | void advconf_hashtable_print_all(struct advconf_hashtable *table, int tablenum) 478 | { 479 | int i = 0; 480 | EnterFunction(); 481 | if(!table || tablenum<=0 ) 482 | return; 483 | for (i=0; itype = adv_redirect_player; 506 | tmp->index = flag; 507 | //shost 508 | tmp->s_host_len = (strlen(shost)+1); 509 | tmp->s_host = ADVKILL_CALLOC(1, tmp->s_host_len); 510 | if(tmp->s_host == NULL) 511 | goto exit_fail; 512 | snprintf(tmp->s_host, tmp->s_host_len, "%s", shost); 513 | //dhost 514 | tmp->d_host_len = (strlen(dhost)+1); 515 | tmp->d_host = ADVKILL_CALLOC(1, tmp->d_host_len); 516 | if(tmp->d_host == NULL) 517 | goto exit_fail; 518 | snprintf(tmp->d_host, tmp->d_host_len, "%s", dhost); 519 | //host map 520 | tmp->mapnum = mapnum; 521 | if (mapnum > 0) 522 | { 523 | tmp->map = (struct advconf_hostmap *)ADVKILL_CALLOC(mapnum, sizeof(struct advconf_hostmap)); 524 | if (tmp->map == NULL) 525 | { 526 | goto exit_fail; 527 | } 528 | for (i=0; imap[i].surllen = (strlen(surl) + 1); 531 | tmp->map[i].durllen = (strlen(durl) + 1); 532 | tmp->map[i].surl = (char *)ADVKILL_CALLOC(1, tmp->map[i].surllen); 533 | if(tmp->map[i].surl == NULL) 534 | goto exit_fail; 535 | snprintf(tmp->map[i].surl, tmp->map[i].surllen, "%s", surl); 536 | tmp->map[i].durl = (char *)ADVKILL_CALLOC(1, tmp->map[i].durllen); 537 | if(tmp->map[i].durl == NULL) 538 | goto exit_fail; 539 | snprintf(tmp->map[i].durl, tmp->map[i].durllen, "%s", durl); 540 | } 541 | } 542 | 543 | return tmp; 544 | exit_fail: 545 | advconf_hashnode_free(tmp); 546 | return NULL; 547 | } 548 | #endif 549 | -------------------------------------------------------------------------------- /advhash.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file advhash.h 3 | @date 2014/07/31 4 | @author WangChunyan 5 | @version 1.0.0 6 | @brief 配置哈希表相关操作接口 7 | 8 | @note 9 | 哈希表相关操作,包括哈希算法,初始化,节点插入/删除,查找,释放等。 10 | */ 11 | #ifndef _ADV_HASH_H_ 12 | #define _ADV_HASH_H_ 13 | #include "advkill.h" 14 | 15 | #define MAX_HASH_SIZE 0xFFFFFFFF 16 | 17 | #define HOST_HASH_SEED 13 18 | #define HOST_HASH_SIZE_BIT 5 19 | #define HOST_BIT_MOVE (32-HOST_HASH_SIZE_BIT) 20 | #define HOST_HASH_SIZE_MASK (MAX_HASH_SIZE >> HOST_BIT_MOVE) 21 | #define HOST_HASH_SIZE (HOST_HASH_SIZE_MASK+1) ///< 配置哈希表最大个数 22 | 23 | /** 24 | 计算字符串的hash值,返回索引位置 25 | 26 | @param str 输入字符串 27 | @return 返回字符串在哈希表中的索引 28 | */ 29 | unsigned int host_bkdr_hash(unsigned char *str); 30 | 31 | /** 32 | 释放URL配置占用的内存空间 33 | 34 | @param map URL配置结构首地址 35 | @param mapnum URL配置个数 36 | */ 37 | void advconf_hostmap_free(struct advconf_hostmap *map, int mapnum); 38 | 39 | /** 40 | 释放配置哈希节点的内存空间 41 | 42 | @param node 要释放的哈希节点 43 | */ 44 | void advconf_hashnode_free(struct advconf_hashnode *node); 45 | 46 | /** 47 | 添加配置哈希节点到哈希表 48 | 49 | @param table 配置哈希表首地址 50 | @param tablenum 哈希表大小 51 | @param node 要添加的配置结构 52 | */ 53 | void advconf_hashnode_add(struct advconf_hashtable *table, int tablenum, struct advconf_hashnode *node); 54 | 55 | /** 56 | 根据Host从哈希表中删除配置节点 57 | 58 | @param table 配置哈希表首地址 59 | @param tablenum 哈希表大小 60 | @param host Host名称(字符串) 61 | @return 成功返回 ADV_KILL_FAIL,失败返回 ADV_KILL_OK。 62 | */ 63 | int advconf_hashnode_del_by_host(struct advconf_hashtable *table, int tablenum, char *host); 64 | 65 | /** 66 | 根据Host从哈希表中查找配置节点 67 | 68 | @param table 配置哈希表首地址 69 | @param tablenum 哈希表大小 70 | @param host Host名称(字符串) 71 | @param referer HTTP协议中的referer字符串,若配置项中有例外选项,则host不在referer中的配置项才匹配 72 | @return 成功返回 配置项结构体地址,失败返回 NULL。 73 | */ 74 | struct advconf_hashnode * advconf_hashnode_find_by_host(struct advconf_hashtable *table, int tablenum, char *host, char *referer); 75 | 76 | /** 77 | 根据URL从哈希表中查找配置节点 78 | 79 | @param table 配置哈希表首地址 80 | @param tablenum 哈希表大小 81 | @param url 源URL字符串 82 | @return 成功返回 配置项结构体地址,失败返回 NULL。 83 | */ 84 | struct advconf_hashnode * advconf_hashnode_find_by_url(struct advconf_hashtable *table, int tablenum, char *url); 85 | 86 | /** 87 | 删除一条哈希链表中的所有配置节点并释放内存 88 | 89 | @param table 配置哈希链表头 90 | */ 91 | void web_conf_data_hashtable_del_all(struct advconf_hashtable *table); 92 | 93 | /** 94 | 根据URL从哈希配置节点中查找URL配置 95 | 96 | @param node 配置节点地址 97 | @param surl 源URL字符串 98 | @return 成功返回 URL配置地址,失败返回 NULL。 99 | */ 100 | struct advconf_hostmap *advconf_hostmap_find_by_url(struct advconf_hashnode *node, char *surl); 101 | 102 | /** 103 | 初始化配置哈希表 104 | 105 | @param table 哈希表首地址需要保存的地址 106 | @param tablenum 哈希表大小 107 | @return 成功返回 ADV_KILL_OK,失败返回 ADV_KILL_FAIL。 108 | */ 109 | int advconf_hashtable_init(struct advconf_hashtable **table, int tablenum); 110 | 111 | /** 112 | 释放配置哈希表 113 | 114 | @param table 哈希表首地址 115 | @param tablenum 哈希表大小 116 | */ 117 | void advconf_hashtable_release(struct advconf_hashtable *table, int tablenum); 118 | 119 | /** 120 | 清空哈希表中所有配置 121 | 122 | @param table 哈希表首地址 123 | @param tablenum 哈希表大小 124 | */ 125 | void advconf_hashtable_empty(struct advconf_hashtable *table, int tablenum); 126 | 127 | /** 128 | 打印配置项内所有信息(用于调试) 129 | 130 | @param node 配置节点地址 131 | */ 132 | void advconf_hashnode_print(struct advconf_hashnode *node); 133 | 134 | /** 135 | 根据Host从哈希表中查找配置节点并打印其信息 136 | 137 | @param table 哈希表首地址 138 | @param tablenum 哈希表大小 139 | @param host 要打印的Host字符串 140 | */ 141 | void advconf_hashnode_print_by_host(struct advconf_hashtable *table, int tablenum, char *host); 142 | 143 | /** 144 | 打印一条哈希链表中所有配置信息 145 | 146 | @param table 配置哈希链表地址 147 | */ 148 | void advconf_hashtable_print(struct advconf_hashtable *table); 149 | 150 | /** 151 | 打印配置哈希表中所有配置信息 152 | 153 | @param table 哈希表首地址 154 | @param tablenum 哈希表大小 155 | */ 156 | void advconf_hashtable_print_all(struct advconf_hashtable *table, int tablenum); 157 | 158 | #ifdef ADVKILL_PRINT_DEBUG_INFO 159 | struct advconf_hashnode *advconf_hashnode_generate(int flag, int mapnum); 160 | #endif 161 | #endif 162 | -------------------------------------------------------------------------------- /advkill-conf.sh: -------------------------------------------------------------------------------- 1 | #youku tudou 2 | #echo "R 2 static.youku.com loader.swf 192.168.1.118 /loader.swf">/proc/advkill/advconf 3 | #echo "R 5 js.tudouui.com /bin/lingtong/PortalPlayer_56.swf 192.168.1.118 /tudou.swf">/proc/advkill/advconf 4 | echo "D 10 valf.atm.youku.com /vf? valf.atm.youku.com a" > /proc/advkill/advconf 5 | echo "D 11 ad.api.3g.youku.com /adv? ad.api.3g.youku.com a" > /proc/advkill/advconf 6 | echo "D 12 mf.atm.youku.com /mf? mf.atm.youku.com a" > /proc/advkill/advconf 7 | #echo "D 13 pl.youku.com ids= pl.youku.com a" > /proc/advkill/advconf 8 | echo "D 14 valo.atm.youku.com /vo? valo.atm.youku.com a" > /proc/advkill/advconf 9 | echo "D 15 f.youku.com /flv/ f.youku.com a" > /proc/advkill/advconf 10 | echo "D 16 ad.api.3g.tudou.com /adv? ad.api.3g.tudou.com a" > /proc/advkill/advconf 11 | #youku pad 12 | #echo "D 13 123.129.231.12 .flv.ts?,.flv?,.FLV? 123.129.231.12 a,b,c" > /proc/advkill/advconf 13 | #echo "D 14 119.167.152.22 .flv.ts?,.flv?,.FLV? 123.129.231.12 a,b,c" > /proc/advkill/advconf 14 | #echo "D 14 27.221.31.202 .flv.ts?,.flv?,.FLV? 123.129.231.12 a,b,c" > /proc/advkill/advconf 15 | #echo "D 14 61.55.189.49 .flv.ts?,.flv?,.FLV? 123.129.231.12 a,b,c" > /proc/advkill/advconf 16 | #echo "D 14 182.118.6.112 .flv.ts?,.flv?,.FLV? 123.129.231.12 a,b,c" > /proc/advkill/advconf 17 | #echo "D 14 119.188.38.184 .flv.ts?,.flv?,.FLV? 123.129.231.12 a,b,c" > /proc/advkill/advconf 18 | #echo "D 14 182.118.58.17 .flv.ts?,.flv?,.FLV? 123.129.231.12 a,b,c" > /proc/advkill/advconf 19 | #echo "D 14 61.158.246.22 .flv.ts?,.flv?,.FLV? 123.129.231.12 a,b,c" > /proc/advkill/advconf 20 | #echo "D 14 119.188.38.184 .flv.ts?,.flv?,.FLV? 123.129.231.12 a,b,c" > /proc/advkill/advconf 21 | #echo "D 14 119.188.38.73 .flv.ts?,.flv?,.FLV? 123.129.231.12 a,b,c" > /proc/advkill/advconf 22 | #echo "D 14 61.158.246.44 .flv.ts?,.flv?,.FLV? 123.129.231.12 a,b,c" > /proc/advkill/advconf 23 | #echo "D 14 27.221.23.131 .flv.ts?,.flv?,.FLV? 123.129.231.12 a,b,c" > /proc/advkill/advconf 24 | #echo "D 14 27.221.23.132 .flv.ts?,.flv?,.FLV? 123.129.231.12 a,b,c" > /proc/advkill/advconf 25 | #echo "D 14 182.118.6.15 .flv.ts?,.flv?,.FLV? 123.129.231.12 a,b,c" > /proc/advkill/advconf 26 | #echo "D 14 27.221.18.174 .flv.ts?,.flv?,.FLV? 123.129.231.12 a,b,c" > /proc/advkill/advconf 27 | #echo "D 14 61.55.189.22 .flv.ts?,.flv?,.FLV? 123.129.231.12 a,b,c" > /proc/advkill/advconf 28 | #echo "D 14 119.167.152.19 .flv.ts?,.flv?,.FLV? 123.129.231.12 a,b,c" > /proc/advkill/advconf 29 | 30 | #letv 31 | #echo "R 4 player.letvcdn.com /LetvPlayer.swf 192.168.1.118 /letv.swf">/proc/advkill/advconf 32 | #echo "D 20 pro.hoye.letv.com /main/s? pro.hoye.letv.com a" > /proc/advkill/advconf 33 | #echo "D 21 ark.letv.com /s? ark.letv.com !cis=" > /proc/advkill/advconf 34 | #echo "D 22 dc.letv.com /vq/ac? dc.letv.com a" > /proc/advkill/advconf 35 | #echo "D 23 g3.letv.cn /vod/v1/ g3.letv.cn a" > /proc/advkill/advconf 36 | #echo "D 24 g3.letv.com .flv? g3.letv.com a" > /proc/advkill/advconf 37 | echo "D 25 dc.letv.com / dc.letv.com a" > /proc/advkill/advconf 38 | echo "M 26 ark.letv.com ark= ark.letv.com 02" > /proc/advkill/advconf 39 | 40 | #ku6 41 | #echo "R 7 player.ku6cdn.com /default/juchang/swf/201205291326/player.swf 192.168.1.118 /ku6.swf">/proc/advkill/advconf 42 | #echo "D 30 pic.snyu.com .flv,.FLV,.swf pic.snyu.com a,b,c" > /proc/advkill/advconf 43 | #echo "D 31 static.acs86.com .flv,.FLV,.swf static.acs86.com a,b,c" > /proc/advkill/advconf 44 | #echo "D 32 g.aa.sdo.com /?sdk= g.aa.sdo.com a" > /proc/advkill/advconf 45 | #echo "D 33 g1.sdo.com /?method= g1.sdo.com a" > /proc/advkill/advconf 46 | #echo "D 35 abc1.sdo.com .flv abc1.sdo.com a" > /proc/advkill/advconf 47 | #echo "D 38 dwtracking.sdo.com /ku6.gif? dwtracking.sdo.com 0" > /proc/advkill/advconf 48 | #echo "D 39 st.vq.ku6.cn /start? st.vq.ku6.cn a" > /proc/advkill/advconf 49 | echo "R 36 player.ku6cdn.com v.swf adtchrome.qiniudn.com /ku6_20140420.swf">/proc/advkill/advconf 50 | #echo "D 36 s.x.cn.miaozhen.com /ax? s.x.cn.miaozhen.com a">/proc/advkill/advconf 51 | #echo "D 37 g1.sdo.com /? g1.sdo.com a">/proc/advkill/advconf 52 | #echo "D 38 ku6im.allyes.com /main/s? ku6im.allyes.com a">/proc/advkill/advconf 53 | 54 | #tencent 55 | echo "D 40 livew.l.qq.com /livemsg? livew.l.qq.com a" > /proc/advkill/advconf 56 | echo "D 41 adslvfile.qq.com .flv,.FLV adslvfile.qq.com a,b" > /proc/advkill/advconf 57 | echo "D 42 vv.video.qq.com /getmind? vv.video.qq.com a" > /proc/advkill/advconf 58 | echo "D 43 livec.l.qq.com /livemsg? livec.l.qq.com a" > /proc/advkill/advconf 59 | echo "D 44 livep.l.qq.com /livemsg? livew.l.qq.com a" > /proc/advkill/advconf 60 | echo "D 45 lives.l.qq.com /livemsg? lives.l.qq.com a" > /proc/advkill/advconf 61 | echo "D 46 vv.video.qq.com /getvmind? vv.video.qq.com a" > /proc/advkill/advconf 62 | 63 | #xunlei 64 | #echo "D 50 *.float.sandai.net .flv,.FLV float.sandai.net a,b" > /proc/advkill/advconf 65 | #echo "D 51 logic.cpm.cm.sandai.net /adlistrequest? logic.cpm.cm.sandai.net a" > /proc/advkill/advconf 66 | echo "D 52 *.logic.cpm.cm.sandai.net /adlistrequest? cpm.cm.sandai.net a" > /proc/advkill/advconf 67 | #echo "D 53 *.logic.cpm.cm.sandai.net /adrequest? logic.cpm.cm.sandai.net a" > /proc/advkill/advconf 68 | #echo "D 54 float.sandai.net .flv,.FLV float.sandai.net a,b" > /proc/advkill/advconf 69 | 70 | #sohu 71 | #echo "D 60 mfiles.sohu.com .mp4 mfiles.sohu.com a" > /proc/advkill/advconf 72 | #echo "D 61 images.sohu.com .mp4 images.sohu.com a" > /proc/advkill/advconf 73 | #echo "D 62 f.aty.sohu.com /f? f.aty.sohu.com a" > /proc/advkill/advconf 74 | #echo "D 63 v.aty.sohu.com /v? v.aty.sohu.com a" > /proc/advkill/advconf 75 | echo "G 62 v.aty.sohu.com /v? v.aty.sohu.com a" > /proc/advkill/advconf 76 | echo "D 63 m.aty.sohu.com /m? m.aty.sohu.com a" > /proc/advkill/advconf 77 | 78 | #56 79 | echo "D 70 cdn1.56imgs.com .flv cdn1.56imgs.com a" > /proc/advkill/advconf 80 | echo "D 71 a.hpg.cn.miaozhen.com /a.gif? a.hpg.cn.miaozhen.com a" > /proc/advkill/advconf 81 | echo "D 72 mad.stat.v-56.com /api.ad_ mad.stat.v-56.com a" > /proc/advkill/advconf 82 | 83 | #iqiyi,pps 84 | #echo "D 82 api.cupid.qiyi.com /api? api.cupid.qiyi.com a" > /proc/advkill/advconf 85 | #echo "D 83 mixer.cupid.iqiyi.com /mixer? mixer.cupid.iqiyi.com a" > /proc/advkill/advconf 86 | #echo "D 80 cpro.baidu.com / cpro.baidu.com a" > /proc/advkill/advconf 87 | #echo "D 81 drmcmm.baidu.com / drmcmm.baidu.com a" > /proc/advkill/advconf 88 | #echo "D 82 duiwai.baidu.com / duiwai.baidu.com a" > /proc/advkill/advconf 89 | #echo "D 83 eiv.baidu.com / eiv.baidu.com a" > /proc/advkill/advconf 90 | #echo "D 84 spcode.baidu.com / spcode.baidu.com a" > /proc/advkill/advconf 91 | #echo "D 85 msg.iqiyi.com / msg.iqiyi.com a" > /proc/advkill/advconf 92 | #echo "D 86 jsmsg.video.qiyi.com / jsmsg.video.qiyi.com a" > /proc/advkill/advconf 93 | #echo "D 87 msg.video.qiyi.com / msg.video.qiyi.com a" > /proc/advkill/advconf 94 | #echo "D 88 afp.qiyi.com / afp.qiyi.com a" > /proc/advkill/advconf 95 | #echo "M 89 policy.cupid.qiyi.com a= policy.cupid.qiyi.com qc_100000_100000" > /proc/advkill/advconf 96 | ### here comment it 97 | #echo "D 80 msg.video.qiyi.com /adpb.gif? msg.video.qiyi.com a" > /proc/advkill/advconf 98 | #echo "D 81 msg.video.qiyi.com /cfp.gif? msg.video.qiyi.com a" > /proc/advkill/advconf 99 | #echo "R 82 www.iqiyi.com!.pps.tv/ /Player.swf adtchrome.qiniudn.com /iqiyi_20140525.swf">/proc/advkill/advconf 100 | #echo "D 83 cache.video.qiyi.com /mad/ cache.video.qiyi.com a" > /proc/advkill/advconf 101 | #echo "D 84 cache.video.qiyi.com /p2p/ cache.video.qiyi.com a" > /proc/advkill/advconf 102 | #echo "D 85 data.video.iqiyi.com /other/ data.video.iqiyi.com a" > /proc/advkill/advconf 103 | echo "D 86 data.video.qiyi.com vid= data.video.iqiyi.com a" > /proc/advkill/advconf 104 | #echo "D 87 msg2.video.qiyi.com /adPingBacks msg2.video.qiyi.com a" > /proc/advkill/advconf 105 | 106 | #PPTV 107 | echo "D 90 asimgs.pplive.cn .flv,.FLV,.swf asimgs.pplive.cn a,b,c" > /proc/advkill/advconf 108 | echo "D 91 de.as.pptv.com /3.0draft?,3.0draft/?,/webdelivery/webafp? de.as.pptv.com a,b,c" > /proc/advkill/advconf 109 | 110 | #CNTV 111 | echo "D 100 v.cctv.com .mp4,.MP4 v.cctv.com a,b" > /proc/advkill/advconf 112 | 113 | #ji dong wang 114 | echo "D 110 86mms.megajoy.com .flv,jpg,JPG 86mms.megajoy.com a,b,c">/proc/advkill/advconf 115 | echo "D 111 86get.maxduo.com /providerv.ashx 86get.maxduo.com a">/proc/advkill/advconf 116 | echo "D 112 pic.snyu.com .flv,.swf pic.snyu.com a,b">/proc/advkill/advconf 117 | 118 | #feng xing wang 119 | echo "D 120 pub.funshion.com /interface/deliver? pub.funshion.com a">/proc/advkill/advconf 120 | echo "D 121 adm.funshion.com .flv adm.funshion.com a">/proc/advkill/advconf 121 | 122 | #m1905 123 | #echo "D 130 afp.m1905.com .flv afp.m1905.com a">/proc/advkill/advconf 124 | echo "D 131 afp.acs86.com /a.htm? afp.acs86.com a">/proc/advkill/advconf 125 | 126 | #www.v1.cn 127 | #echo "D 140 luck.v1.cn /adxml.php? luck.v1.cn a">/proc/advkill/advconf 128 | echo "D 141 luck.v1.cn /adxml.php? luck.v1.cn !stype=text" > /proc/advkill/advconf 129 | 130 | #www.tangdou.com 131 | echo "D 150 s.x.cn.miaozhen.com /ax? s.x.cn.miaozhen.com a">/proc/advkill/advconf 132 | echo "D 151 cb.baidu.com /ecom? cb.baidu.com a" > /proc/advkill/advconf 133 | echo "D 152 pos.baidu.com /ecom? pos.baidu.com a" > /proc/advkill/advconf 134 | echo "D 153 cpro.baidu.com /uijs.php? cpro.baidu.com a" > /proc/advkill/advconf 135 | 136 | #www.imgo.tv 137 | #echo "D 160 acs86.com /a.htm? acs86.com a">/proc/advkill/advconf 138 | echo "D 161 static.acs86.com .flv static.acs86.com a">/proc/advkill/advconf 139 | echo "D 162 res.hunantv.com .flv res.hunantv.com a">/proc/advkill/advconf 140 | 141 | #movie.wasu.cn 142 | echo "D 170 p.37youyou.com .swf p.37youyou.com a">/proc/advkill/advconf 143 | 144 | #baofeng 145 | echo "D 180 xs.houyi.baofeng.net /Consultation/index.php? xs.houyi.baofeng.net a">/proc/advkill/advconf 146 | 147 | #v.ifeng.com 148 | echo "D 190 pubads.g.doubleclick.net /adx? pubads.g.doubleclick.net a">/proc/advkill/advconf 149 | 150 | #video.sina.com.cn 151 | echo "D 200 sax.sina.com.cn /video/impress? sax.sina.com.cn a">/proc/advkill/advconf 152 | echo "D 201 v-sence.gentags.net /www/delivery/pcvdo.php? v-sence.gentags.net a">/proc/advkill/advconf 153 | echo "D 202 sax.sina.com.cn /video/newimpress? sax.sina.com.cn a">/proc/advkill/advconf 154 | 155 | #pps 156 | #echo "D 210 show.cupid.qiyi.com /show2 show.cupid.qiyi.com a" > /proc/advkill/advconf 157 | #echo "D 211 data.video.iqiyi.com /videos/other/ data.video.qiyi.com a" > /proc/advkill/advconf 158 | #echo "D 212 data.video.qiyi.com /videos/other/ data.video.iyi.com a" > /proc/advkill/advconf 159 | 160 | #woxiu 161 | echo "D 220 www.woxiu.com /get_pre_config.php www.woxiu.com a" > /proc/advkill/advconf -------------------------------------------------------------------------------- /advkill.c: -------------------------------------------------------------------------------- 1 | /** 2 | @file advkill.c 3 | @date 2014/07/31 4 | @author WangChunyan 5 | @version 1.0.0 6 | @brief 去广告应用中的主控文件 7 | 8 | @note 9 | 去广告应用主控文件,主要流程加载内核模块,注册netfilter钩子函数, 10 | 抓取数据包并根据预配置规则进行匹配,若匹配到再根据预配置规则进行 11 | 一系列预定义操作。 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include //wake_up_process() 31 | #include 32 | 33 | #include "advkill.h" 34 | #include "strcmd.h" 35 | #include "pkgoper.h" 36 | #include "advproc.h" 37 | #include "advhash.h" 38 | 39 | /** 40 | 内核模块声明 41 | */ 42 | MODULE_LICENSE("GPL"); 43 | MODULE_AUTHOR("Aaron"); 44 | MODULE_DESCRIPTION("Aaron's project kill advertisement"); 45 | MODULE_VERSION("1.0"); 46 | 47 | /* advertisement config */ 48 | struct advconf_hashtable *g_advconf_hashtable = NULL; ///< 去广告配置全局变量,为配置哈希表首地址 49 | struct mutex g_advconf_mutex; ///< 全局互斥变量,防止在程序运行中动态修改配置引起冲突 50 | 51 | static char *g_location = NULL; ///< 全局变量,暂时保存HTTP请求中的location内容 52 | static char *g_shost = NULL; ///< 全局变量,暂时保存HTTP请求中的Host内容 53 | static char *g_referer = NULL; ///< 全局变量,暂时保存HTTP请求中的Referer字段 54 | static char *g_surl = NULL; ///< 全局变量,暂时保存HTTP请求中的URL内容 55 | //static unsigned long long g_adv_num = 0; 56 | 57 | #ifdef ADVKILL_CHECK_MEM 58 | unsigned long long int g_calloc_times = 0; 59 | unsigned long long int g_calloc_size = 0; 60 | unsigned long long int g_free_times = 0; 61 | unsigned long long int g_free_size = 0; 62 | #endif 63 | 64 | /** 65 | 初始化全局参数 66 | 67 | 主要为全局变量申请空间,以便避免每次使用都申请/释放空间,减少内存操作。 68 | */ 69 | int global_parameter_init(void) 70 | { 71 | g_location = (char *)ADVKILL_CALLOC(1, ADV_MAX_LOCATION_LEN); 72 | if (g_location == NULL) 73 | return ADV_KILL_FAIL; 74 | g_shost = (char *)ADVKILL_CALLOC(1, ADV_MAX_SHOST_LEN); 75 | if (g_shost == NULL) 76 | { 77 | ADVKILL_FREE(g_location, ADV_MAX_LOCATION_LEN); 78 | g_location = NULL; 79 | return ADV_KILL_FAIL; 80 | } 81 | 82 | g_referer = (char *)ADVKILL_CALLOC(1, ADV_MAX_REFERER_LEN); 83 | if (g_referer == NULL) 84 | { 85 | ADVKILL_FREE(g_location, ADV_MAX_LOCATION_LEN); 86 | g_location = NULL; 87 | ADVKILL_FREE(g_shost, ADV_MAX_SHOST_LEN); 88 | g_shost = NULL; 89 | return ADV_KILL_FAIL; 90 | } 91 | 92 | g_surl = (char *)ADVKILL_CALLOC(1, ADV_MAX_SURL_LEN); 93 | if (g_surl == NULL) 94 | { 95 | ADVKILL_FREE(g_location, ADV_MAX_LOCATION_LEN); 96 | g_location = NULL; 97 | ADVKILL_FREE(g_shost, ADV_MAX_SHOST_LEN); 98 | g_shost = NULL; 99 | ADVKILL_FREE(g_referer, ADV_MAX_REFERER_LEN); 100 | g_referer = NULL; 101 | return ADV_KILL_FAIL; 102 | } 103 | 104 | return ADV_KILL_OK; 105 | } 106 | 107 | /** 108 | 释放全局变量占用内存空间 109 | 110 | 程序退出时,释放所有变量的内存空间。 111 | */ 112 | void global_parameter_destroy(void) 113 | { 114 | if (g_location != NULL) 115 | { 116 | ADVKILL_FREE(g_location, ADV_MAX_LOCATION_LEN); 117 | g_location = NULL; 118 | } 119 | if (g_shost != NULL) 120 | { 121 | ADVKILL_FREE(g_shost, ADV_MAX_SHOST_LEN); 122 | g_shost = NULL; 123 | } 124 | if(g_referer != NULL) 125 | { 126 | ADVKILL_FREE(g_referer, ADV_MAX_REFERER_LEN); 127 | g_referer = NULL; 128 | } 129 | if (g_surl != NULL) 130 | { 131 | ADVKILL_FREE(g_surl, ADV_MAX_SURL_LEN); 132 | g_surl = NULL; 133 | } 134 | } 135 | 136 | /** 137 | 程序启动业务操作前的准备工作 138 | 139 | 包括初始化全局变量,申请内存空间,创建proc文件系统,初始化配置哈希表。 140 | */ 141 | int advkill_prepare(void) 142 | { 143 | int ret = ADV_KILL_OK; 144 | 145 | mutex_init(&g_advconf_mutex); 146 | ret = global_parameter_init(); 147 | if (ret != ADV_KILL_OK) 148 | { 149 | ADV_PRINT_ERROR("global_parameter_init failed"); 150 | return ADV_KILL_FAIL; 151 | } 152 | ret = create_proc_file(); 153 | if(ret != ADV_KILL_OK) 154 | { 155 | ADV_PRINT_ERROR("create_proc_file failed"); 156 | return ADV_KILL_FAIL; 157 | } 158 | ret = advconf_hashtable_init(&g_advconf_hashtable, HOST_HASH_SIZE); 159 | if (ret != ADV_KILL_OK) 160 | { 161 | ADV_PRINT_ERROR("advconf_hashtable_init failed"); 162 | return ADV_KILL_FAIL; 163 | } 164 | return ret; 165 | } 166 | 167 | /** 168 | 程序退出前的操作 169 | 170 | 包括删除proc文件系统,释放全局哈希表(配置),释放全局变量的。 171 | */ 172 | void advkill_finish(void) 173 | { 174 | destroy_proc_file(); 175 | advconf_hashtable_release(g_advconf_hashtable, HOST_HASH_SIZE); 176 | global_parameter_destroy(); 177 | mutex_destroy(&g_advconf_mutex); 178 | } 179 | 180 | /** 181 | netfilter注册钩子函数,函数原型为内核确定 182 | 183 | 在该钩子函数内进行去广告业务处理。 184 | */ 185 | #if (LINUX_VERSION_CODE < KERNEL_VERSION (3, 13, 0)) 186 | unsigned int hook_func( unsigned int hooknum, 187 | struct sk_buff **skb, 188 | const struct net_device *in, 189 | const struct net_device *out, 190 | int (*okfn)(struct sk_buff *) 191 | ) 192 | #else 193 | unsigned int hook_func(const struct nf_hook_ops *ops, 194 | struct sk_buff *skb, 195 | const struct net_device *in, 196 | const struct net_device *out, 197 | int (*okfn)(struct sk_buff *)) 198 | #endif 199 | { 200 | struct iphdr *iph = NULL; 201 | struct tcphdr *tcph = NULL; 202 | #if (LINUX_VERSION_CODE < KERNEL_VERSION (3, 13, 0)) 203 | struct sk_buff *sb = *skb; 204 | #else 205 | struct sk_buff *sb = skb; 206 | #endif 207 | char *httpcontent = NULL; 208 | int httpcontentlen = 0; 209 | char *shost = NULL; 210 | char *referer = NULL; 211 | int refererlen = 0; 212 | int shostlen = 0; 213 | char *surl = NULL; 214 | int surllen = 0; 215 | int ret = ADV_KILL_OK; 216 | struct advconf_hashnode *tmphost = NULL; 217 | struct advconf_hostmap *tmpmap = NULL; 218 | int skbuffoper = 0; 219 | char *urlflagpos = NULL; 220 | int i = 0; 221 | //for temp domain,eg: *.logic.cpm.cm.sandai.net 222 | char *tmpdomain = NULL; 223 | 224 | //printk(KERN_INFO "----begin enter hook function--\n\n"); 225 | /* is not ip protocol, return accept */ 226 | iph = ip_hdr(sb); 227 | if (iph == NULL) 228 | { 229 | goto exit_no_cmd; 230 | } 231 | //printk(KERN_INFO "sip[%08x],dip[%08x],proto[%d]\n", iph->saddr, iph->daddr, iph->protocol); 232 | /* is not tcp protocol,return accept */ 233 | if(iph->protocol != IPPROTO_TCP) 234 | { 235 | goto exit_no_cmd; 236 | } 237 | /* find tcp header and tcp data len */ 238 | tcph = (struct tcphdr *) ((unsigned char *)iph + (iph->ihl * 4)); 239 | if (0 != skb_linearize(sb)) 240 | { 241 | goto exit_no_cmd; 242 | } 243 | //printk(KERN_INFO "tcp sport[%d],dport[%d]\n", tcph->source, tcph->dest); 244 | httpcontentlen = (ntohs(iph->tot_len) - iph->ihl*4 - tcph->doff*4); 245 | if (httpcontentlen <= HTTP_MIN_LEN) 246 | { 247 | //printk(KERN_INFO "http content len[%d]\n", httpcontentlen); 248 | goto exit_no_cmd; 249 | } 250 | 251 | httpcontent = (char *) ((unsigned char *)tcph + tcph->doff*4); 252 | /*if (strncmp(httpcontent, HTTP_METHOD_FLAG, HTTP_METHOD_FLAG_LEN) != 0) 253 | { 254 | goto exit_no_cmd; 255 | }*/ 256 | memset(g_shost, 0, ADV_MAX_SHOST_LEN); 257 | shost = get_http_field(httpcontent, httpcontentlen, HTTP_HOST_FLAG, HTTP_HOST_FLAG_LEN, g_shost, ADV_MAX_SHOST_LEN, &shostlen); 258 | if (shost == NULL) 259 | { 260 | goto exit_no_cmd; 261 | } 262 | 263 | memset(g_surl, 0, ADV_MAX_SURL_LEN); 264 | surl = get_http_get_url(httpcontent, httpcontentlen, g_surl, ADV_MAX_SURL_LEN, &surllen); 265 | if (surl == NULL) 266 | { 267 | goto exit_no_cmd; 268 | } 269 | 270 | memset(g_referer, 0, ADV_MAX_REFERER_LEN); 271 | referer = get_http_field(httpcontent, httpcontentlen, HTTP_REFERER_FLAG, HTTP_REFERER_FLAG_LEN, g_referer, ADV_MAX_REFERER_LEN, &refererlen); 272 | if (refererlen == 0) 273 | { 274 | referer = NULL; 275 | } 276 | 277 | //printk(KERN_ALERT "surl[%s]\n", surl); 278 | #if 0 279 | /* check host is digit or not,eg:192.168.1.1 */ 280 | if (is_digit_host(shost) == ADV_KILL_OK) 281 | { 282 | ADVKILL_MUTEX_LOCK(&g_advconf_mutex); 283 | tmphost = advconf_hashnode_find_by_url(g_advconf_hashtable, HOST_HASH_SIZE, surl); 284 | if (tmphost == NULL) 285 | { 286 | ADVKILL_MUTEX_UNLOCK(&g_advconf_mutex); 287 | goto exit_no_cmd; 288 | } 289 | //g_adv_num++; 290 | //printk(KERN_ALERT "find digit host\n"); 291 | //if (g_adv_num % 4 == 1) 292 | goto find_url; 293 | /*else 294 | { 295 | send_client_notfound(sb); 296 | skbuffoper = 1; 297 | ADVKILL_MUTEX_UNLOCK(&g_advconf_mutex); 298 | goto exit_free; 299 | }*/ 300 | } 301 | #endif 302 | 303 | /* check domain is contain date or not,eg: 20131223.logic.cpm.cm.sandai.net */ 304 | if (domain_contain_digits(shost, XUNLEI_KANKAN_DOMAIN_DIGIT_NUM) == ADV_KILL_OK) 305 | { 306 | tmpdomain = domain_regroup_match_mode(shost, XUNLEI_KANKAN_DOMAIN_DIGIT_INDEX); 307 | if (tmpdomain != NULL) 308 | { 309 | ADVKILL_MUTEX_LOCK(&g_advconf_mutex); 310 | tmphost = advconf_hashnode_find_by_host(g_advconf_hashtable, HOST_HASH_SIZE, tmpdomain, referer); 311 | if (tmphost == NULL) 312 | { 313 | ADVKILL_MUTEX_UNLOCK(&g_advconf_mutex); 314 | goto exit_no_cmd; 315 | } 316 | goto find_url; 317 | } 318 | } 319 | 320 | ADVKILL_MUTEX_LOCK(&g_advconf_mutex); 321 | tmphost = advconf_hashnode_find_by_host(g_advconf_hashtable, HOST_HASH_SIZE, shost, referer); 322 | if (tmphost == NULL) 323 | { 324 | ADVKILL_MUTEX_UNLOCK(&g_advconf_mutex); 325 | goto exit_no_cmd; 326 | } 327 | 328 | #ifdef ADVKILL_PRINT_DEBUG_INFO 329 | printk(KERN_ALERT "find shost:[%s],surl[%s]\n", shost, surl); 330 | #endif 331 | 332 | find_url: 333 | tmpmap = advconf_hostmap_find_by_url(tmphost, surl); 334 | if (tmpmap == NULL) 335 | { 336 | ADVKILL_MUTEX_UNLOCK(&g_advconf_mutex); 337 | goto exit_no_cmd; 338 | } 339 | 340 | #ifdef ADVKILL_PRINT_DEBUG_INFO 341 | printk(KERN_ALERT "find surl:%s,dev[%s]\n", surl, sb->dev->name); 342 | #endif 343 | 344 | if (tmphost->type == adv_redirect_player) 345 | { 346 | //printk(KERN_ALERT "redirect url\n"); 347 | memset(g_location, 0, ADV_MAX_LOCATION_LEN); 348 | http_location_generate(g_location, ADV_MAX_LOCATION_LEN, tmphost->d_host, tmpmap->durl); 349 | ADVKILL_MUTEX_UNLOCK(&g_advconf_mutex); 350 | //printk(KERN_ALERT "location [%s]\n", g_location); 351 | #ifdef ADVKILL_PRINT_DEBUG_INFO 352 | printk(KERN_ALERT "begin send_client_location\n"); 353 | #endif 354 | 355 | ret = send_client_location(sb, g_location); 356 | #ifdef ADVKILL_PRINT_DEBUG_INFO 357 | printk(KERN_ALERT "send_client_location ret[%d]\n", ret); 358 | #endif 359 | if (ret != ADV_KILL_OK) 360 | { 361 | ADV_PRINT_ERROR("send_client_location failed\n"); 362 | goto exit_no_cmd; 363 | } 364 | 365 | skbuffoper = 1; 366 | goto exit_free; 367 | } 368 | else if (tmphost->type == adv_drop_request) 369 | { 370 | ADVKILL_MUTEX_UNLOCK(&g_advconf_mutex); 371 | if (is_contain_except_url(g_surl, tmphost) == ADV_KILL_OK) 372 | { 373 | goto exit_no_cmd; 374 | } 375 | ret = send_client_notfound(sb); 376 | if (ret != ADV_KILL_OK) 377 | { 378 | ADV_PRINT_ERROR("send_client_notfound failed\n"); 379 | goto exit_no_cmd; 380 | } 381 | 382 | skbuffoper = 1; 383 | goto exit_free; 384 | } 385 | else if (tmphost->type == adv_modify_url) 386 | { 387 | ADVKILL_MUTEX_UNLOCK(&g_advconf_mutex); 388 | 389 | #ifdef ADVKILL_PRINT_DEBUG_INFO 390 | printk(KERN_ALERT "host[%s] modify url,begin find map\n", tmphost->s_host); 391 | #endif 392 | if (tmphost->mapnum > 0) 393 | { 394 | for (i=0; imapnum; i++) 395 | { 396 | urlflagpos = strstr(httpcontent, tmphost->map[i].surl); 397 | if (urlflagpos != NULL) 398 | { 399 | urlflagpos += strlen(tmphost->map[i].surl); 400 | memcpy(urlflagpos, tmphost->map[i].durl, strlen(tmphost->map[i].durl)); 401 | httpcontent = urlflagpos; 402 | } 403 | } 404 | refresh_skb_checksum(sb); 405 | } 406 | goto exit_no_cmd; 407 | } 408 | else if (tmphost->type == adv_bad_gw) 409 | { 410 | ADVKILL_MUTEX_UNLOCK(&g_advconf_mutex); 411 | if (is_contain_except_url(g_surl, tmphost) == ADV_KILL_OK) 412 | { 413 | goto exit_no_cmd; 414 | } 415 | ret = send_client_bad_gateway(sb); 416 | if (ret != ADV_KILL_OK) 417 | { 418 | ADV_PRINT_ERROR("send_client_bad_gateway failed\n"); 419 | goto exit_no_cmd; 420 | } 421 | 422 | skbuffoper = 1; 423 | goto exit_free; 424 | } 425 | else if (tmphost->type == adv_fake_pack) 426 | { 427 | ADVKILL_MUTEX_UNLOCK(&g_advconf_mutex); 428 | if (is_contain_except_url(g_surl, tmphost) == ADV_KILL_OK) 429 | { 430 | goto exit_no_cmd; 431 | } 432 | ret = send_client_fake_message(sb,tmphost->d_host,tmphost->map[0].durl); 433 | if (ret != ADV_KILL_OK) 434 | { 435 | ADV_PRINT_ERROR("send_client_bad_gateway failed\n"); 436 | goto exit_no_cmd; 437 | } 438 | 439 | skbuffoper = 1; 440 | goto exit_free; 441 | } 442 | 443 | ADVKILL_MUTEX_UNLOCK(&g_advconf_mutex); 444 | 445 | exit_no_cmd: 446 | skbuffoper = 0; 447 | 448 | exit_free: 449 | 450 | if (skbuffoper == 0) 451 | return NF_ACCEPT; 452 | else if(skbuffoper == 1) 453 | return NF_DROP; 454 | else 455 | return NF_ACCEPT; 456 | } 457 | 458 | static struct nf_hook_ops nfho_forward = 459 | { 460 | .hook = hook_func, 461 | .owner = THIS_MODULE, 462 | .pf = PF_INET, 463 | #if (LINUX_VERSION_CODE < KERNEL_VERSION (2, 6, 26)) 464 | .hooknum = NF_IP_FORWARD, 465 | #else 466 | .hooknum = NF_INET_FORWARD, 467 | #endif 468 | .priority = NF_IP_PRI_FIRST, 469 | }; 470 | 471 | #ifdef ADVKILL_PRINT_DEBUG_INFO 472 | void advconf_hashnode_add_by_number(int num) 473 | { 474 | //int i = 0; 475 | struct advconf_hashnode *tmpnode = NULL; 476 | //for (i=1; i<=num; i++) 477 | { 478 | tmpnode = advconf_hashnode_generate(1, 1); 479 | 480 | if (tmpnode == NULL) 481 | { 482 | printk(KERN_ALERT "advconf_hashnode_generate [%d] failed\n", 1); 483 | return; 484 | //break; 485 | } 486 | advconf_hashnode_add(g_advconf_hashtable, HOST_HASH_SIZE, tmpnode); 487 | } 488 | } 489 | #endif 490 | 491 | /** 492 | 内核模块入口,初始化程序并注册钩子函数 493 | */ 494 | 495 | static int __init adv_kill_module_init(void) 496 | { 497 | #ifdef ADVKILL_PRINT_DEBUG_INFO 498 | printk(KERN_ALERT "kill advertisement module load\n"); 499 | #endif 500 | 501 | /* init system */ 502 | if (advkill_prepare() != ADV_KILL_OK) 503 | { 504 | ADV_PRINT_ERROR("advkill_prepare failed"); 505 | return ADV_KILL_FAIL; 506 | } 507 | /* register package receiver */ 508 | 509 | nf_register_hook(&nfho_forward); 510 | 511 | return 0; 512 | } 513 | 514 | /** 515 | 内核模块出口,做收尾工作并注销钩子函数 516 | */ 517 | static void __exit adv_kill_module_exit(void) 518 | { 519 | #ifdef ADVKILL_PRINT_DEBUG_INFO 520 | printk(KERN_ALERT "kill advertisement module unload\n"); 521 | #endif 522 | 523 | nf_unregister_hook(&nfho_forward); 524 | /* destroy system */ 525 | advkill_finish(); 526 | 527 | #ifdef ADVKILL_CHECK_MEM 528 | printk(KERN_ALERT "calloc times[%llu],size[%llu],free times[%llu],size[%llu]\n", g_calloc_times, g_calloc_size, g_free_times, g_free_size); 529 | #endif 530 | } 531 | 532 | module_init(adv_kill_module_init); 533 | module_exit(adv_kill_module_exit); 534 | -------------------------------------------------------------------------------- /advkill.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file advkill.h 3 | @date 2014/07/31 4 | @author WangChunyan 5 | @version 1.0.0 6 | @brief 去广告应用中用到的主要数据结构 7 | 8 | @note 9 | 去广告应用中主要数据结构,记录了需要修改数据包的网站,修改规则等信息。 10 | */ 11 | 12 | #ifndef _ADV_KILL_H_ 13 | #define _ADV_KILL_H_ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #define _BO_TONG_ 1 23 | 24 | //#define ADVKILL_PRINT_DEBUG_INFO 1 25 | //#define ADVKILL_CHECK_MEM 1 26 | 27 | #define ADV_KILL_OK 0 28 | #define ADV_KILL_FAIL -1 29 | 30 | #define ADV_MAX_LOCATION_LEN 256 31 | #define ADV_MAX_SHOST_LEN 128 32 | #define ADV_MAX_REFERER_LEN 128 33 | #define ADV_MAX_SURL_LEN 1024 34 | 35 | #ifndef ADVKILL_CHECK_MEM 36 | #define ADVKILL_CALLOC(n, size) kcalloc(n, size, GFP_KERNEL) 37 | #define ADVKILL_FREE(addr, size) kfree(addr) 38 | #else 39 | #define ADVKILL_CALLOC(n, size) kcalloc(n, size, GFP_KERNEL);(g_calloc_times++);(g_calloc_size+=((n)*(size))) 40 | #define ADVKILL_FREE(addr, size) kfree(addr);(g_free_times++);(g_free_size+=(size)) 41 | #endif 42 | 43 | #define ADV_PRINT_INFO(info) printk(KERN_ALERT "%s\n", info) 44 | #define ADV_PRINT_ERROR(error) printk(KERN_ERR "%s\n", error) 45 | #define EnterFunction() //printk(KERN_INFO "Enter function[%s],line[%d]\n", __FUNCTION__, __LINE__); PrintCurrentTime() 46 | #define LeaveFunction() //PrintCurrentTime(); printk(KERN_ALERT "Leave function[%s],line[%d]\n", __FUNCTION__, __LINE__) 47 | #define LeaveFunction_fail() //PrintCurrentTime(); printk(KERN_ALERT "----Failed,Leave function[%s],line[%d]\n", __FUNCTION__, __LINE__) 48 | 49 | #define ADVKILL_MUTEX_LOCK(mutex) mutex_lock(mutex) 50 | #define ADVKILL_MUTEX_UNLOCK(mutex) mutex_unlock(mutex) 51 | 52 | /** 53 | 记录去广告配置规则 54 | 55 | 主要记录要匹配的源URL和要修改成的URL 56 | */ 57 | struct advconf_hostmap 58 | { 59 | char *surl; ///< 匹配到的源URL 60 | char *durl; ///< 要修改成的URL 61 | int surllen; ///< 源RUL长度 62 | int durllen; ///< 要修改成的URL长度 63 | }; 64 | 65 | /** 66 | 去广告配置模式 67 | 68 | adv_redirect_player: 重定向播放器,一般返回302 69 | adv_drop_request: 丢弃请求包,一般返回404 70 | adv_modify_url: 修改源URL内容 71 | adv_bad_gw: 返回错误的网关 502 72 | */ 73 | typedef enum {adv_redirect_player=0, adv_drop_request=1, adv_modify_url=2, adv_bad_gw=3, adv_fake_pack=4} ADV_CMD; 74 | 75 | /** 76 | 去广告应用中的配置信息结构体 77 | 78 | 主要记录操作类型,源Host,修改成的目的Host,以及URL规则, 79 | 其中URl规则可以是多套。 80 | */ 81 | struct advconf_hashnode 82 | { 83 | struct hlist_node node; ///< 哈希链表节点 84 | ADV_CMD type; ///< 配置操作类型 85 | int index; ///< 配置索引 86 | unsigned char *s_host; ///< 要匹配的源Host 87 | unsigned char *d_host; ///< 要修改成的目的Host 88 | unsigned short int s_host_len; ///< 要匹配的源Host占用内存大小 89 | unsigned short int d_host_len; ///< 要修改成的目的Host占用内存大小 90 | struct advconf_hostmap *map; ///< 配置规则中URL配置结构首地址 91 | int mapnum; ///< 配置规则中URl配置的个数(同一个Host几套URl规则) 92 | }; 93 | 94 | /** 95 | 去广告配置中哈希链表头 96 | 97 | */ 98 | struct advconf_hashtable 99 | { 100 | struct hlist_head head; ///< 哈希链表头,代表哈希表中的其中一个哈希链表 101 | }; 102 | 103 | #endif 104 | -------------------------------------------------------------------------------- /advproc.c: -------------------------------------------------------------------------------- 1 | /** 2 | @file advproc.c 3 | @date 2014/07/31 4 | @author WangChunyan 5 | @version 1.0.0 6 | @brief proc文件系统相关操作接口 7 | 8 | @note 9 | 创建proc文件,删除proc文件,读写proc文件操作 10 | */ 11 | 12 | #include "advkill.h" 13 | #include "advproc.h" 14 | #include "advconfparse.h" 15 | #include "advhash.h" 16 | 17 | extern struct advconf_hashtable *g_advconf_hashtable; 18 | 19 | #ifdef ADVKILL_CHECK_MEM 20 | extern unsigned long long int g_calloc_times; 21 | extern unsigned long long int g_calloc_size; 22 | extern unsigned long long int g_free_times; 23 | extern unsigned long long int g_free_size; 24 | #endif 25 | 26 | static struct proc_dir_entry *proc_dir = NULL; ///< proc文件中文件夹 27 | static struct proc_dir_entry *proc_advkill_conf = NULL; ///< proc文件中文件 28 | static int advkill_conf_index; 29 | static int advkill_conf_next; 30 | static char *advkillconfdata = NULL; ///< 内核中去广告配置缓冲区地址 31 | 32 | /** 33 | 从用户空间将数据读取到内核空间,解析后保存在哈希表中 34 | 35 | @param filp 文件结构体指针,本接口对此没有操作,为内核函数参数格式 36 | @param buff 用户空间数据地址 37 | @param len 用户空间数据长度 38 | @param data 本接口对此没有操作,为内核函数参数格式 39 | @return 返回读取的长度 40 | */ 41 | #if (LINUX_VERSION_CODE < KERNEL_VERSION (3, 10, 0)) 42 | static ssize_t advkill_conf_write( struct file *filp, const char __user *buff, unsigned long len, void *data); 43 | #else 44 | static ssize_t advkill_conf_write( struct file *filp, const char __user *buff, size_t len, loff_t *data); 45 | #endif 46 | /** 47 | 从内核空间将去广告配置内存拷贝到用户空间 48 | 49 | @param page 用户空间接收数据的地址 50 | @param start 本接口对此没有操作,为内核函数参数格式 51 | @param off 本接口对此没有操作,为内核函数参数格式 52 | @param count 本接口对此没有操作,为内核函数参数格式 53 | @param eof 本接口对此没有操作,为内核函数参数格式 54 | @param data 本接口对此没有操作,为内核函数参数格式 55 | @return 返回写入的长度 56 | */ 57 | #if (LINUX_VERSION_CODE < KERNEL_VERSION (3, 10, 0)) 58 | static int advkill_conf_read( char *page, char **start, off_t off, int count, int *eof, void *data); 59 | #endif 60 | 61 | /** 62 | 从用户空间将数据读取到内核空间,解析后保存在哈希表中 63 | 64 | @param filp 文件结构体指针,本接口对此没有操作,为内核函数参数格式 65 | @param buff 用户空间数据地址 66 | @param len 用户空间数据长度 67 | @param data 本接口对此没有操作,为内核函数参数格式 68 | @return 返回读取的长度 69 | */ 70 | 71 | #if (LINUX_VERSION_CODE < KERNEL_VERSION (3, 10, 0)) 72 | static ssize_t advkill_conf_write( struct file *filp, const char __user *buff, unsigned long len, void *data) 73 | #else 74 | static ssize_t advkill_conf_write( struct file *filp, const char __user *buff, size_t len, loff_t *data) 75 | #endif 76 | { 77 | int space_available = (MAX_ADVKILL_CONF_LEN-advkill_conf_index)+1; 78 | 79 | if (len > space_available) 80 | { 81 | memset(advkillconfdata, 0, MAX_ADVKILL_CONF_LEN); 82 | advkill_conf_index = 0; 83 | advkill_conf_next = 0; 84 | } 85 | if(advkill_conf_index>0)advkillconfdata[advkill_conf_index-1] = '\n'; 86 | if (copy_from_user(&advkillconfdata[advkill_conf_index], buff, len )) 87 | { 88 | return -EFAULT; 89 | } 90 | 91 | #ifdef ADVKILL_PRINT_DEBUG_INFO 92 | ADV_PRINT_INFO(&advkillconfdata[advkill_conf_index]); 93 | #endif 94 | 95 | //parse advconf 96 | parse_advconf_line_data(&advkillconfdata[advkill_conf_index], g_advconf_hashtable, HOST_HASH_SIZE); 97 | 98 | advkill_conf_index += len; 99 | advkillconfdata[advkill_conf_index-1] = '\0'; 100 | 101 | return len; 102 | } 103 | 104 | /** 105 | 从内核空间将去广告配置内存拷贝到用户空间 106 | 107 | @param page 用户空间接收数据的地址 108 | @param start 本接口对此没有操作,为内核函数参数格式 109 | @param off 本接口对此没有操作,为内核函数参数格式 110 | @param count 本接口对此没有操作,为内核函数参数格式 111 | @param eof 本接口对此没有操作,为内核函数参数格式 112 | @param data 本接口对此没有操作,为内核函数参数格式 113 | @return 返回写入的长度 114 | */ 115 | #if (LINUX_VERSION_CODE < KERNEL_VERSION (3, 10, 0)) 116 | static int advkill_conf_read( char *page, char **start, off_t off, int count, int *eof, void *data) 117 | { 118 | int len; 119 | 120 | if (off > 0) 121 | { 122 | *eof = 1; 123 | return 0; 124 | } 125 | /* Wrap-around */ 126 | if (advkill_conf_next >= advkill_conf_index) 127 | advkill_conf_next = 0; 128 | len = sprintf(page, "%s\n", &advkillconfdata[advkill_conf_next]); 129 | advkill_conf_next += len; 130 | 131 | return len; 132 | } 133 | #else 134 | static int advkill_conf_seq_read(struct seq_file *seq, void *v) 135 | { 136 | return seq_printf(seq, "%s\n", advkillconfdata); 137 | } 138 | static int advkill_conf_seq_open(struct inode *inode, struct file *file) 139 | { 140 | return single_open(file, advkill_conf_seq_read, NULL); 141 | } 142 | #endif 143 | 144 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 10, 0)) 145 | static const struct file_operations advkill_fops = { 146 | .owner = THIS_MODULE, 147 | .open = advkill_conf_seq_open, 148 | .read = seq_read, 149 | .llseek = seq_lseek, 150 | .write = advkill_conf_write, 151 | .release = single_release, 152 | }; 153 | #endif 154 | /** 155 | 创建需要用到的proc文件 156 | 157 | @return 成功返回 RR_OK,失败返回 RR_FAIL。 158 | */ 159 | int create_proc_file(void) 160 | { 161 | int ret = ADV_KILL_OK; 162 | //web config 163 | advkillconfdata = (char *)ADVKILL_CALLOC(1, MAX_ADVKILL_CONF_LEN); 164 | if (advkillconfdata == NULL) 165 | return ADV_KILL_FAIL; 166 | 167 | proc_dir = proc_mkdir(ADV_KILL_PROC_DIRECTORY, NULL); 168 | if (proc_dir == NULL) 169 | { 170 | ret = -ENOMEM; 171 | printk(KERN_ERR "Couldn't create proc dir[/proc/%s]\n", ADV_KILL_PROC_DIRECTORY); 172 | goto exit_fail; 173 | } 174 | else 175 | { 176 | #if (LINUX_VERSION_CODE < KERNEL_VERSION (3, 10, 0)) 177 | proc_advkill_conf = create_proc_entry(ADV_KILL_PROC_FILE, 0644, proc_dir); 178 | if (proc_advkill_conf == NULL) 179 | { 180 | printk(KERN_ERR "Couldn't create proc entry[/proc/%s/%s]\n", ADV_KILL_PROC_DIRECTORY, ADV_KILL_PROC_FILE); 181 | ret = -ENOMEM; 182 | goto exit_fail; 183 | } 184 | proc_advkill_conf->read_proc = advkill_conf_read; 185 | proc_advkill_conf->write_proc = advkill_conf_write; 186 | #else 187 | proc_advkill_conf = proc_create(ADV_KILL_PROC_FILE, 0644, proc_dir, &advkill_fops); 188 | if (proc_advkill_conf == NULL) 189 | { 190 | printk(KERN_ERR "Couldn't create proc entry[/proc/%s/%s]\n", ADV_KILL_PROC_DIRECTORY, ADV_KILL_PROC_FILE); 191 | ret = -ENOMEM; 192 | goto exit_fail; 193 | } 194 | #endif 195 | } 196 | 197 | return ret; 198 | 199 | exit_fail: 200 | if (advkillconfdata != NULL) 201 | { 202 | ADVKILL_FREE(advkillconfdata, MAX_ADVKILL_CONF_LEN); 203 | advkillconfdata = NULL; 204 | } 205 | if (proc_dir != NULL) 206 | { 207 | remove_proc_entry(ADV_KILL_PROC_FILE, proc_dir); 208 | proc_dir = NULL; 209 | } 210 | return ret; 211 | } 212 | 213 | /** 214 | 删除proc文件 215 | */ 216 | void destroy_proc_file(void) 217 | { 218 | if (proc_advkill_conf != NULL) 219 | { 220 | remove_proc_entry(ADV_KILL_PROC_FILE, proc_dir); 221 | proc_advkill_conf = NULL; 222 | } 223 | if (proc_dir != NULL) 224 | { 225 | remove_proc_entry(ADV_KILL_PROC_DIRECTORY, NULL); 226 | proc_dir = NULL; 227 | } 228 | if (advkillconfdata != NULL) 229 | { 230 | ADVKILL_FREE(advkillconfdata, MAX_ADVKILL_CONF_LEN); 231 | advkillconfdata = NULL; 232 | } 233 | } 234 | -------------------------------------------------------------------------------- /advproc.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file advproc.h 3 | @date 2014/07/31 4 | @author WangChunyan 5 | @version 1.0.0 6 | @brief proc文件系统相关操作接口 7 | 8 | @note 9 | 创建proc文件,删除proc文件,读写proc文件操作 10 | */ 11 | 12 | #ifndef _ADV_PROC_H_ 13 | /** 14 | @file advproc.h 15 | @date 2014/07/31 16 | @author WangChunyan 17 | @version 1.0.0 18 | @brief 去广告应用的proc文件 19 | 20 | @note 21 | 创建proc文件,删除proc文件 22 | */ 23 | #define _ADV_PROC_H_ 24 | 25 | #include 26 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 10, 0)) 27 | #include 28 | #include 29 | #endif 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #define MAX_ADVKILL_CONF_LEN 1024 ///< proc文件系统中每条配置最大长度 36 | #define ADV_KILL_PROC_DIRECTORY "advkill" ///< proc文件目录名称 37 | #define ADV_KILL_PROC_FILE "advconf" ///< proc文件名称 38 | 39 | /** 40 | 创建需要用到的proc文件 41 | 42 | @return 成功返回 RR_OK,失败返回 RR_FAIL。 43 | */ 44 | int create_proc_file(void); 45 | 46 | /** 47 | 删除proc文件 48 | */ 49 | void destroy_proc_file(void); 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /pkgoper.c: -------------------------------------------------------------------------------- 1 | /** 2 | @file pkgoper.c 3 | @date 2014/07/31 4 | @author WangChunyan 5 | @version 1.0.0 6 | @brief 去广告应用中数据包操作接口 7 | 8 | @note 9 | 数据包操作接口,包括组装数据包,发送数据包等。 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include "pkgoper.h" 22 | #include "advkill.h" 23 | 24 | #ifdef ADVKILL_CHECK_MEM 25 | extern unsigned long long int g_calloc_times; 26 | extern unsigned long long int g_calloc_size; 27 | extern unsigned long long int g_free_times; 28 | extern unsigned long long int g_free_size; 29 | #endif 30 | 31 | struct client_nicname lan_name[] = 32 | { 33 | { 0, ETH_CLIENT_LAN0 }, 34 | { 1, ETH_CLIENT_LAN1 }, 35 | { -1, NULL } 36 | }; 37 | 38 | struct client_nicname wlan_name[] = 39 | { 40 | { 0, ETH_CLIENT_WLAN0 }, 41 | { 1, ETH_CLIENT_WLAN1 }, 42 | { -1, NULL } 43 | }; 44 | 45 | /** 46 | 重新计算IP校验和 47 | 48 | @param skb 要校验的skb地址 49 | */ 50 | static void refresh_ip_checksum(struct sk_buff *skb) 51 | { 52 | ip_send_check((struct iphdr *)skb->data); 53 | } 54 | 55 | /** 56 | 重新计算TCP校验和 57 | 58 | @param skb 要校验的skb地址 59 | */ 60 | static void refresh_tcp_checksum(struct sk_buff *skb) 61 | { 62 | struct iphdr *iph; 63 | struct tcphdr *tcph; 64 | int tcplen; 65 | 66 | iph = (struct iphdr *)skb->data; 67 | tcph = (struct tcphdr *)(skb->data + (iph->ihl << 2)); 68 | tcplen = ntohs(iph->tot_len) - (iph->ihl << 2); 69 | tcph->check = 0; 70 | tcph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, tcplen, IPPROTO_TCP, csum_partial((char *)tcph, tcplen, 0)); 71 | } 72 | 73 | /** 74 | 重新对IP头和TCP头进行校验 75 | 76 | @param skb 原始的sk_buff结构地址 77 | */ 78 | void refresh_skb_checksum(struct sk_buff *skb) 79 | { 80 | refresh_ip_checksum(skb); 81 | refresh_tcp_checksum(skb); 82 | } 83 | 84 | /** 85 | 根据tcp数据生成数据包 86 | 87 | 根据tcp数据,生成数据包,并填充 mac/ip/tcp 头部信息 88 | @param skb 原始的sk_buff结构地址 89 | @param names 网卡名称结构首地址 90 | @param num 网卡个数 91 | @param tcpdata tcp数据地址 92 | @param tcpdatalen tcp数据长度 93 | @return 成功返回数据包地址,失败返回NULL。 94 | */ 95 | struct sk_buff *pkg_skbuff_generate(struct sk_buff *skb, struct client_nicname *names, int num, char *tcpdata, int tcpdatalen) 96 | { 97 | struct sk_buff *new_skb = NULL; 98 | struct net_device *dev = NULL; 99 | struct iphdr *iph = NULL,*new_iph = NULL; 100 | struct tcphdr *tcph = NULL,*new_tcph = NULL; 101 | struct ethhdr *ethdr = NULL; 102 | char *newpdata = NULL; 103 | unsigned char * mac_header_addr = NULL; 104 | int i = 0; 105 | 106 | if(!skb || !names) 107 | { 108 | goto out; 109 | } 110 | iph = ip_hdr(skb); 111 | if(iph == NULL) 112 | { 113 | goto out; 114 | } 115 | tcph = (struct tcphdr *)((char *)iph + iph->ihl*4); 116 | if(tcph == NULL) 117 | { 118 | goto out; 119 | } 120 | ethdr = eth_hdr(skb); 121 | if(ethdr == NULL) 122 | { 123 | goto out; 124 | } 125 | 126 | for (i=0; names[i].index != -1; i++) 127 | { 128 | #if (LINUX_VERSION_CODE < KERNEL_VERSION (2, 6, 24))//不确定版本号是否应该更早 129 | dev = dev_get_by_name(names[i].name); 130 | #else 131 | dev = dev_get_by_name(&init_net, names[i].name); 132 | #endif 133 | if (dev != NULL) 134 | break; 135 | } 136 | 137 | if (dev == NULL) 138 | { 139 | goto out; 140 | } 141 | 142 | new_skb = alloc_skb(tcpdatalen + iph->ihl*4 + tcph->doff*4 + 14, GFP_ATOMIC); 143 | if(new_skb == NULL) 144 | { 145 | goto out; 146 | } 147 | #if (LINUX_VERSION_CODE < KERNEL_VERSION (3, 11, 0)) 148 | new_skb->mac_header = new_skb->data; 149 | skb_reserve(new_skb,14); 150 | new_skb->transport_header = new_skb->data; 151 | new_skb->network_header = new_skb->data; 152 | 153 | //get_route_mac(iph->saddr, iph->daddr); 154 | memcpy(&new_skb->mac_header[0], ethdr->h_source, 6); 155 | memcpy(&new_skb->mac_header[6], ethdr->h_dest, 6); 156 | new_skb->mac_header[12] = 0x08; 157 | new_skb->mac_header[13] = 0x00; 158 | #else 159 | skb_reset_mac_header(new_skb); 160 | skb_reserve(new_skb,14); 161 | skb_reset_transport_header(new_skb); 162 | skb_reset_network_header(new_skb); 163 | 164 | mac_header_addr=skb_mac_header(new_skb); 165 | if(mac_header_addr==NULL) 166 | { 167 | printk("Can't get header address!\n"); 168 | goto out; 169 | } 170 | //get_route_mac(iph->saddr, iph->daddr); 171 | memcpy(mac_header_addr, ethdr->h_source, 6); 172 | memcpy(mac_header_addr+6, ethdr->h_dest, 6); 173 | mac_header_addr[12] = 0x08; 174 | mac_header_addr[13] = 0x00; 175 | #endif 176 | skb_put(new_skb, iph->ihl*4 + tcph->doff*4); 177 | new_skb->mac_len = 14; 178 | new_skb->dev = dev; 179 | new_skb->pkt_type = PACKET_OTHERHOST; 180 | new_skb->protocol = __constant_htons(ETH_P_IP); 181 | new_skb->ip_summed = CHECKSUM_NONE; 182 | new_skb->priority = 0; 183 | /* 184 | *IP set 185 | */ 186 | new_iph = (struct iphdr *)new_skb->data; 187 | memset((char *)new_iph, 0, iph->ihl*4); 188 | new_iph->version = iph->version; 189 | new_iph->ihl = iph->ihl; 190 | new_iph->tos = iph->tos; 191 | new_iph->id = iph->id; 192 | new_iph->ttl = iph->ttl; 193 | new_iph->frag_off = iph->frag_off; 194 | new_iph->protocol = IPPROTO_TCP; 195 | //new_iph->saddr = iph->saddr; 196 | new_iph->saddr = iph->daddr; 197 | new_iph->daddr = iph->saddr; 198 | new_iph->tot_len = htons(tcpdatalen + iph->ihl*4 + tcph->doff*4); 199 | new_iph->check = 0; 200 | /* 201 | *TCP set 202 | */ 203 | new_tcph = (struct tcphdr *)(new_skb->data + iph->ihl*4); 204 | memset((char *)new_tcph, 0, tcph->doff*4); 205 | 206 | new_tcph->source = tcph->dest; 207 | new_tcph->dest = tcph->source; 208 | new_tcph->seq = tcph->ack_seq; 209 | new_tcph->ack_seq = htonl(ntohl(tcph->seq) + (ntohs(iph->tot_len) - iph->ihl*4 - tcph->doff*4)); 210 | new_tcph->doff = tcph->doff; 211 | new_tcph->fin = tcph->fin; 212 | new_tcph->ack = tcph->ack; 213 | new_tcph->psh = tcph->psh; 214 | new_tcph->window = tcph->window; 215 | new_tcph->check = 0; 216 | 217 | if (tcpdatalen > 0) 218 | { 219 | newpdata = skb_put(new_skb, tcpdatalen); 220 | if (newpdata != NULL) 221 | { 222 | if (tcpdata != NULL) 223 | memcpy(newpdata, tcpdata, tcpdatalen); 224 | } 225 | } 226 | refresh_skb_checksum(new_skb); 227 | return new_skb; 228 | out: 229 | if (NULL != skb) 230 | { 231 | dev_put (dev); 232 | kfree_skb (skb); 233 | } 234 | return NULL; 235 | } 236 | 237 | /** 238 | 发送tcp数据包 239 | 240 | @param skb 原始的sk_buff结构地址 241 | @param tcpdata tcp数据地址 242 | @param tcpdatalen tcp数据长度 243 | @return 成功返回 ADV_KILL_OK,失败返回 ADV_KILL_FAIL。 244 | */ 245 | int pkg_skbuff_dev_xmit(struct sk_buff *skb, char *tcpdata, int tcpdatalen) 246 | { 247 | struct sk_buff *new_skb_lan = NULL; 248 | int ret = 0; 249 | 250 | new_skb_lan = pkg_skbuff_generate(skb, lan_name, sizeof(lan_name)/sizeof(struct client_nicname), tcpdata, tcpdatalen); 251 | new_skb_lan->data -= 14; 252 | new_skb_lan->len += 14; 253 | ret = dev_queue_xmit(new_skb_lan); 254 | if(ret != 0) 255 | { 256 | #ifdef ADVKILL_PRINT_DEBUG_INFO 257 | printk(KERN_ALERT "dev queue xmit failed %d\n",ret); 258 | #endif 259 | return ADV_KILL_FAIL; 260 | } 261 | return ADV_KILL_OK; 262 | } 263 | 264 | /** 265 | 根据Host生成location字符串 266 | 267 | @param httplen 生成的location长度 268 | @param host Host字符串内容 269 | @return 成功返回location地址,失败返回NULL。 270 | */ 271 | char *http_location_str_generate(int *httplen, char *host) 272 | { 273 | char *new_data = NULL; 274 | int http_len = 0, new_offset = 0; 275 | char *response_head = HTTP_RESPONSE_HEAD_NOT_FIND; 276 | char *location = HTTP_RESPONSE_LOCATION; 277 | char *ending = HTTP_RESPONSE_END; 278 | int hostlen = 0; 279 | 280 | if(!httplen || !host) 281 | return NULL; 282 | 283 | hostlen = strlen(host); 284 | http_len = (HTTP_RESPONSE_HEAD_NOT_FIND_LEN + HTTP_RESPONSE_LOCATION_LEN + hostlen + 4); 285 | *httplen = http_len; 286 | new_data = (char *)ADVKILL_CALLOC(1, http_len+1); 287 | if(new_data == NULL) 288 | { 289 | goto err; 290 | } 291 | //http 302 292 | memcpy(new_data, response_head, HTTP_RESPONSE_HEAD_NOT_FIND_LEN); 293 | new_offset += HTTP_RESPONSE_HEAD_NOT_FIND_LEN; 294 | //location 295 | memcpy(new_data + new_offset, location, HTTP_RESPONSE_LOCATION_LEN); 296 | new_offset += HTTP_RESPONSE_LOCATION_LEN; 297 | //host 298 | memcpy(new_data + new_offset, host, hostlen); 299 | new_offset += hostlen; 300 | //\r\n 301 | memcpy(new_data + new_offset, ending, HTTP_RESPONSE_END_LEN); 302 | new_offset += HTTP_RESPONSE_END_LEN; 303 | memcpy(new_data + new_offset, ending, HTTP_RESPONSE_END_LEN); 304 | 305 | return new_data; 306 | 307 | err: 308 | return NULL; 309 | } 310 | 311 | /** 312 | 根据location发送302消息 313 | 314 | @param skb 原始的sk_buff结构地址 315 | @param location 需要发送的location内容 316 | @return 成功返回 ADV_KILL_OK,失败返回 ADV_KILL_FAIL。 317 | */ 318 | int send_client_location(struct sk_buff *skb, char *location) 319 | { 320 | char *tcpdata = NULL; 321 | int tcpdatalen = 0; 322 | 323 | if(!location || !skb) 324 | return ADV_KILL_FAIL; 325 | tcpdata = http_location_str_generate(&tcpdatalen, location); 326 | if (tcpdata == NULL) 327 | { 328 | return ADV_KILL_FAIL; 329 | } 330 | pkg_skbuff_dev_xmit(skb, tcpdata, tcpdatalen); 331 | 332 | ADVKILL_FREE(tcpdata, tcpdatalen+1); 333 | return ADV_KILL_OK; 334 | } 335 | 336 | /** 337 | 发送404消息 338 | 339 | @param skb 原始的sk_buff结构地址 340 | @return 成功返回 ADV_KILL_OK,失败返回 ADV_KILL_FAIL。 341 | */ 342 | int send_client_notfound(struct sk_buff *skb) 343 | { 344 | if(!skb) 345 | return ADV_KILL_FAIL; 346 | 347 | return pkg_skbuff_dev_xmit(skb, HTTP_NOT_FOUND_STR, HTTP_NOT_FOUND_STR_LEN); 348 | } 349 | 350 | /** 351 | 发送502消息 352 | 353 | @param skb 原始的sk_buff结构地址 354 | @return 成功返回 ADV_KILL_OK,失败返回 ADV_KILL_FAIL。 355 | */ 356 | int send_client_bad_gateway(struct sk_buff *skb) 357 | { 358 | if(!skb) 359 | return ADV_KILL_FAIL; 360 | 361 | return pkg_skbuff_dev_xmit(skb, HTTP_BAD_GATEWAY, HTTP_BAD_GATEWAY_STR_LEN); 362 | } 363 | 364 | /* 365 | 发送伪造的HTTP200响应 366 | @param skb 原始的sk_buff结构地址 CType Content-Type Cont 网页内容 367 | @return 成功返回 ADV_KILL_OK,失败返回 ADV_KILL_FAIL。 368 | HTTP/1.1 200 OK\r\n 369 | Server: QWS\r\n 370 | Content-Type: text/xml\r\n 371 | Content-Length: 125\r\n 372 | Connection: close\r\n 373 | Accept-Ranges: bytes\r\n\r\n 374 | */ 375 | int send_client_fake_message(struct sk_buff *skb, const char * CType, const char * Cont) 376 | { 377 | char *new_data = NULL; 378 | int retval = 0, datlen = 0; 379 | 380 | if(!skb) 381 | return ADV_KILL_FAIL; 382 | 383 | datlen = strlen(CType)+strlen(Cont)+120; 384 | new_data = (char *)ADVKILL_CALLOC(1, datlen); 385 | if(new_data==NULL) 386 | return ADV_KILL_FAIL; 387 | sprintf(new_data,"HTTP/1.1 200 OK\r\nServer: QWS\r\nContent-Type: %s\r\nContent-Length: %d\r\nConnection: close\r\nAccept-Ranges: bytes\r\n\r\n%s",CType,strlen(Cont),Cont); 388 | retval=pkg_skbuff_dev_xmit(skb, new_data, strlen(new_data)); 389 | ADVKILL_FREE(new_data, datlen); 390 | return retval; 391 | } 392 | 393 | 394 | -------------------------------------------------------------------------------- /pkgoper.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file pkgoper.h 3 | @date 2014/07/31 4 | @author WangChunyan 5 | @version 1.0.0 6 | @brief 去广告应用中数据包操作接口 7 | 8 | @note 9 | 数据包操作接口,包括组装数据包,发送数据包等。 10 | */ 11 | 12 | #ifndef _PKG_OPER_H_ 13 | #define _PKG_OPER_H_ 14 | 15 | #define HTTP_RESPONSE_HEAD_NOT_FIND "HTTP/1.1 307 Temporary Redirect\r\n" 16 | #define HTTP_RESPONSE_HEAD_NOT_FIND_LEN 33 17 | #define HTTP_RESPONSE_LOCATION "Location: " 18 | #define HTTP_RESPONSE_LOCATION_LEN 10 19 | #define HTTP_RESPONSE_END "\r\n" 20 | #define HTTP_RESPONSE_END_LEN 2 21 | //#define HTTP_RESPONSE_CONNECTION "Connection: closed" 22 | 23 | /* HTTP 404 代码 */ 24 | #define HTTP_NOT_FOUND_STR "HTTP/1.1 404 Not Found\r\n" \ 25 | "Server: QWS\r\n" \ 26 | "Content-Type: text/html\r\n" \ 27 | "Content-Length: 130\r\n" \ 28 | "Connection: keep-alive\r\n\r\n" \ 29 | "404 Not Found

404 Not Found


QWS
" 30 | #define HTTP_NOT_FOUND_STR_LEN 239 31 | 32 | /* HTTP 502 代码 */ 33 | #define HTTP_BAD_GATEWAY "HTTP/1.1 502 Bad Gateway\r\n" \ 34 | "Server: QWS\r\n" \ 35 | "Content-Type: text/html\r\n" \ 36 | "Content-Length: 134\r\n" \ 37 | "Connection: keep-alive\r\n\r\n" \ 38 | "502 Bad Gateway

502 Bad Gateway


QWS
" 39 | #define HTTP_BAD_GATEWAY_STR_LEN 245 40 | 41 | /* HTTP 302 代码*/ 42 | #define HTTP_FIND_LOCAL_STR "HTTP/1.1 302 Found\r\nLocation: http://127.0.0.1/\r\n\r\n" 43 | #define HTTP_FIND_LOCAL_STR_LEN 51 44 | 45 | /* lan interface */ 46 | #define ETH_CLIENT_LAN0 "br-lan" 47 | #define ETH_CLIENT_LAN1 "br-lan" 48 | 49 | /* wlan interface */ 50 | #define ETH_CLIENT_WLAN0 "vlan0" 51 | #define ETH_CLIENT_WLAN1 "vlan1" 52 | 53 | /** 54 | 网卡信息结构体 55 | 56 | 主要在往网卡发送数据包时使用,包括有线和无线网卡。 57 | */ 58 | struct client_nicname 59 | { 60 | int index; ///< 网卡索引 61 | char *name; ///< 网卡名称 62 | }; 63 | 64 | /** 65 | 根据tcp数据生成数据包 66 | 67 | 根据tcp数据,生成数据包,并填充 mac/ip/tcp 头部信息 68 | @param skb 原始的sk_buff结构地址 69 | @param names 网卡名称结构首地址 70 | @param num 网卡个数 71 | @param tcpdata tcp数据地址 72 | @param tcpdatalen tcp数据长度 73 | @return 成功返回数据包地址,失败返回NULL。 74 | */ 75 | struct sk_buff *pkg_skbuff_generate(struct sk_buff *skb, struct client_nicname *names, int num, char *tcpdata, int tcpdatalen); 76 | 77 | /** 78 | 发送tcp数据包 79 | 80 | @param skb 原始的sk_buff结构地址 81 | @param tcpdata tcp数据地址 82 | @param tcpdatalen tcp数据长度 83 | @return 成功返回 ADV_KILL_OK,失败返回 ADV_KILL_FAIL。 84 | */ 85 | int pkg_skbuff_dev_xmit(struct sk_buff *skb, char *tcpdata, int tcpdatalen); 86 | 87 | /** 88 | 根据Host生成location字符串 89 | 90 | @param httplen 生成的location长度 91 | @param host Host字符串内容 92 | @return 成功返回location地址,失败返回NULL。 93 | */ 94 | char *http_location_str_generate(int *httplen, char *host); 95 | 96 | /** 97 | 根据location发送302消息 98 | 99 | @param skb 原始的sk_buff结构地址 100 | @param location 需要发送的location内容 101 | @return 成功返回 ADV_KILL_OK,失败返回 ADV_KILL_FAIL。 102 | */ 103 | int send_client_location(struct sk_buff *skb, char *location); 104 | 105 | /** 106 | 发送404消息 107 | 108 | @param skb 原始的sk_buff结构地址 109 | @return 成功返回 ADV_KILL_OK,失败返回 ADV_KILL_FAIL。 110 | */ 111 | int send_client_notfound(struct sk_buff *skb); 112 | 113 | /** 114 | 发送502消息 115 | 116 | @param skb 原始的sk_buff结构地址 117 | @return 成功返回 ADV_KILL_OK,失败返回 ADV_KILL_FAIL。 118 | */ 119 | int send_client_bad_gateway(struct sk_buff *skb); 120 | 121 | /** 122 | 重新对IP头和TCP头进行校验 123 | 124 | @param skb 原始的sk_buff结构地址 125 | */ 126 | void refresh_skb_checksum(struct sk_buff *skb); 127 | 128 | /* 129 | 发送伪造的HTTP200响应 130 | @param skb 原始的sk_buff结构地址 CType Content-Type Cont 网页内容 131 | @return 成功返回 ADV_KILL_OK,失败返回 ADV_KILL_FAIL。 132 | HTTP/1.1 200 OK\r\n 133 | Server: QWS\r\n 134 | Content-Type: text/xml\r\n 135 | Content-Length: 125\r\n 136 | Connection: close\r\n 137 | Accept-Ranges: bytes\r\n\r\n 138 | */ 139 | int send_client_fake_message(struct sk_buff *skb, const char * CType, const char * Cont); 140 | #endif 141 | 142 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/981213/adkill/e2b788431ff65f5217cefd1842e69261c8829a54/readme.txt -------------------------------------------------------------------------------- /strcmd.c: -------------------------------------------------------------------------------- 1 | /** 2 | @file strcmd.c 3 | @date 2014/07/31 4 | @author WangChunyan 5 | @version 1.0.0 6 | @brief 字符操作接口 7 | 8 | @note 9 | 主要解析对HTTP协议相关字符串进行操作 10 | */ 11 | 12 | #include "strcmd.h" 13 | 14 | #ifdef ADVKILL_CHECK_MEM 15 | extern unsigned long long int g_calloc_times; 16 | extern unsigned long long int g_calloc_size; 17 | extern unsigned long long int g_free_times; 18 | extern unsigned long long int g_free_size; 19 | #endif 20 | 21 | /** 22 | 根据字段标识获取HTTP协议中字段内容 23 | 24 | @param httpstr HTTP协议字符串 25 | @param httpstrlen HTTP协议字符串长度 26 | @param fieldflag 要获取字段的标识 27 | @param fieldflaglen 要获取字段的标识长度 28 | @param field 要保存字段内容的地址 29 | @param maxfieldlen 要保存字段内容的最大长度 30 | @param realfieldlen 获取到的字段内容的实际长度 31 | @return 获取到的字段内容的地址 32 | */ 33 | char *get_http_field(char *httpstr, int httpstrlen, char *fieldflag, int fieldflaglen, char *field, int maxfieldlen, int *realfieldlen) 34 | { 35 | char *beginpos = NULL; 36 | char *endpos = NULL; 37 | char *tmppos = NULL; 38 | int len = 0; 39 | 40 | if (!httpstr || !fieldflag || !field || !realfieldlen) 41 | return NULL; 42 | endpos = (httpstr + httpstrlen); 43 | beginpos = strstr(httpstr, fieldflag); 44 | if (beginpos == NULL) 45 | return NULL; 46 | beginpos += fieldflaglen; 47 | tmppos = beginpos; 48 | while(*tmppos != '\r' && tmppos < endpos) 49 | { 50 | len++; 51 | tmppos++; 52 | } 53 | if (len <= 0) 54 | return NULL; 55 | if (len > (maxfieldlen -1)) 56 | { 57 | *realfieldlen = (maxfieldlen -1); 58 | memcpy(field, beginpos, maxfieldlen -1); 59 | return field; 60 | } 61 | 62 | *realfieldlen = len; 63 | memcpy(field, beginpos, len); 64 | return field; 65 | } 66 | 67 | /** 68 | 获取HTTP协议中URL内容 69 | 70 | @param httpstr HTTP协议字符串 71 | @param httpstrlen HTTP协议字符串长度 72 | @param field 要保存字段内容的地址 73 | @param maxfieldlen 要保存字段内容的最大长度 74 | @param geturllen 获取到的URL的实际长度 75 | @return 获取到的URL内容的地址 76 | */ 77 | char *get_http_get_url(char *httpstr, int httpstrlen, char *field, int maxfieldlen, int *geturllen) 78 | { 79 | char *beginpos = NULL; 80 | char *endpos = NULL; 81 | int len = 0; 82 | 83 | if (!httpstr || !geturllen) 84 | return NULL; 85 | 86 | beginpos = httpstr; 87 | beginpos += HTTP_METHOD_FLAG_LEN; 88 | endpos = strstr(beginpos, HTTP_URL_END_FLAG); 89 | 90 | if (endpos == NULL) 91 | return NULL; 92 | len = (endpos - beginpos); 93 | if(len <= 0 || len > (maxfieldlen - 1)) 94 | return NULL; 95 | 96 | *geturllen = len; 97 | memcpy(field, beginpos, len); 98 | return field; 99 | } 100 | 101 | /** 102 | 根据Host和URL生成location内容 103 | 104 | @param location 要保存的location内容的地址 105 | @param maxlen 要保存location内容的最大长度 106 | @param host location内容用到的Host 107 | @param url location内容用到的URL 108 | */ 109 | void http_location_generate(char *location, int maxlen, char *host, char *url) 110 | { 111 | if(!location || !host || !url) 112 | return; 113 | snprintf(location, maxlen, "%s%s%s", HTTP_LOCATION_PREFIX, host, url); 114 | } 115 | 116 | /** 117 | 检测Host内容是否全为IP地址而非域名 118 | 119 | @param host 要检测的Host内容 120 | @return 是IP地址返回 ADV_KILL_OK,否则返回 ADV_KILL_FAIL。 121 | */ 122 | int is_digit_host(char *host) 123 | { 124 | char *tmphost = NULL; 125 | 126 | if(!host) 127 | return ADV_KILL_FAIL; 128 | tmphost = host; 129 | while(*tmphost != '\0') 130 | { 131 | if (*tmphost < '.' || *tmphost > '9') 132 | { 133 | return ADV_KILL_FAIL; 134 | } 135 | tmphost++; 136 | } 137 | return ADV_KILL_OK; 138 | } 139 | 140 | /** 141 | 检测域名中是否至少包含指定个数的数字 142 | 143 | @param domain 要检测的域名内容 144 | @param digitnum 要包含的数字最少个数 145 | @return 若是IP地址返回 ADV_KILL_OK,否则返回 ADV_KILL_FAIL。 146 | */ 147 | int domain_contain_digits(char *domain, int digitnum) 148 | { 149 | char *tmpdomain = NULL; 150 | int tmpnum = 0; 151 | int maxlen = 0; 152 | int i = 0; 153 | 154 | if (!domain || digitnum <= 0) 155 | return ADV_KILL_FAIL; 156 | tmpdomain = domain; 157 | maxlen = strlen(tmpdomain); 158 | 159 | for (i=0; i= '0' && *tmpdomain <= '9') 162 | { 163 | tmpnum++; 164 | } 165 | else 166 | { 167 | tmpnum = 0; 168 | } 169 | if (tmpnum >= digitnum) 170 | return ADV_KILL_OK; 171 | tmpdomain++; 172 | } 173 | return ADV_KILL_FAIL; 174 | } 175 | 176 | /** 177 | 检测域名是否符合组匹配模式 178 | 179 | @param domain 要检测的域名内容 180 | @param fieldindex 域名第几个子域开始匹配 181 | @return 成功返回 匹配模式地址,失败返回 NULL。 182 | */ 183 | char * domain_regroup_match_mode(char *domain, int fieldindex) 184 | { 185 | int index = 0; 186 | int maxlen = 0; 187 | int fieldnum = 0; 188 | 189 | if (!domain || fieldindex <= 0) 190 | { 191 | return NULL; 192 | } 193 | maxlen = strlen(domain); 194 | for (index=0; indexmapnum <= 0) 222 | return ADV_KILL_FAIL; 223 | for (i=0; imapnum; i++) 224 | { 225 | tmppos = strchr(node->map[i].durl, URL_EXCEPT_CHAR); 226 | if (tmppos != NULL) 227 | { 228 | tmppos++; 229 | if (strstr(surl, tmppos) != NULL) 230 | return ADV_KILL_OK; 231 | } 232 | } 233 | return ADV_KILL_FAIL; 234 | } 235 | -------------------------------------------------------------------------------- /strcmd.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file strcmd.h 3 | @date 2014/07/31 4 | @author WangChunyan 5 | @version 1.0.0 6 | @brief 字符操作接口 7 | 8 | @note 9 | 主要解析对HTTP协议相关字符串进行操作 10 | */ 11 | #ifndef _STR_CMD_H_ 12 | #define _STR_CMD_H_ 13 | #include "advkill.h" 14 | 15 | #define HTTP_METHOD_FLAG "GET " 16 | #define HTTP_METHOD_FLAG_LEN 4 17 | #define HTTP_URL_END_FLAG " HTTP/" 18 | #define HTTP_URL_END_LEN 9 19 | #define HTTP_HOST_FLAG "Host: " 20 | #define HTTP_HOST_FLAG_LEN 6 21 | #define HTTP_REFERER_FLAG "Referer: " 22 | #define HTTP_REFERER_FLAG_LEN 9 23 | #define HTTP_MIN_LEN (HTTP_METHOD_FLAG_LEN + HTTP_URL_END_LEN + 2 + HTTP_HOST_FLAG_LEN + 2) 24 | 25 | #define HTTP_LOCATION_PREFIX "http://" 26 | 27 | #define XUNLEI_KANKAN_DOMAIN_DIGIT_NUM 8 28 | #define XUNLEI_KANKAN_DOMAIN_DIGIT_INDEX 1 29 | #define DOMAIN_SEP_CHAR '.' 30 | #define DOMAIN_MATCH_CHAR '*' ///< 域名模糊匹配标识 31 | #define URL_EXCEPT_CHAR '!' ///< URL例外标识 32 | #define HOST_EXCEPT_CHAR '!' ///< Host例外标识 33 | 34 | /** 35 | 根据字段标识获取HTTP协议中字段内容 36 | 37 | @param httpstr HTTP协议字符串 38 | @param httpstrlen HTTP协议字符串长度 39 | @param fieldflag 要获取字段的标识 40 | @param fieldflaglen 要获取字段的标识长度 41 | @param field 要保存字段内容的地址 42 | @param maxfieldlen 要保存字段内容的最大长度 43 | @param realfieldlen 获取到的字段内容的实际长度 44 | @return 获取到的字段内容的地址 45 | */ 46 | char *get_http_field(char *httpstr, int httpstrlen, char *fieldflag, int fieldflaglen, char *field, int maxfieldlen, int *realfieldlen); 47 | 48 | /** 49 | 获取HTTP协议中URL内容 50 | 51 | @param httpstr HTTP协议字符串 52 | @param httpstrlen HTTP协议字符串长度 53 | @param field 要保存字段内容的地址 54 | @param maxfieldlen 要保存字段内容的最大长度 55 | @param geturllen 获取到的URL的实际长度 56 | @return 获取到的URL内容的地址 57 | */ 58 | char *get_http_get_url(char *httpstr, int httpstrlen, char *field, int maxfieldlen, int *geturllen); 59 | 60 | /** 61 | 根据Host和URL生成location内容 62 | 63 | @param location 要保存的location内容的地址 64 | @param maxlen 要保存location内容的最大长度 65 | @param host location内容用到的Host 66 | @param url location内容用到的URL 67 | */ 68 | void http_location_generate(char *location, int maxlen, char *host, char *url); 69 | 70 | /** 71 | 检测Host内容是否全为IP地址而非域名 72 | 73 | @param host 要检测的Host内容 74 | @return 是IP地址返回 ADV_KILL_OK,否则返回 ADV_KILL_FAIL。 75 | */ 76 | int is_digit_host(char *host); 77 | 78 | /** 79 | 检测域名中是否至少包含指定个数的数字 80 | 81 | @param domain 要检测的域名内容 82 | @param digitnum 要包含的数字最少个数 83 | @return 若是IP地址返回 ADV_KILL_OK,否则返回 ADV_KILL_FAIL。 84 | */ 85 | int domain_contain_digits(char *domain, int digitnum); 86 | 87 | /** 88 | 检测域名是否符合组匹配模式 89 | 90 | @param domain 要检测的域名内容 91 | @param fieldindex 域名第几个子域开始匹配 92 | @return 成功返回 匹配模式地址,失败返回 NULL。 93 | */ 94 | char * domain_regroup_match_mode(char *domain, int fieldindex); 95 | 96 | /** 97 | 检测指定配置节点中是否包含URL例外模式 98 | 99 | @param surl 原始URL 100 | @param node 要检测的配置节点地址 101 | @return 若是返回 ADV_KILL_OK,否则返回 ADV_KILL_FAIL。 102 | */ 103 | int is_contain_except_url(char *surl, struct advconf_hashnode *node); 104 | 105 | #endif 106 | --------------------------------------------------------------------------------