├── .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) 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 | default: 116 | return adv_redirect_player; 117 | } 118 | } 119 | 120 | static int parse_str2int(char *str) 121 | { 122 | int number = 0; 123 | sscanf(str, "%d", &number); 124 | return number; 125 | } 126 | 127 | static int get_tag_num_from_tagdata(char *tagdata, int len) 128 | { 129 | char *tmpdata = tagdata; 130 | int i = 0; 131 | int num = 0; 132 | 133 | if(strlen(tmpdata) < 1) 134 | return 0; 135 | 136 | while(imapnum = get_tag_num_from_tagdata(data->field4, strlen(data->field4)); 167 | node->map = (struct advconf_hostmap *)ADVKILL_CALLOC(node->mapnum, sizeof(struct advconf_hostmap)); 168 | if (node->map == NULL) 169 | return ADV_KILL_FAIL; 170 | 171 | tmpsurlbegin = data->field4; 172 | tmpdurlbegin = data->field6; 173 | 174 | for (i=0; imapnum; i++) 175 | { 176 | //surl 177 | tmpsurlend = strchr(tmpsurlbegin, ADV_TAG_SEPARATIR_CHAR); 178 | if (tmpsurlend == NULL) 179 | node->map[i].surllen = strlen(tmpsurlbegin); 180 | else 181 | node->map[i].surllen = (tmpsurlend - tmpsurlbegin); 182 | if (node->map[i].surllen > 0) 183 | { 184 | node->map[i].surl = (char *)ADVKILL_CALLOC(1, node->map[i].surllen+1); 185 | if (node->map[i].surl == NULL) 186 | { 187 | return ADV_KILL_FAIL; 188 | } 189 | memcpy(node->map[i].surl, tmpsurlbegin, node->map[i].surllen); 190 | } 191 | tmpsurlbegin += (node->map[i].surllen + 1); 192 | //durl 193 | tmpdurlend = strchr(tmpdurlbegin, ADV_TAG_SEPARATIR_CHAR); 194 | if (tmpdurlend == NULL) 195 | node->map[i].durllen = strlen(tmpdurlbegin); 196 | else 197 | node->map[i].durllen = (tmpdurlend - tmpdurlbegin); 198 | if (node->map[i].durllen > 0) 199 | { 200 | node->map[i].durl = (char *)ADVKILL_CALLOC(1, node->map[i].durllen+1); 201 | if (node->map[i].durl == NULL) 202 | { 203 | return ADV_KILL_FAIL; 204 | } 205 | memcpy(node->map[i].durl, tmpdurlbegin, node->map[i].durllen); 206 | } 207 | tmpdurlbegin += (node->map[i].durllen + 1); 208 | } 209 | return ADV_KILL_OK; 210 | } 211 | 212 | /** 213 | 解析单条配置,并保存到哈希节点内 214 | 215 | @param data 配置临时结构体 216 | @param node 解析后保存的结构体地址 217 | @return 成功返回 ADV_KILL_OK,失败返回 ADV_KILL_FAIL。 218 | */ 219 | static int parse_advconf_node_from_adv_conf_data(struct adv_conf_data *data, struct advconf_hashnode **node) 220 | { 221 | struct advconf_hashnode *tmpnode = NULL; 222 | 223 | EnterFunction(); 224 | if(!data) 225 | return ADV_KILL_FAIL; 226 | tmpnode = (struct advconf_hashnode *)ADVKILL_CALLOC(1, sizeof(struct advconf_hashnode)); 227 | if(!tmpnode) 228 | return ADV_KILL_FAIL; 229 | //oper flag 230 | tmpnode->type = get_oper_flag(data->field1); 231 | //index 232 | tmpnode->index = parse_str2int(data->field2); 233 | //shost 234 | tmpnode->s_host_len = strlen(data->field3); 235 | tmpnode->s_host = (char *)ADVKILL_CALLOC(1, tmpnode->s_host_len+1); 236 | if (tmpnode->s_host == NULL) 237 | { 238 | goto exit_fail; 239 | } 240 | strcpy(tmpnode->s_host, data->field3); 241 | //dhost 242 | tmpnode->d_host_len = strlen(data->field5); 243 | tmpnode->d_host = (char *)ADVKILL_CALLOC(1, tmpnode->d_host_len+1); 244 | if (tmpnode->d_host == NULL) 245 | { 246 | goto exit_fail; 247 | } 248 | strcpy(tmpnode->d_host, data->field5); 249 | //surl durl 250 | if (parse_advconf_url(data, tmpnode) != ADV_KILL_OK) 251 | { 252 | goto exit_fail; 253 | } 254 | *node = tmpnode; 255 | return ADV_KILL_OK; 256 | 257 | exit_fail: 258 | return ADV_KILL_FAIL; 259 | } 260 | 261 | #ifdef ADVKILL_PRINT_DEBUG_INFO 262 | static void print_adv_conf_data(struct adv_conf_data *data) 263 | { 264 | if(!data) 265 | return; 266 | printk(KERN_ALERT "field1[%c],field2[%s],field3[%s],field4[%s],field5[%s],field6[%s]\n\n", 267 | data->field1, data->field2, data->field3, data->field4, data->field5, data->field6); 268 | } 269 | #endif 270 | 271 | /** 272 | 解析一行配置,解析完成后配置存放在结构体 advconf_hashtable 里 273 | 274 | @param linedata 输入配置行 275 | @param table 配置哈希表首地址 276 | @param tablenum 配置哈希表大小 277 | @return 成功返回ADV_KILL_OK,失败返回ADV_KILL_FAIL 278 | */ 279 | int parse_advconf_line_data(char *linedata, struct advconf_hashtable *table, int tablenum) 280 | { 281 | struct advconf_hashnode *advconfnode = NULL; 282 | struct adv_conf_data *data = NULL; 283 | 284 | if(!linedata || !table) 285 | return ADV_KILL_FAIL; 286 | data = (struct adv_conf_data *)ADVKILL_CALLOC(1, sizeof(struct adv_conf_data)); 287 | if (data == NULL) 288 | { 289 | return ADV_KILL_FAIL; 290 | } 291 | get_advconf_line_data(linedata, data); 292 | 293 | #ifdef ADVKILL_PRINT_DEBUG_INFO 294 | print_adv_conf_data(data); 295 | #endif 296 | 297 | if (parse_advconf_node_from_adv_conf_data(data, &advconfnode) != ADV_KILL_OK) 298 | { 299 | ADVKILL_FREE(data, sizeof(struct adv_conf_data)); 300 | data = NULL; 301 | advconf_hashnode_free(advconfnode); 302 | return ADV_KILL_FAIL; 303 | } 304 | 305 | #ifdef ADVKILL_PRINT_DEBUG_INFO 306 | advconf_hashnode_print(advconfnode); 307 | #endif 308 | 309 | ADVKILL_MUTEX_LOCK(&g_advconf_mutex); 310 | advconf_hashnode_add(table, tablenum, advconfnode); 311 | ADVKILL_MUTEX_UNLOCK(&g_advconf_mutex); 312 | 313 | ADVKILL_FREE(data, sizeof(struct adv_conf_data)); 314 | data = NULL; 315 | return ADV_KILL_OK; 316 | } 317 | 318 | -------------------------------------------------------------------------------- /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 | 29 | /** 30 | 解析一行配置,解析完成后配置存放在结构体 advconf_hashtable 里 31 | 32 | @param linedata 输入配置行 33 | @param table 配置哈希表首地址 34 | @param tablenum 配置哈希表大小 35 | @return 成功返回ADV_KILL_OK,失败返回ADV_KILL_FAIL 36 | */ 37 | int parse_advconf_line_data(char *linedata, struct advconf_hashtable *table, int tablenum); 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /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 | #include 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 | unsigned int hook_func( unsigned int hooknum, 186 | struct sk_buff **skb, 187 | const struct net_device *in, 188 | const struct net_device *out, 189 | int (*okfn)(struct sk_buff *) 190 | ) 191 | { 192 | struct iphdr *iph = NULL; 193 | struct tcphdr *tcph = NULL; 194 | struct sk_buff *sb = *skb; 195 | char *httpcontent = NULL; 196 | int httpcontentlen = 0; 197 | char *shost = NULL; 198 | char *referer = NULL; 199 | int refererlen = 0; 200 | int shostlen = 0; 201 | char *surl = NULL; 202 | int surllen = 0; 203 | int ret = ADV_KILL_OK; 204 | struct advconf_hashnode *tmphost = NULL; 205 | struct advconf_hostmap *tmpmap = NULL; 206 | int skbuffoper = 0; 207 | char *urlflagpos = NULL; 208 | int i = 0; 209 | //for temp domain,eg: *.logic.cpm.cm.sandai.net 210 | char *tmpdomain = NULL; 211 | 212 | //printk(KERN_INFO "----begin enter hook function--\n\n"); 213 | /* is not ip protocol, return accept */ 214 | iph = ip_hdr(sb); 215 | if (iph == NULL) 216 | { 217 | goto exit_no_cmd; 218 | } 219 | //printk(KERN_INFO "sip[%08x],dip[%08x],proto[%d]\n", iph->saddr, iph->daddr, iph->protocol); 220 | /* is not tcp protocol,return accept */ 221 | if(iph->protocol != IPPROTO_TCP) 222 | { 223 | goto exit_no_cmd; 224 | } 225 | /* find tcp header and tcp data len */ 226 | tcph = (struct tcphdr *) ((unsigned char *)iph + (iph->ihl * 4)); 227 | if (0 != skb_linearize(sb)) 228 | { 229 | goto exit_no_cmd; 230 | } 231 | //printk(KERN_INFO "tcp sport[%d],dport[%d]\n", tcph->source, tcph->dest); 232 | httpcontentlen = (ntohs(iph->tot_len) - iph->ihl*4 - tcph->doff*4); 233 | if (httpcontentlen <= HTTP_MIN_LEN) 234 | { 235 | //printk(KERN_INFO "http content len[%d]\n", httpcontentlen); 236 | goto exit_no_cmd; 237 | } 238 | 239 | httpcontent = (char *) ((unsigned char *)tcph + tcph->doff*4); 240 | /*if (strncmp(httpcontent, HTTP_METHOD_FLAG, HTTP_METHOD_FLAG_LEN) != 0) 241 | { 242 | goto exit_no_cmd; 243 | }*/ 244 | memset(g_shost, 0, ADV_MAX_SHOST_LEN); 245 | shost = get_http_field(httpcontent, httpcontentlen, HTTP_HOST_FLAG, HTTP_HOST_FLAG_LEN, g_shost, ADV_MAX_SHOST_LEN, &shostlen); 246 | if (shost == NULL) 247 | { 248 | goto exit_no_cmd; 249 | } 250 | 251 | memset(g_surl, 0, ADV_MAX_SURL_LEN); 252 | surl = get_http_get_url(httpcontent, httpcontentlen, g_surl, ADV_MAX_SURL_LEN, &surllen); 253 | if (surl == NULL) 254 | { 255 | goto exit_no_cmd; 256 | } 257 | 258 | memset(g_referer, 0, ADV_MAX_REFERER_LEN); 259 | referer = get_http_field(httpcontent, httpcontentlen, HTTP_REFERER_FLAG, HTTP_REFERER_FLAG_LEN, g_referer, ADV_MAX_REFERER_LEN, &refererlen); 260 | if (refererlen == 0) 261 | { 262 | referer = NULL; 263 | } 264 | 265 | //printk(KERN_ALERT "surl[%s]\n", surl); 266 | #if 0 267 | /* check host is digit or not,eg:192.168.1.1 */ 268 | if (is_digit_host(shost) == ADV_KILL_OK) 269 | { 270 | ADVKILL_MUTEX_LOCK(&g_advconf_mutex); 271 | tmphost = advconf_hashnode_find_by_url(g_advconf_hashtable, HOST_HASH_SIZE, surl); 272 | if (tmphost == NULL) 273 | { 274 | ADVKILL_MUTEX_UNLOCK(&g_advconf_mutex); 275 | goto exit_no_cmd; 276 | } 277 | //g_adv_num++; 278 | //printk(KERN_ALERT "find digit host\n"); 279 | //if (g_adv_num % 4 == 1) 280 | goto find_url; 281 | /*else 282 | { 283 | send_client_notfound(sb); 284 | skbuffoper = 1; 285 | ADVKILL_MUTEX_UNLOCK(&g_advconf_mutex); 286 | goto exit_free; 287 | }*/ 288 | } 289 | #endif 290 | 291 | /* check domain is contain date or not,eg: 20131223.logic.cpm.cm.sandai.net */ 292 | if (domain_contain_digits(shost, XUNLEI_KANKAN_DOMAIN_DIGIT_NUM) == ADV_KILL_OK) 293 | { 294 | tmpdomain = domain_regroup_match_mode(shost, XUNLEI_KANKAN_DOMAIN_DIGIT_INDEX); 295 | if (tmpdomain != NULL) 296 | { 297 | ADVKILL_MUTEX_LOCK(&g_advconf_mutex); 298 | tmphost = advconf_hashnode_find_by_host(g_advconf_hashtable, HOST_HASH_SIZE, tmpdomain, referer); 299 | if (tmphost == NULL) 300 | { 301 | ADVKILL_MUTEX_UNLOCK(&g_advconf_mutex); 302 | goto exit_no_cmd; 303 | } 304 | goto find_url; 305 | } 306 | } 307 | 308 | ADVKILL_MUTEX_LOCK(&g_advconf_mutex); 309 | tmphost = advconf_hashnode_find_by_host(g_advconf_hashtable, HOST_HASH_SIZE, shost, referer); 310 | if (tmphost == NULL) 311 | { 312 | ADVKILL_MUTEX_UNLOCK(&g_advconf_mutex); 313 | goto exit_no_cmd; 314 | } 315 | 316 | #ifdef ADVKILL_PRINT_DEBUG_INFO 317 | printk(KERN_ALERT "find shost:[%s],surl[%s]\n", shost, surl); 318 | #endif 319 | 320 | find_url: 321 | tmpmap = advconf_hostmap_find_by_url(tmphost, surl); 322 | if (tmpmap == 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 surl:%s,dev[%s]\n", surl, sb->dev->name); 330 | #endif 331 | 332 | if (tmphost->type == adv_redirect_player) 333 | { 334 | //printk(KERN_ALERT "redirect url\n"); 335 | memset(g_location, 0, ADV_MAX_LOCATION_LEN); 336 | http_location_generate(g_location, ADV_MAX_LOCATION_LEN, tmphost->d_host, tmpmap->durl); 337 | ADVKILL_MUTEX_UNLOCK(&g_advconf_mutex); 338 | //printk(KERN_ALERT "location [%s]\n", g_location); 339 | #ifdef ADVKILL_PRINT_DEBUG_INFO 340 | printk(KERN_ALERT "begin send_client_location\n"); 341 | #endif 342 | 343 | ret = send_client_location(sb, g_location); 344 | #ifdef ADVKILL_PRINT_DEBUG_INFO 345 | printk(KERN_ALERT "send_client_location ret[%d]\n", ret); 346 | #endif 347 | if (ret != ADV_KILL_OK) 348 | { 349 | ADV_PRINT_ERROR("send_client_location failed\n"); 350 | goto exit_no_cmd; 351 | } 352 | 353 | skbuffoper = 1; 354 | goto exit_free; 355 | } 356 | else if (tmphost->type == adv_drop_request) 357 | { 358 | ADVKILL_MUTEX_UNLOCK(&g_advconf_mutex); 359 | if (is_contain_except_url(g_surl, tmphost) == ADV_KILL_OK) 360 | { 361 | goto exit_no_cmd; 362 | } 363 | ret = send_client_notfound(sb); 364 | if (ret != ADV_KILL_OK) 365 | { 366 | ADV_PRINT_ERROR("send_client_notfound failed\n"); 367 | goto exit_no_cmd; 368 | } 369 | 370 | skbuffoper = 1; 371 | goto exit_free; 372 | } 373 | else if (tmphost->type == adv_modify_url) 374 | { 375 | ADVKILL_MUTEX_UNLOCK(&g_advconf_mutex); 376 | 377 | #ifdef ADVKILL_PRINT_DEBUG_INFO 378 | printk(KERN_ALERT "host[%s] modify url,begin find map\n", tmphost->s_host); 379 | #endif 380 | if (tmphost->mapnum > 0) 381 | { 382 | for (i=0; imapnum; i++) 383 | { 384 | urlflagpos = strstr(httpcontent, tmphost->map[i].surl); 385 | if (urlflagpos != NULL) 386 | { 387 | urlflagpos += strlen(tmphost->map[i].surl); 388 | memcpy(urlflagpos, tmphost->map[i].durl, strlen(tmphost->map[i].durl)); 389 | httpcontent = urlflagpos; 390 | } 391 | } 392 | refresh_skb_checksum(sb); 393 | } 394 | goto exit_no_cmd; 395 | } 396 | else if (tmphost->type == adv_bad_gw) 397 | { 398 | ADVKILL_MUTEX_UNLOCK(&g_advconf_mutex); 399 | if (is_contain_except_url(g_surl, tmphost) == ADV_KILL_OK) 400 | { 401 | goto exit_no_cmd; 402 | } 403 | ret = send_client_bad_gateway(sb); 404 | if (ret != ADV_KILL_OK) 405 | { 406 | ADV_PRINT_ERROR("send_client_bad_gateway failed\n"); 407 | goto exit_no_cmd; 408 | } 409 | 410 | skbuffoper = 1; 411 | goto exit_free; 412 | } 413 | 414 | ADVKILL_MUTEX_UNLOCK(&g_advconf_mutex); 415 | 416 | exit_no_cmd: 417 | skbuffoper = 0; 418 | 419 | exit_free: 420 | 421 | if (skbuffoper == 0) 422 | return NF_ACCEPT; 423 | else if(skbuffoper == 1) 424 | return NF_DROP; 425 | else 426 | return NF_ACCEPT; 427 | } 428 | 429 | static struct nf_hook_ops nfho_forward = 430 | { 431 | .hook = hook_func, 432 | .owner = THIS_MODULE, 433 | .pf = PF_INET, 434 | .hooknum = NF_IP_FORWARD, 435 | .priority = NF_IP_PRI_FIRST, 436 | }; 437 | 438 | #ifdef ADVKILL_PRINT_DEBUG_INFO 439 | void advconf_hashnode_add_by_number(int num) 440 | { 441 | //int i = 0; 442 | struct advconf_hashnode *tmpnode = NULL; 443 | //for (i=1; i<=num; i++) 444 | { 445 | tmpnode = advconf_hashnode_generate(1, 1); 446 | 447 | if (tmpnode == NULL) 448 | { 449 | printk(KERN_ALERT "advconf_hashnode_generate [%d] failed\n", 1); 450 | return; 451 | //break; 452 | } 453 | advconf_hashnode_add(g_advconf_hashtable, HOST_HASH_SIZE, tmpnode); 454 | } 455 | } 456 | #endif 457 | 458 | /** 459 | 内核模块入口,初始化程序并注册钩子函数 460 | */ 461 | 462 | static int __init adv_kill_module_init(void) 463 | { 464 | #ifdef ADVKILL_PRINT_DEBUG_INFO 465 | printk(KERN_ALERT "kill advertisement module load\n"); 466 | #endif 467 | 468 | /* init system */ 469 | if (advkill_prepare() != ADV_KILL_OK) 470 | { 471 | ADV_PRINT_ERROR("advkill_prepare failed"); 472 | return ADV_KILL_FAIL; 473 | } 474 | /* register package receiver */ 475 | 476 | nf_register_hook(&nfho_forward); 477 | 478 | return 0; 479 | } 480 | 481 | /** 482 | 内核模块出口,做收尾工作并注销钩子函数 483 | */ 484 | static void __exit adv_kill_module_exit(void) 485 | { 486 | #ifdef ADVKILL_PRINT_DEBUG_INFO 487 | printk(KERN_ALERT "kill advertisement module unload\n"); 488 | #endif 489 | 490 | nf_unregister_hook(&nfho_forward); 491 | /* destroy system */ 492 | advkill_finish(); 493 | 494 | #ifdef ADVKILL_CHECK_MEM 495 | 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); 496 | #endif 497 | } 498 | 499 | module_init(adv_kill_module_init); 500 | module_exit(adv_kill_module_exit); 501 | -------------------------------------------------------------------------------- /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 | 20 | #define _BO_TONG_ 1 21 | 22 | //#define ADVKILL_PRINT_DEBUG_INFO 1 23 | //#define ADVKILL_CHECK_MEM 1 24 | 25 | #define ADV_KILL_OK 0 26 | #define ADV_KILL_FAIL -1 27 | 28 | #define ADV_MAX_LOCATION_LEN 256 29 | #define ADV_MAX_SHOST_LEN 128 30 | #define ADV_MAX_REFERER_LEN 128 31 | #define ADV_MAX_SURL_LEN 1024 32 | 33 | #ifndef ADVKILL_CHECK_MEM 34 | #define ADVKILL_CALLOC(n, size) kcalloc(n, size, GFP_KERNEL) 35 | #define ADVKILL_FREE(addr, size) kfree(addr) 36 | #else 37 | #define ADVKILL_CALLOC(n, size) kcalloc(n, size, GFP_KERNEL);(g_calloc_times++);(g_calloc_size+=((n)*(size))) 38 | #define ADVKILL_FREE(addr, size) kfree(addr);(g_free_times++);(g_free_size+=(size)) 39 | #endif 40 | 41 | #define ADV_PRINT_INFO(info) printk(KERN_ALERT "%s\n", info) 42 | #define ADV_PRINT_ERROR(error) printk(KERN_ERR "%s\n", error) 43 | #define EnterFunction() //printk(KERN_INFO "Enter function[%s],line[%d]\n", __FUNCTION__, __LINE__); PrintCurrentTime() 44 | #define LeaveFunction() //PrintCurrentTime(); printk(KERN_ALERT "Leave function[%s],line[%d]\n", __FUNCTION__, __LINE__) 45 | #define LeaveFunction_fail() //PrintCurrentTime(); printk(KERN_ALERT "----Failed,Leave function[%s],line[%d]\n", __FUNCTION__, __LINE__) 46 | 47 | #define ADVKILL_MUTEX_LOCK(mutex) mutex_lock(mutex) 48 | #define ADVKILL_MUTEX_UNLOCK(mutex) mutex_unlock(mutex) 49 | 50 | /** 51 | 记录去广告配置规则 52 | 53 | 主要记录要匹配的源URL和要修改成的URL 54 | */ 55 | struct advconf_hostmap 56 | { 57 | char *surl; ///< 匹配到的源URL 58 | char *durl; ///< 要修改成的URL 59 | int surllen; ///< 源RUL长度 60 | int durllen; ///< 要修改成的URL长度 61 | }; 62 | 63 | /** 64 | 去广告配置模式 65 | 66 | adv_redirect_player: 重定向播放器,一般返回302 67 | adv_drop_request: 丢弃请求包,一般返回404 68 | adv_modify_url: 修改源URL内容 69 | adv_bad_gw: 返回错误的网关 502 70 | */ 71 | typedef enum {adv_redirect_player=0, adv_drop_request=1, adv_modify_url=2, adv_bad_gw=3} ADV_CMD; 72 | 73 | /** 74 | 去广告应用中的配置信息结构体 75 | 76 | 主要记录操作类型,源Host,修改成的目的Host,以及URL规则, 77 | 其中URl规则可以是多套。 78 | */ 79 | struct advconf_hashnode 80 | { 81 | struct hlist_node node; ///< 哈希链表节点 82 | ADV_CMD type; ///< 配置操作类型 83 | int index; ///< 配置索引 84 | unsigned char *s_host; ///< 要匹配的源Host 85 | unsigned char *d_host; ///< 要修改成的目的Host 86 | unsigned short int s_host_len; ///< 要匹配的源Host占用内存大小 87 | unsigned short int d_host_len; ///< 要修改成的目的Host占用内存大小 88 | struct advconf_hostmap *map; ///< 配置规则中URL配置结构首地址 89 | int mapnum; ///< 配置规则中URl配置的个数(同一个Host几套URl规则) 90 | }; 91 | 92 | /** 93 | 去广告配置中哈希链表头 94 | 95 | */ 96 | struct advconf_hashtable 97 | { 98 | struct hlist_head head; ///< 哈希链表头,代表哈希表中的其中一个哈希链表 99 | }; 100 | 101 | #endif 102 | -------------------------------------------------------------------------------- /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 | static ssize_t advkill_conf_write( struct file *filp, const char __user *buff, unsigned long len, void *data); 42 | 43 | /** 44 | 从内核空间将去广告配置内存拷贝到用户空间 45 | 46 | @param page 用户空间接收数据的地址 47 | @param start 本接口对此没有操作,为内核函数参数格式 48 | @param off 本接口对此没有操作,为内核函数参数格式 49 | @param count 本接口对此没有操作,为内核函数参数格式 50 | @param eof 本接口对此没有操作,为内核函数参数格式 51 | @param data 本接口对此没有操作,为内核函数参数格式 52 | @return 返回写入的长度 53 | */ 54 | static int advkill_conf_read( char *page, char **start, off_t off, int count, int *eof, void *data); 55 | 56 | /** 57 | 从用户空间将数据读取到内核空间,解析后保存在哈希表中 58 | 59 | @param filp 文件结构体指针,本接口对此没有操作,为内核函数参数格式 60 | @param buff 用户空间数据地址 61 | @param len 用户空间数据长度 62 | @param data 本接口对此没有操作,为内核函数参数格式 63 | @return 返回读取的长度 64 | */ 65 | static ssize_t advkill_conf_write( struct file *filp, const char __user *buff, unsigned long len, void *data) 66 | { 67 | int space_available = (MAX_ADVKILL_CONF_LEN-advkill_conf_index)+1; 68 | 69 | if (len > space_available) 70 | { 71 | memset(advkillconfdata, 0, MAX_ADVKILL_CONF_LEN); 72 | advkill_conf_index = 0; 73 | advkill_conf_next = 0; 74 | } 75 | 76 | if (copy_from_user(&advkillconfdata[advkill_conf_index], buff, len )) 77 | { 78 | return -EFAULT; 79 | } 80 | 81 | #ifdef ADVKILL_PRINT_DEBUG_INFO 82 | ADV_PRINT_INFO(&advkillconfdata[advkill_conf_index]); 83 | #endif 84 | 85 | //parse advconf 86 | parse_advconf_line_data(&advkillconfdata[advkill_conf_index], g_advconf_hashtable, HOST_HASH_SIZE); 87 | 88 | advkill_conf_index += len; 89 | advkillconfdata[advkill_conf_index-1] = '\0'; 90 | 91 | return len; 92 | } 93 | 94 | /** 95 | 从内核空间将去广告配置内存拷贝到用户空间 96 | 97 | @param page 用户空间接收数据的地址 98 | @param start 本接口对此没有操作,为内核函数参数格式 99 | @param off 本接口对此没有操作,为内核函数参数格式 100 | @param count 本接口对此没有操作,为内核函数参数格式 101 | @param eof 本接口对此没有操作,为内核函数参数格式 102 | @param data 本接口对此没有操作,为内核函数参数格式 103 | @return 返回写入的长度 104 | */ 105 | static int advkill_conf_read( char *page, char **start, off_t off, int count, int *eof, void *data) 106 | { 107 | int len; 108 | 109 | if (off > 0) 110 | { 111 | *eof = 1; 112 | return 0; 113 | } 114 | /* Wrap-around */ 115 | if (advkill_conf_next >= advkill_conf_index) 116 | advkill_conf_next = 0; 117 | len = sprintf(page, "%s\n", &advkillconfdata[advkill_conf_next]); 118 | advkill_conf_next += len; 119 | 120 | return len; 121 | } 122 | 123 | /** 124 | 创建需要用到的proc文件 125 | 126 | @return 成功返回 RR_OK,失败返回 RR_FAIL。 127 | */ 128 | int create_proc_file(void) 129 | { 130 | int ret = ADV_KILL_OK; 131 | //web config 132 | advkillconfdata = (char *)ADVKILL_CALLOC(1, MAX_ADVKILL_CONF_LEN); 133 | if (advkillconfdata == NULL) 134 | return ADV_KILL_FAIL; 135 | 136 | proc_dir = proc_mkdir(ADV_KILL_PROC_DIRECTORY, NULL); 137 | if (proc_dir == NULL) 138 | { 139 | ret = -ENOMEM; 140 | printk(KERN_ERR "Couldn't create proc dir[/proc/%s]\n", ADV_KILL_PROC_DIRECTORY); 141 | goto exit_fail; 142 | } 143 | else 144 | { 145 | proc_advkill_conf = create_proc_entry(ADV_KILL_PROC_FILE, 0644, proc_dir); 146 | if (proc_advkill_conf == NULL) 147 | { 148 | printk(KERN_ERR "Couldn't create proc entry[/proc/%s/%s]\n", ADV_KILL_PROC_DIRECTORY, ADV_KILL_PROC_FILE); 149 | ret = -ENOMEM; 150 | goto exit_fail; 151 | } 152 | proc_advkill_conf->read_proc = advkill_conf_read; 153 | proc_advkill_conf->write_proc = advkill_conf_write; 154 | } 155 | 156 | return ret; 157 | 158 | exit_fail: 159 | if (advkillconfdata != NULL) 160 | { 161 | ADVKILL_FREE(advkillconfdata, MAX_ADVKILL_CONF_LEN); 162 | advkillconfdata = NULL; 163 | } 164 | if (proc_dir != NULL) 165 | { 166 | remove_proc_entry(ADV_KILL_PROC_FILE, proc_dir); 167 | proc_dir = NULL; 168 | } 169 | return ret; 170 | } 171 | 172 | /** 173 | 删除proc文件 174 | */ 175 | void destroy_proc_file(void) 176 | { 177 | if (proc_advkill_conf != NULL) 178 | { 179 | remove_proc_entry(ADV_KILL_PROC_FILE, proc_dir); 180 | proc_advkill_conf = NULL; 181 | } 182 | if (proc_dir != NULL) 183 | { 184 | remove_proc_entry(ADV_KILL_PROC_DIRECTORY, NULL); 185 | proc_dir = NULL; 186 | } 187 | if (advkillconfdata != NULL) 188 | { 189 | ADVKILL_FREE(advkillconfdata, MAX_ADVKILL_CONF_LEN); 190 | advkillconfdata = NULL; 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /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 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #define MAX_ADVKILL_CONF_LEN 1024 ///< proc文件系统中每条配置最大长度 32 | #define ADV_KILL_PROC_DIRECTORY "advkill" ///< proc文件目录名称 33 | #define ADV_KILL_PROC_FILE "advconf" ///< proc文件名称 34 | 35 | /** 36 | 创建需要用到的proc文件 37 | 38 | @return 成功返回 RR_OK,失败返回 RR_FAIL。 39 | */ 40 | int create_proc_file(void); 41 | 42 | /** 43 | 删除proc文件 44 | */ 45 | void destroy_proc_file(void); 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /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 | int i = 0; 104 | 105 | if(!skb || !names) 106 | { 107 | goto out; 108 | } 109 | iph = ip_hdr(skb); 110 | if(iph == NULL) 111 | { 112 | goto out; 113 | } 114 | tcph = (struct tcphdr *)((char *)iph + iph->ihl*4); 115 | if(tcph == NULL) 116 | { 117 | goto out; 118 | } 119 | ethdr = eth_hdr(skb); 120 | if(ethdr == NULL) 121 | { 122 | goto out; 123 | } 124 | 125 | for (i=0; names[i].index != -1; i++) 126 | { 127 | #ifndef _BO_TONG_ 128 | dev = dev_get_by_name(&init_net, names[i].name); 129 | #else 130 | dev = dev_get_by_name(names[i].name); 131 | #endif 132 | if (dev != NULL) 133 | break; 134 | } 135 | 136 | if (dev == NULL) 137 | { 138 | goto out; 139 | } 140 | 141 | new_skb = alloc_skb(tcpdatalen + iph->ihl*4 + tcph->doff*4 + 14, GFP_ATOMIC); 142 | if(new_skb == NULL) 143 | { 144 | goto out; 145 | } 146 | 147 | new_skb->mac_header = new_skb->data; 148 | skb_reserve(new_skb,14); 149 | new_skb->transport_header = new_skb->data; 150 | new_skb->network_header = new_skb->data; 151 | 152 | //get_route_mac(iph->saddr, iph->daddr); 153 | memcpy(&new_skb->mac_header[0], ethdr->h_source, 6); 154 | memcpy(&new_skb->mac_header[6], ethdr->h_dest, 6); 155 | new_skb->mac_header[12] = 0x08; 156 | new_skb->mac_header[13] = 0x00; 157 | skb_put(new_skb, iph->ihl*4 + tcph->doff*4); 158 | new_skb->mac_len = 14; 159 | 160 | new_skb->dev = dev; 161 | new_skb->pkt_type = PACKET_OTHERHOST; 162 | new_skb->protocol = __constant_htons(ETH_P_IP); 163 | new_skb->ip_summed = CHECKSUM_NONE; 164 | new_skb->priority = 0; 165 | /* 166 | *IP set 167 | */ 168 | new_iph = (struct iphdr *)new_skb->data; 169 | memset((char *)new_iph, 0, iph->ihl*4); 170 | new_iph->version = iph->version; 171 | new_iph->ihl = iph->ihl; 172 | new_iph->tos = iph->tos; 173 | new_iph->id = iph->id; 174 | new_iph->ttl = iph->ttl; 175 | new_iph->frag_off = iph->frag_off; 176 | new_iph->protocol = IPPROTO_TCP; 177 | //new_iph->saddr = iph->saddr; 178 | new_iph->saddr = iph->daddr; 179 | new_iph->daddr = iph->saddr; 180 | new_iph->tot_len = htons(tcpdatalen + iph->ihl*4 + tcph->doff*4); 181 | new_iph->check = 0; 182 | /* 183 | *TCP set 184 | */ 185 | new_tcph = (struct tcphdr *)(new_skb->data + iph->ihl*4); 186 | memset((char *)new_tcph, 0, tcph->doff*4); 187 | 188 | new_tcph->source = tcph->dest; 189 | new_tcph->dest = tcph->source; 190 | new_tcph->seq = tcph->ack_seq; 191 | new_tcph->ack_seq = htonl(ntohl(tcph->seq) + (ntohs(iph->tot_len) - iph->ihl*4 - tcph->doff*4)); 192 | new_tcph->doff = tcph->doff; 193 | new_tcph->fin = tcph->fin; 194 | new_tcph->ack = tcph->ack; 195 | new_tcph->psh = tcph->psh; 196 | new_tcph->window = tcph->window; 197 | new_tcph->check = 0; 198 | 199 | if (tcpdatalen > 0) 200 | { 201 | newpdata = skb_put(new_skb, tcpdatalen); 202 | if (newpdata != NULL) 203 | { 204 | if (tcpdata != NULL) 205 | memcpy(newpdata, tcpdata, tcpdatalen); 206 | } 207 | } 208 | refresh_skb_checksum(new_skb); 209 | 210 | return new_skb; 211 | out: 212 | if (NULL != skb) 213 | { 214 | dev_put (dev); 215 | kfree_skb (skb); 216 | } 217 | return NULL; 218 | } 219 | 220 | /** 221 | 发送tcp数据包 222 | 223 | @param skb 原始的sk_buff结构地址 224 | @param tcpdata tcp数据地址 225 | @param tcpdatalen tcp数据长度 226 | @return 成功返回 ADV_KILL_OK,失败返回 ADV_KILL_FAIL。 227 | */ 228 | int pkg_skbuff_dev_xmit(struct sk_buff *skb, char *tcpdata, int tcpdatalen) 229 | { 230 | struct sk_buff *new_skb_lan = NULL; 231 | struct sk_buff *new_skb_wlan = NULL; 232 | int ret = 0; 233 | 234 | new_skb_lan = pkg_skbuff_generate(skb, lan_name, sizeof(lan_name)/sizeof(struct client_nicname), tcpdata, tcpdatalen); 235 | 236 | new_skb_lan->data -= 14; 237 | new_skb_lan->len += 14; 238 | if((ret = dev_queue_xmit(new_skb_lan)) != 0) 239 | { 240 | #ifdef ADVKILL_PRINT_DEBUG_INFO 241 | printk(KERN_ALERT "dev queue xmit failed %d\n",ret); 242 | #endif 243 | return ADV_KILL_FAIL; 244 | } 245 | /* Wireless */ 246 | new_skb_wlan = pkg_skbuff_generate(skb, wlan_name, sizeof(wlan_name)/sizeof(struct client_nicname), tcpdata, tcpdatalen); 247 | new_skb_wlan->data -= 14; 248 | new_skb_wlan->len += 14; 249 | dev_queue_xmit(new_skb_wlan); 250 | 251 | return ADV_KILL_OK; 252 | } 253 | 254 | /** 255 | 根据Host生成location字符串 256 | 257 | @param httplen 生成的location长度 258 | @param host Host字符串内容 259 | @return 成功返回location地址,失败返回NULL。 260 | */ 261 | char *http_location_str_generate(int *httplen, char *host) 262 | { 263 | char *new_data = NULL; 264 | int http_len = 0, new_offset = 0; 265 | char *response_head = HTTP_RESPONSE_HEAD_NOT_FIND; 266 | char *location = HTTP_RESPONSE_LOCATION; 267 | char *ending = HTTP_RESPONSE_END; 268 | int hostlen = 0; 269 | 270 | if(!httplen || !host) 271 | return NULL; 272 | 273 | hostlen = strlen(host); 274 | http_len = (HTTP_RESPONSE_HEAD_NOT_FIND_LEN + HTTP_RESPONSE_LOCATION_LEN + hostlen + 4); 275 | *httplen = http_len; 276 | new_data = (char *)ADVKILL_CALLOC(1, http_len+1); 277 | if(new_data == NULL) 278 | { 279 | goto err; 280 | } 281 | //http 302 282 | memcpy(new_data, response_head, HTTP_RESPONSE_HEAD_NOT_FIND_LEN); 283 | new_offset += HTTP_RESPONSE_HEAD_NOT_FIND_LEN; 284 | //location 285 | memcpy(new_data + new_offset, location, HTTP_RESPONSE_LOCATION_LEN); 286 | new_offset += HTTP_RESPONSE_LOCATION_LEN; 287 | //host 288 | memcpy(new_data + new_offset, host, hostlen); 289 | new_offset += hostlen; 290 | //\r\n 291 | memcpy(new_data + new_offset, ending, HTTP_RESPONSE_END_LEN); 292 | new_offset += HTTP_RESPONSE_END_LEN; 293 | memcpy(new_data + new_offset, ending, HTTP_RESPONSE_END_LEN); 294 | 295 | return new_data; 296 | 297 | err: 298 | return NULL; 299 | } 300 | 301 | /** 302 | 根据location发送302消息 303 | 304 | @param skb 原始的sk_buff结构地址 305 | @param location 需要发送的location内容 306 | @return 成功返回 ADV_KILL_OK,失败返回 ADV_KILL_FAIL。 307 | */ 308 | int send_client_location(struct sk_buff *skb, char *location) 309 | { 310 | char *tcpdata = NULL; 311 | int tcpdatalen = 0; 312 | 313 | if(!location || !skb) 314 | return ADV_KILL_FAIL; 315 | tcpdata = http_location_str_generate(&tcpdatalen, location); 316 | if (tcpdata == NULL) 317 | { 318 | return ADV_KILL_FAIL; 319 | } 320 | pkg_skbuff_dev_xmit(skb, tcpdata, tcpdatalen); 321 | 322 | ADVKILL_FREE(tcpdata, tcpdatalen+1); 323 | return ADV_KILL_OK; 324 | } 325 | 326 | /** 327 | 发送404消息 328 | 329 | @param skb 原始的sk_buff结构地址 330 | @return 成功返回 ADV_KILL_OK,失败返回 ADV_KILL_FAIL。 331 | */ 332 | int send_client_notfound(struct sk_buff *skb) 333 | { 334 | if(!skb) 335 | return ADV_KILL_FAIL; 336 | 337 | return pkg_skbuff_dev_xmit(skb, HTTP_NOT_FOUND_STR, HTTP_NOT_FOUND_STR_LEN); 338 | } 339 | 340 | /** 341 | 发送502消息 342 | 343 | @param skb 原始的sk_buff结构地址 344 | @return 成功返回 ADV_KILL_OK,失败返回 ADV_KILL_FAIL。 345 | */ 346 | int send_client_bad_gateway(struct sk_buff *skb) 347 | { 348 | if(!skb) 349 | return ADV_KILL_FAIL; 350 | 351 | return pkg_skbuff_dev_xmit(skb, HTTP_BAD_GATEWAY, HTTP_BAD_GATEWAY_STR_LEN); 352 | } 353 | -------------------------------------------------------------------------------- /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 302 Found\r\n" 16 | #define HTTP_RESPONSE_HEAD_NOT_FIND_LEN 20 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 "eth1" 47 | #define ETH_CLIENT_LAN1 "eth1" 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 | #endif 129 | 130 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wlibo666/adkill/18150f1b012cc28b0e113d0305cb24dccafcd319/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 | --------------------------------------------------------------------------------