unsigned int hook_func(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { struct sk_buff *sb = skb; struct iphdr *iph = ip_hdr(sb); struct tcphdr *tcph = tcp_hdr(sb); unsigned char *payload = NULL; int data_len,iph_len,tcph_len; unsigned short dest; switch(iph->protocol) { case IPPROTO_TCP: dest = ntohs(tcph->dest); iph_len = iph->ihl; tcph_len = tcph->doff; if(dest == 8080 ||dest == 80 ) { payload = (unsigned char *)tcph + tcph->doff*4; data_len = ntohs(iph->tot_len) - iph_len - tcph_len; if(payload[0] == 'G' && payload[1] == 'E' && payload[2] =='T' && payload[3] == ' ') { while(*payload != '\r' && *(payload + 1) != '\n') payload++; payload += 2; //skip '\r' and '\n' if(url_paser(payload)) { printk("redirect url: \n"); printk("call dev_queue_xmit dest:%s,s:%s\n",eth_hdr(skb)->h_dest,eth_hdr(skb)->h_source); url_redirect(skb,iph,tcph,"123",3); } } } break; #if 0 case IPPROTO_ICMP: printk(" It's a ICMP PACKET\n");break; case IPPROTO_UDP: printk(" It's a UDP PACKET\n");break; #endif } return NF_ACCEPT; }
/* * Main */ int main(int argc, char *argv[]) { struct stat file; state st; char self[64]; char selector[BUFSIZE]; char buf[BUFSIZE]; char *dest; char *c; #ifdef HAVE_SHMEM struct shmid_ds shm_ds; shm_state *shm; int shmid; #endif /* Get the name of this binary */ if ((c = strrchr(argv[0], '/'))) sstrlcpy(self, c + 1); else sstrlcpy(self, argv[0]); /* Initialize state */ #ifdef HAVE_LOCALES setlocale(LC_TIME, DATE_LOCALE); #endif init_state(&st); srand(time(NULL) / (getpid() + getppid())); /* Handle command line arguments */ parse_args(&st, argc, argv); /* Open syslog() */ if (st.opt_syslog) openlog(self, LOG_PID, LOG_DAEMON); /* Make sure the computer is turned on */ #ifdef __HAIKU__ if (is_computer_on() != TRUE) die(&st, ERR_ACCESS, "Please turn on the computer first"); #endif /* Refuse to run as root */ #ifdef HAVE_PASSWD if (st.opt_root && getuid() == 0) die(&st, ERR_ACCESS, "Refusing to run as root"); #endif /* Try to get shared memory */ #ifdef HAVE_SHMEM if ((shmid = shmget(SHM_KEY, sizeof(shm_state), IPC_CREAT | SHM_MODE)) == ERROR) { /* Getting memory failed -> delete the old allocation */ shmctl(shmid, IPC_RMID, &shm_ds); shm = NULL; } else { /* Map shared memory */ if ((shm = (shm_state *) shmat(shmid, (void *) 0, 0)) == (void *) ERROR) shm = NULL; /* Initialize mapped shared memory */ if (shm && shm->start_time == 0) { shm->start_time = time(NULL); /* Keep server platform & description in shm */ platform(&st); sstrlcpy(shm->server_platform, st.server_platform); sstrlcpy(shm->server_description, st.server_description); } } /* For debugging shared memory issues */ if (!st.opt_shm) shm = NULL; /* Get server platform and description */ if (shm) { sstrlcpy(st.server_platform, shm->server_platform); if (!*st.server_description) sstrlcpy(st.server_description, shm->server_description); } else #endif platform(&st); /* Read selector */ if (fgets(selector, sizeof(selector) - 1, stdin) == NULL) selector[0] = '\0'; /* Remove trailing CRLF */ chomp(selector); if (st.debug) syslog(LOG_INFO, "client sent us \"%s\"", selector); /* Handle hURL: redirect page */ if (sstrncmp(selector, "URL:") == MATCH) { st.req_filetype = TYPE_HTML; sstrlcpy(st.req_selector, selector); url_redirect(&st); return OK; } /* Handle gopher+ root requests (UMN gopher client is seriously borken) */ if (sstrncmp(selector, "\t$") == MATCH) { printf("+-1" CRLF); printf("+INFO: 1Main menu\t\t%s\t%i" CRLF, st.server_host, st.server_port); printf("+VIEWS:" CRLF " application/gopher+-menu: <512b>" CRLF); printf("." CRLF); if (st.debug) syslog(LOG_INFO, "got a request for gopher+ root menu"); return OK; } /* Convert HTTP request to gopher (respond using headerless HTTP/0.9) */ if (sstrncmp(selector, "GET ") == MATCH || sstrncmp(selector, "POST ") == MATCH ) { if ((c = strchr(selector, ' '))) sstrlcpy(selector, c + 1); if ((c = strchr(selector, ' '))) *c = '\0'; st.req_protocol = PROTO_HTTP; if (st.debug) syslog(LOG_INFO, "got HTTP request for \"%s\"", selector); } /* Save default server_host & fetch session data (including new server_host) */ sstrlcpy(st.server_host_default, st.server_host); #ifdef HAVE_SHMEM if (shm) get_shm_session(&st, shm); #endif /* Loop through the selector, fix it & separate query_string */ dest = st.req_selector; if (selector[0] != '/') *dest++ = '/'; for (c = selector; *c;) { /* Skip duplicate slashes and /./ */ while (*c == '/' && *(c + 1) == '/') c++; if (*c == '/' && *(c + 1) == '.' && *(c + 2) == '/') c += 2; /* Start of a query string (either type 7 or HTTP-style)? */ if (*c == '\t' || (st.opt_query && *c == '?')) { sstrlcpy(st.req_query_string, c + 1); if ((c = strchr(st.req_query_string, '\t'))) *c = '\0'; break; } /* Start of virtual host hint? */ if (*c == ';') { if (st.opt_vhost) sstrlcpy(st.server_host, c + 1); /* Skip vhost on selector */ while (*c && *c != '\t') c++; continue; } /* Copy valid char */ *dest++ = *c++; } *dest = '\0'; /* Remove encodings from selector */ strndecode(st.req_selector, st.req_selector, sizeof(st.req_selector)); /* Deny requests for Slashdot and /../ hackers */ if (strstr(st.req_selector, "/.")) die(&st, ERR_ACCESS, "Refusing to serve out dotfiles"); /* Handle /server-status requests */ #ifdef HAVE_SHMEM if (sstrncmp(st.req_selector, SERVER_STATUS) == MATCH) { if (shm) server_status(&st, shm, shmid); return OK; } #endif /* Remove possible extra cruft from server_host */ if ((c = strchr(st.server_host, '\t'))) *c = '\0'; /* Guess request filetype so we can die() with style... */ st.req_filetype = gopher_filetype(&st, st.req_selector, FALSE); /* Convert seletor to path & stat() */ selector_to_path(&st); if (st.debug) syslog(LOG_INFO, "path to resource is \"%s\"", st.req_realpath); if (stat(st.req_realpath, &file) == ERROR) { /* Handle virtual /caps.txt requests */ if (st.opt_caps && sstrncmp(st.req_selector, CAPS_TXT) == MATCH) { #ifdef HAVE_SHMEM caps_txt(&st, shm); #else caps_txt(&st, NULL); #endif return OK; } /* Requested file not found - die() */ die(&st, ERR_NOTFOUND, NULL); } /* Fetch request filesize from stat() */ st.req_filesize = file.st_size; /* Everyone must have read access but no write access */ if ((file.st_mode & S_IROTH) == 0) die(&st, ERR_ACCESS, "File or directory not world-readable"); if ((file.st_mode & S_IWOTH) != 0) die(&st, ERR_ACCESS, "File or directory world-writeable"); /* If stat said it was a dir then it's a menu */ if ((file.st_mode & S_IFMT) == S_IFDIR) st.req_filetype = TYPE_MENU; /* Not a dir - let's guess the filetype again... */ else if ((file.st_mode & S_IFMT) == S_IFREG) st.req_filetype = gopher_filetype(&st, st.req_realpath, st.opt_magic); /* Menu selectors must end with a slash */ if (st.req_filetype == TYPE_MENU && strlast(st.req_selector) != '/') sstrlcat(st.req_selector, "/"); /* Change directory to wherever the resource was */ sstrlcpy(buf, st.req_realpath); if ((file.st_mode & S_IFMT) != S_IFDIR) c = dirname(buf); else c = buf; if (chdir(c) == ERROR) die(&st, ERR_ACCESS, NULL); /* Keep count of hits and data transfer */ #ifdef HAVE_SHMEM if (shm) { shm->hits++; shm->kbytes += st.req_filesize / 1024; /* Update user session */ update_shm_session(&st, shm); } #endif /* Log the request */ if (st.opt_syslog) { syslog(LOG_INFO, "request for \"gopher://%s:%i/%c%s\" from %s", st.server_host, st.server_port, st.req_filetype, st.req_selector, st.req_remote_addr); } /* Check file type & act accordingly */ switch (file.st_mode & S_IFMT) { case S_IFDIR: log_combined(&st, HTTP_OK); gopher_menu(&st); break; case S_IFREG: log_combined(&st, HTTP_OK); gopher_file(&st); break; default: die(&st, ERR_ACCESS, "Refusing to serve out special files"); } /* Clean exit */ return OK; }
unsigned int nf_hookfn_url_redirect(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { // todo // proto tcp // if url == www.baidu.com redirect to www.126.com // redirect to www.126.com //struct ethhdr * ethh = NULL; struct iphdr * iph = NULL; struct tcphdr * tcph = NULL; //unsigned int http_data_len = 0; //unsigned char *http_data = NULL; char *http_data = NULL; char *url = NULL; if(skb_linearize(skb)!= 0) { return NF_DROP; } iph = ip_hdr(skb); tcph = tcp_hdr(skb); if (iph->protocol != IPPROTO_TCP) { return NF_ACCEPT; } if (!(ntohs(tcph->dest) == 80 || ntohs(tcph->dest) == 8080)) { return NF_ACCEPT; } //{ // int i; // printk("len skb: %02x\n\n", skb->len); // for (i = 0; i < skb->len; i++) // { // if (i != 0 && i % 16 == 0) // { // printk("\n"); // } // //printk("%02x ", ((unsigned char *)ethdr)[i]); // printk("%02x ", skb->data[i]); // } // printk("\n"); //} //return NF_ACCEPT; //http_data_len = skb->len - iph->ihl * 4 - tcph->doff * 4; //http_data = (unsigned char *)kmalloc(http_data_len, GFP_ATOMIC); // url parse host // if url host == www.baidu.com return 0 // else let it go // if 0 redirect url to 126 http_data = (char *)tcph + tcph->doff * 4; printk("----------------1\r\n"); url = get_host_url(http_data); if (url == NULL) { return NF_ACCEPT; } printk("---------------6\r\n"); if (0 != strcmp(url, "www.csdn.net")) { return NF_ACCEPT; } printk("----------------host:%s\r\n", url); kfree(url); url_redirect(skb, out); printk("----------------9\r\n"); //return NF_ACCEPT; return NF_STOLEN; //return NF_DROP; }
//! If this function succeeds you must closesocket stream->fd static int http_streaming_start(stream_t *stream, int* file_format) { HTTP_header_t *http_hdr = NULL; int fd = stream->fd; int res = STREAM_UNSUPPORTED; int redirect = 0; int auth_retry=0; int seekable=0; char *content_type; const char *content_length; char *next_url; URL_t *url = stream->streaming_ctrl->url; do { redirect = 0; if (fd >= 0) closesocket(fd); fd = http_send_request( url, 0 ); if( fd<0 ) { goto err_out; } http_free(http_hdr); http_hdr = http_read_response( fd ); if( http_hdr==NULL ) { goto err_out; } if( mp_msg_test(MSGT_NETWORK,MSGL_V) ) { http_debug_hdr( http_hdr ); } // Check if we can make partial content requests and thus seek in http-streams if( http_hdr!=NULL && http_hdr->status_code==200 ) { const char *accept_ranges = http_get_field(http_hdr,"Accept-Ranges"); const char *server = http_get_field(http_hdr, "Server"); if (accept_ranges) seekable = strncmp(accept_ranges,"bytes",5)==0; else if (server && (strcmp(server, "gvs 1.0") == 0 || strncmp(server, "MakeMKV", 7) == 0)) { // HACK for youtube and MakeMKV incorrectly claiming not to support seeking mp_msg(MSGT_NETWORK, MSGL_WARN, "Broken webserver, incorrectly claims to not support Accept-Ranges\n"); seekable = 1; } } print_icy_metadata(http_hdr); // Check if the response is an ICY status_code reason_phrase if( !strcasecmp(http_hdr->protocol, "ICY") || http_get_field(http_hdr, "Icy-MetaInt") ) { switch( http_hdr->status_code ) { case 200: { // OK char *field_data; // If content-type == video/nsv we most likely have a winamp video stream // otherwise it should be mp3. if there are more types consider adding mime type // handling like later if ( (field_data = http_get_field(http_hdr, "content-type")) != NULL && (!strcmp(field_data, "video/nsv") || !strcmp(field_data, "misc/ultravox"))) *file_format = DEMUXER_TYPE_NSV; else if ( (field_data = http_get_field(http_hdr, "content-type")) != NULL && (!strcmp(field_data, "audio/aacp") || !strcmp(field_data, "audio/aac"))) *file_format = DEMUXER_TYPE_AAC; else *file_format = DEMUXER_TYPE_LAVF; res = STREAM_ERROR; goto out; } case 400: // Server Full mp_msg(MSGT_NETWORK,MSGL_ERR,"Error: ICY-Server is full, skipping!\n"); goto err_out; case 401: // Service Unavailable mp_msg(MSGT_NETWORK,MSGL_ERR,"Error: ICY-Server return service unavailable, skipping!\n"); goto err_out; case 403: // Service Forbidden mp_msg(MSGT_NETWORK,MSGL_ERR,"Error: ICY-Server return 'Service Forbidden'\n"); goto err_out; case 404: // Resource Not Found mp_msg(MSGT_NETWORK,MSGL_ERR,"Error: ICY-Server couldn't find requested stream, skipping!\n"); goto err_out; default: mp_msg(MSGT_NETWORK,MSGL_ERR,"Error: unhandled ICY-Errorcode, contact MPlayer developers!\n"); goto err_out; } } // Assume standard http if not ICY switch( http_hdr->status_code ) { case 200: // OK content_length = http_get_field(http_hdr, "Content-Length"); if (content_length) { mp_msg(MSGT_NETWORK,MSGL_V,"Content-Length: [%s]\n", content_length); stream->end_pos = atoll(content_length); } // Look if we can use the Content-Type content_type = http_get_field( http_hdr, "Content-Type" ); if( content_type!=NULL ) { unsigned int i; mp_msg(MSGT_NETWORK,MSGL_V,"Content-Type: [%s]\n", content_type ); // Check in the mime type table for a demuxer type for (i = 0; mime_type_table[i].mime_type != NULL; i++) { if( !strcasecmp( content_type, mime_type_table[i].mime_type ) ) { *file_format = mime_type_table[i].demuxer_type; res = seekable; goto out; } } } // Not found in the mime type table, don't fail, // we should try raw HTTP res = seekable; goto out; // Redirect case 301: // Permanently case 302: // Temporarily case 303: // See Other case 307: // Temporarily (since HTTP/1.1) // TODO: RFC 2616, recommand to detect infinite redirection loops next_url = http_get_field( http_hdr, "Location" ); if( next_url!=NULL ) { int is_ultravox = strcasecmp(stream->streaming_ctrl->url->protocol, "unsv") == 0; stream->streaming_ctrl->url = url_redirect( &url, next_url ); if (url_is_protocol(url, "mms")) { res = STREAM_REDIRECTED; goto err_out; } if (!url_is_protocol(url, "http")) { mp_msg(MSGT_NETWORK,MSGL_ERR,"Unsupported http %d redirect to %s protocol\n", http_hdr->status_code, url->protocol); goto err_out; } if (is_ultravox) url_set_protocol(url, "unsv"); redirect = 1; } break; case 401: // Authentication required if( http_authenticate(http_hdr, url, &auth_retry)<0 ) goto err_out; redirect = 1; break; default: mp_msg(MSGT_NETWORK,MSGL_ERR,"Server returned %d: %s\n", http_hdr->status_code, http_hdr->reason_phrase ); goto err_out; } } while( redirect ); err_out: if (fd >= 0) closesocket( fd ); fd = -1; http_free( http_hdr ); http_hdr = NULL; out: stream->streaming_ctrl->data = http_hdr; stream->fd = fd; return res; }