コード例 #1
0
ファイル: cache.c プロジェクト: YurieCo/csapp-2
int cache_query(struct cache_s *cache, 
                const char* key, void **value)
{
    pthread_rwlock_rdlock(&cache -> lock);
    hashmap_entry_by_key(cache -> map, key, value);
    pthread_rwlock_unlock(&cache -> lock);
    return 0;
}
コード例 #2
0
ファイル: reqs.c プロジェクト: OPSF/uClinux
/*
 * If there is a Content-Length header, then return the value; otherwise, return
 * a negative number.
 */
static long
get_content_length(hashmap_t hashofheaders)
{
	ssize_t len;
	char *data;
	long content_length = -1;

	len = hashmap_entry_by_key(hashofheaders, "content-length", (void **)&data);
	if (len > 0)
		content_length = atol(data);

	return content_length;
}
コード例 #3
0
ファイル: reqs.c プロジェクト: OPSF/uClinux
/*
 * Extract the headers to remove.  These headers were listed in the Connection
 * and Proxy-Connection headers.
 */
static int
remove_connection_headers(hashmap_t hashofheaders)
{
	static char* headers[] = {
		"connection",
		"proxy-connection"
	};

	char *data;
	char* ptr;
	ssize_t len;
	int i;

	for (i = 0; i != (sizeof(headers) / sizeof(char *)); ++i) {
		/* Look for the connection header.  If it's not found, return. */
		len = hashmap_entry_by_key(hashofheaders, headers[i], (void **)&data);
		if (len <= 0)
			return 0;

		/*
		 * Go through the data line and replace any special characters
		 * with a NULL.
		 */
		ptr = data;
		while ((ptr = strpbrk(ptr, "()<>@,;:\\\"/[]?={} \t")))
			*ptr++ = '\0';

		/*
		 * All the tokens are separated by NULLs.  Now go through the
		 * token and remove them from the hashofheaders.
		 */
		ptr = data;
		while (ptr < data + len) {
			hashmap_remove(hashofheaders, ptr);

			/* Advance ptr to the next token */
			ptr += strlen(ptr) + 1;
			while (*ptr == '\0')
				ptr++;
		}

		/* Now remove the connection header it self. */
		hashmap_remove(hashofheaders, headers[i]);
	}

	return 0;
}
コード例 #4
0
ファイル: reqs.c プロジェクト: OPSF/uClinux
/*
 * Search for Via header in a hash of headers and either write a new Via
 * header, or append our information to the end of an existing Via header.
 *
 * FIXME: Need to add code to "hide" our internal information for security
 * purposes.
 */
static int
write_via_header(int fd, hashmap_t hashofheaders,
		 unsigned int major, unsigned int minor)
{
	ssize_t len;
	char hostname[512];
	char *data;
	int ret;

	if (config.via_proxy_name) {
		strlcpy(hostname, config.via_proxy_name, sizeof(hostname));
	} else if (gethostname(hostname, sizeof(hostname)) < 0) {
		strcpy(hostname, "unknown");
	}

	/*
	 * See if there is a "Via" header.  If so, again we need to do a bit
	 * of processing.
	 */
	len = hashmap_entry_by_key(hashofheaders, "via", (void **)&data);
	if (len > 0) {
		ret = write_message(fd,
				    "Via: %s, %hu.%hu %s (%s/%s)\r\n",
				    data,
				    major, minor,
				    hostname, PACKAGE, VERSION);

		hashmap_remove(hashofheaders, "via");
	} else {
		ret = write_message(fd,
				    "Via: %hu.%hu %s (%s/%s)\r\n",
				    major, minor,
				    hostname, PACKAGE, VERSION);
	}

	return ret;
}
コード例 #5
0
ファイル: process.c プロジェクト: sylar94444/iptraffic
void process_pkt(unsigned char* arg, const struct pcap_pkthdr* pkthdr, const unsigned char* packet)
{
    int rtn = IPTRAFFIC_FUNC_SUCCESS;
    struct iphdr*  ip_hdr = NULL;
    struct tcphdr* tcp_hdr = NULL;
    struct ethhdr * eth_hdr = NULL;
    unsigned char* cp = (unsigned char*)packet;
    struct http_request_s *req = g_cycle.request;
    struct http_response_s *resp = g_cycle.response;
    struct list_s * l = NULL;

    eth_hdr = (struct ethhdr*)cp;
    
    /* only IP or PPP */
    u_int16_t ether_type = ntohs(eth_hdr->h_proto);
    if(ether_type != 0x0800 && ether_type != 0x8100)
    {   
        return;
    }
    cp = cp + ETHER_HDR_LEN;

    /* check 802.1Q packet*/
    if (ether_type == 0x8100)
    {
        cp = cp + 2;
        
        if (cp[0] == 0x88 && cp[1] == 0x64)         /* PPPOE */
        {
            cp = cp + 10;
        }
        else if (cp[0] == 0x08 && cp[1] == 0x00)    /* VLAN */
        {
            cp = cp + 2;
        }
        else
        {
            return;
        }
    }

    /* IP header */
    ip_hdr = (struct iphdr*)cp;
	cp+=(ip_hdr->ihl*4);

#ifdef HAVE_UDPGRE_HEADER
	//UDP报头 或者 GRE报头,都为8字节
	if(ip_hdr->protocol == 0x11 || ip_hdr->protocol == 0x2f)
	{
		cp+=8;
		//GPRS报头
		u_int8_t gtp_flag = *cp;
		switch(gtp_flag)
        {
            case 0x30:
                cp+=8;
                break;            
            case 0x32:
                cp+=12;
                break;  
            default:    
                break;
        }
		//真正的IP报文
		ip_hdr = (struct iphdr*)cp;
		cp+=(ip_hdr->ihl*4);
	}
#endif

    tcp_hdr = (struct tcphdr*)cp;
    cp+=(tcp_hdr->doff*4);

    if (memcmp(cp, "GET", 3) == 0)
    {
        cp+=4;
    }
    else if(memcmp(cp, "POST", 4) == 0)
    {
        cp+=5;
    }
    else
    {
        /* 非GET/POST请求包 */
        return;
    }

    /* 匹配GET请求各个字段失败 */
    rtn = http_parse_get(req, cp);
    if (IPTRAFFIC_FUNC_ERROR == rtn)
    {
        return;
    }
    
    /* http 报文错误 */
    if ((req->host_len <= 0) || (req->uri_len <= 0))
    {
        return;
    }
   
#if 0
     /* 无效报文,例如:图片、视频、文件等 */
    if(http_detect_request_type(req->url, req->url_len) == IPTRAFFIC_FUNC_ERROR)
    {
        return;
    }
#endif   

    /* 依据host为关键字在hash表中搜寻规则 */            
    hashmap_entry_by_key(g_cycle.hashmap, req->host, &l);
    if (NULL == l)
    {
        /* 根据host关键字未找到相应的规则,在默认规则中第二次查找 */
        hashmap_entry_by_key(g_cycle.hashmap, "null", &l);
        if (NULL == l)
        {
            return;
        }
    }

    /* 匹配该规则 */
    struct rule_entry_s *rule = match_rules_repled(req, l, g_cycle.filter, resp);    
    if (!rule)
    {
        return;
    }

#ifndef ENABLE_STAT_ONLY
    //收集数据,UDP实时返回指定服务器
    if(rule->type_repled == REDIRECT_TYPE_RECORD)
    {
        dcenter_udp_packet(ip_hdr, req);

        return;
    }

    /* 生成替换后的链接*/
    rtn = build_url_repled(resp->index, rule, req->url, resp->url);
    if(IPTRAFFIC_FUNC_ERROR == rtn)
    {
        warnlog("Wrong rule!Please check it:url=%s",req->url);
        return;
    }
                                
    build_response_payload(rule, req, resp);
                             
    /* 回响应报文*/
    rtn = send_http_get_ack(eth_hdr, ip_hdr, tcp_hdr);
    if (rtn != IPTRAFFIC_FUNC_SUCCESS)
    {
        errlog( "Failed to send http get ack");
        return;
    }
                                
    /* 发送响应报文*/
    rtn = send_http_resp_repled(eth_hdr, ip_hdr, tcp_hdr, resp->payload);      
    if (rtn != IPTRAFFIC_FUNC_SUCCESS)
    {
        errlog( "Failed to send response with replaced URI");
        return;
    }
#endif

    rule->matched_count++;

    return;
}
コード例 #6
0
ファイル: reqs.c プロジェクト: OPSF/uClinux
/*
 * Break the request line apart and figure out where to connect and
 * build a new request line. Finally connect to the remote server.
 */
static struct request_s *
process_request(struct conn_s *connptr, hashmap_t hashofheaders)
{
	char *url;
	struct request_s *request;

	int ret;

	size_t request_len;

	/* NULL out all the fields so frees don't cause segfaults. */
	request = safecalloc(1, sizeof(struct request_s));
	if (!request)
		return NULL;

	request_len = strlen(connptr->request_line) + 1;

	request->method = safemalloc(request_len);
	url = safemalloc(request_len);
	request->protocol = safemalloc(request_len);

	if (!request->method || !url || !request->protocol) {
		safefree(url);
		free_request_struct(request);

		return NULL;
	}

	ret =
	    sscanf(connptr->request_line, "%[^ ] %[^ ] %[^ ]",
		   request->method, url, request->protocol);
	if (ret < 2) {
		log_message(LOG_ERR,
			    "process_request: Bad Request on file descriptor %d",
			    connptr->client_fd);
		indicate_http_error(connptr, 400, "Bad Request",
				    "detail", "Request has an invalid format",
				    "url", url,
				    NULL);

		safefree(url);
		free_request_struct(request);

		return NULL;
	}

	/* 
	 * FIXME: We need to add code for the simple HTTP/0.9 style GET
	 * request.
	 */

	if (!url) {
		log_message(LOG_ERR,
			    "process_request: Null URL on file descriptor %d",
			    connptr->client_fd);
		indicate_http_error(connptr, 400, "Bad Request",
				    "detail", "Request has an empty URL",
				    "url", url,
				    NULL);

		safefree(url);
		free_request_struct(request);

		return NULL;
	}

	if (strncasecmp(url, "http://", 7) == 0
	    || (UPSTREAM_CONFIGURED() && strncasecmp(url, "ftp://", 6) == 0)) {
		char *skipped_type = strstr(url, "//") + 2;

		if (extract_http_url(skipped_type, request) < 0) {
			indicate_http_error(connptr, 400, "Bad Request",
					    "detail", "Could not parse URL",
					    "url", url,
					    NULL);

			safefree(url);
			free_request_struct(request);

			return NULL;
		}
	} else if (strcmp(request->method, "CONNECT") == 0) {
		if (extract_ssl_url(url, request) < 0) {
			indicate_http_error(connptr, 400, "Bad Request",
					    "detail", "Could not parse URL",
					    "url", url,
					    NULL);

			safefree(url);
			free_request_struct(request);

			return NULL;
		}

		/* Verify that the port in the CONNECT method is allowed */
		if (check_allowed_connect_ports(request->port) <= 0) {
			indicate_http_error(connptr, 403, "Access violation",
					    "detail", "The CONNECT method not allowed " \
					              "with the port you tried to use.",
					    "url", url,
					    NULL);
			log_message(LOG_INFO, "Refused CONNECT method on port %d",
				    request->port);

			safefree(url);
			free_request_struct(request);

			return NULL;
		}
		
		connptr->connect_method = TRUE;
	} else {
#ifdef TRANSPARENT_PROXY
		/*
		 * This section of code is used for the transparent proxy
		 * option.  You will need to configure your firewall to
		 * redirect all connections for HTTP traffic to tinyproxy
		 * for this to work properly.
		 *
		 * This code was written by Petr Lampa <*****@*****.**>
		 */
		int length;
		char *data;
		length = hashmap_entry_by_key(hashofheaders, "host", (void **)&data);
		if (length <= 0) {
			struct sockaddr_in dest_addr;

			if (getsockname(connptr->client_fd, (struct sockaddr *)&dest_addr, &length) < 0) {
				log_message(LOG_ERR,
					    "process_request: cannot get destination IP for %d",
					    connptr->client_fd);
				indicate_http_error(connptr, 400, "Bad Request",
						    "detail", "Unknown destination",
						    "url", url,
						    NULL);
				safefree(url);
				free_request_struct(request);
				return NULL;
			} 
			request->host = safemalloc(17);
			strcpy(request->host, inet_ntoa(dest_addr.sin_addr));
			request->port = ntohs(dest_addr.sin_port);
			request->path = safemalloc(strlen(url) + 1);
			strcpy(request->path, url);
			safefree(url);
			build_url(&url, request->host, request->port, request->path);
			log_message(LOG_INFO,
				    "process_request: trans IP %s %s for %d",
				    request->method, url, connptr->client_fd);
		} else {
			request->host = safemalloc(length+1);
			if (sscanf(data, "%[^:]:%hu", request->host, &request->port) != 2) {
				strcpy(request->host, data);
				request->port = HTTP_PORT;
			}
			request->path = safemalloc(strlen(url) + 1);
			strcpy(request->path, url);
			safefree(url);
			build_url(&url, request->host, request->port, request->path);
			log_message(LOG_INFO,
				    "process_request: trans Host %s %s for %d",
				    request->method, url, connptr->client_fd);
		}
		if (config.ipAddr &&
		    strcmp(request->host, config.ipAddr) == 0) {
			log_message(LOG_ERR,
				    "process_request: destination IP is localhost %d",
				    connptr->client_fd);
			indicate_http_error(connptr, 400, "Bad Request",
					    "detail", "You tried to connect to the machine the proxy is running on",
					    "url", url,
					    NULL);
			safefree(url);
			free_request_struct(request);
			return NULL;
		}
#else
		log_message(LOG_ERR,
			    "process_request: Unknown URL type on file descriptor %d",
			    connptr->client_fd);
		indicate_http_error(connptr, 400, "Bad Request",
				    "detail", "Unknown URL type",
				    "url", url,
				    NULL);

		safefree(url);
		free_request_struct(request);

		return NULL;
#endif
	}

#ifdef FILTER_ENABLE
	/*
	 * Filter restricted domains/urls
	 */
	if (config.filter) {
		if (config.filter_url)
			ret = filter_url(url);
		else
			ret = filter_domain(request->host);

		if (ret) {
			update_stats(STAT_DENIED);

			if (config.filter_url)
				log_message(LOG_NOTICE,
					    "Proxying refused on filtered url \"%s\"",
					    url);
			else
				log_message(LOG_NOTICE,
					    "Proxying refused on filtered domain \"%s\"",
					    request->host);

			indicate_http_error(connptr, 403, "Filtered",
					    "detail", "The request you made has been filted",
					    "url", url,
					    NULL);

			safefree(url);
			free_request_struct(request);

			return NULL;
		}
	}
#endif

	safefree(url);

	/*
	 * Check to see if they're requesting the stat host
	 */
	if (config.stathost && strcmp(config.stathost, request->host) == 0) {
		log_message(LOG_NOTICE, "Request for the stathost.");
		connptr->show_stats = TRUE;

		free_request_struct(request);
		return NULL;
	}

	/*
	 * Break apart the protocol and update the connection structure.
	 */
	if (strncasecmp(request->protocol, "http", 4) == 0) {
		memcpy(request->protocol, "HTTP", 4);
		sscanf(request->protocol, "HTTP/%u.%u",
		       &connptr->protocol.major, &connptr->protocol.minor);
	}

	return request;
}
コード例 #7
0
ファイル: transparent-proxy.c プロジェクト: LazyZhu/tinyproxy
int
do_transparent_proxy (struct conn_s *connptr, hashmap_t hashofheaders,
                      struct request_s *request, struct config_s *conf,
                      char **url)
{
        socklen_t length;
        char *data;
        size_t ulen = strlen (*url);
        ssize_t i;

        length = hashmap_entry_by_key (hashofheaders, "host", (void **) &data);
        if (length <= 0) {
                struct sockaddr_in dest_addr;

                if (getsockname
                    (connptr->client_fd, (struct sockaddr *) &dest_addr,
                     &length) < 0) {
                        log_message (LOG_ERR,
                                     "process_request: cannot get destination IP for %d",
                                     connptr->client_fd);
                        indicate_http_error (connptr, 400, "Bad Request",
                                             "detail", "Unknown destination",
                                             "url", *url, NULL);
                        return 0;
                }

                request->host = (char *) safemalloc (17);
                strlcpy (request->host, inet_ntoa (dest_addr.sin_addr), 17);

                request->port = ntohs (dest_addr.sin_port);

                request->path = (char *) safemalloc (ulen + 1);
                strlcpy (request->path, *url, ulen + 1);

                build_url (url, request->host, request->port, request->path);
                log_message (LOG_INFO,
                             "process_request: trans IP %s %s for %d",
                             request->method, *url, connptr->client_fd);
        } else {
                request->host = (char *) safemalloc (length + 1);
                if (sscanf (data, "%[^:]:%hu", request->host, &request->port) !=
                    2) {
                        strlcpy (request->host, data, length + 1);
                        request->port = HTTP_PORT;
                }

                request->path = (char *) safemalloc (ulen + 1);
                strlcpy (request->path, *url, ulen + 1);

                build_url (url, request->host, request->port, request->path);
                log_message (LOG_INFO,
                             "process_request: trans Host %s %s for %d",
                             request->method, *url, connptr->client_fd);
        }

        if (conf->listen_addrs == NULL) {
                return 1;
        }

        for (i = 0; i < vector_length(conf->listen_addrs); i++) {
                const char *addr;

                addr = (char *)vector_getentry(conf->listen_addrs, i, NULL);

                if (addr && strcmp(request->host, addr) == 0) {
                        log_message(LOG_ERR,
                                    "transparent: destination IP %s is local "
                                    "on socket fd %d",
                                    request->host, connptr->client_fd);
                        indicate_http_error(connptr, 400, "Bad Request",
                                            "detail",
                                            "You tried to connect to the "
                                            "machine the proxy is running on",
                                            "url", *url, NULL);
                        return 0;
                }
        }

        return 1;
}