=== modified file 'src/wccp2.cc' --- src/wccp2.cc 2008-10-10 08:02:53 +0000 +++ src/wccp2.cc 2009-01-10 13:36:20 +0000 @@ -1,6 +1,5 @@ - /* - * $Id: wccp2.cc,v 1.23 2008/02/09 03:48:05 swilton Exp $ + * $Id$ * * DEBUG: section 80 WCCP Support * AUTHOR: Steven Wilton @@ -34,6 +33,9 @@ */ #include "squid.h" + +#if USE_WCCPv2 + #include "comm.h" #include "event.h" #include "Parsing.h" @@ -41,7 +43,6 @@ #include "SwapDir.h" #include "IPAddress.h" -#if USE_WCCPv2 #if HAVE_NETDB_H #include #endif @@ -58,99 +59,87 @@ static EVH wccp2AssignBuckets; /* KDW WCCP V2 */ -#define WCCP2_HERE_I_AM 10 -#define WCCP2_I_SEE_YOU 11 -#define WCCP2_REDIRECT_ASSIGN 12 -#define WCCP2_REMOVAL_QUERY 13 - -#define WCCP2_VERSION 0x200 - + +#define WCCP2_HASH_ASSIGNMENT 0x00 +#define WCCP2_MASK_ASSIGNMENT 0x01 + +#define WCCP2_NONE_SECURITY_LEN 0 +#define WCCP2_MD5_SECURITY_LEN 16 + +/* Useful defines */ +#define WCCP2_NUMPORTS 8 +#define WCCP2_PASSWORD_LEN 8 + + +/* WCCPv2 Pakcet format structures */ +/* Defined in draft-wilson-wccp-v2-12-oct-2001.txt */ + + +/** \interface WCCPv2_Protocol + * Generic header struct + */ +struct wccp2_item_header_t { + uint16_t type; + uint16_t length; +}; + +/* item type values */ #define WCCP2_SECURITY_INFO 0 -#define WCCP2_NO_SECURITY 0 -#define WCCP2_MD5_SECURITY 1 - #define WCCP2_SERVICE_INFO 1 -#define WCCP2_SERVICE_STANDARD 0 -#define WCCP2_SERVICE_DYNAMIC 1 -#define WCCP2_SERVICE_ID_HTTP 0x00 - -#define WCCP2_SERVICE_SRC_IP_HASH 0x1 -#define WCCP2_SERVICE_DST_IP_HASH 0x2 -#define WCCP2_SERVICE_SRC_PORT_HASH 0x4 -#define WCCP2_SERVICE_DST_PORT_HASH 0x8 -#define WCCP2_SERVICE_PORTS_DEFINED 0x10 -#define WCCP2_SERVICE_PORTS_SOURCE 0x20 -#define WCCP2_SERVICE_SRC_IP_ALT_HASH 0x100 -#define WCCP2_SERVICE_DST_IP_ALT_HASH 0x200 -#define WCCP2_SERVICE_SRC_PORT_ALT_HASH 0x400 -#define WCCP2_SERVICE_DST_PORT_ALT_HASH 0x800 - #define WCCP2_ROUTER_ID_INFO 2 - #define WCCP2_WC_ID_INFO 3 - #define WCCP2_RTR_VIEW_INFO 4 - #define WCCP2_WC_VIEW_INFO 5 - #define WCCP2_REDIRECT_ASSIGNMENT 6 - #define WCCP2_QUERY_INFO 7 - #define WCCP2_CAPABILITY_INFO 8 - #define WCCP2_ALT_ASSIGNMENT 13 - #define WCCP2_ASSIGN_MAP 14 - #define WCCP2_COMMAND_EXTENSION 15 -#define WCCP2_CAPABILITY_FORWARDING_METHOD 0x01 -#define WCCP2_CAPABILITY_ASSIGNMENT_METHOD 0x02 -#define WCCP2_CAPABILITY_RETURN_METHOD 0x03 - -#define WCCP2_METHOD_GRE 0x00000001 -#define WCCP2_METHOD_L2 0x00000002 - -#define WCCP2_FORWARDING_METHOD_GRE WCCP2_METHOD_GRE -#define WCCP2_FORWARDING_METHOD_L2 WCCP2_METHOD_L2 - -#define WCCP2_ASSIGNMENT_METHOD_HASH 0x00000001 -#define WCCP2_ASSIGNMENT_METHOD_MASK 0x00000002 - -#define WCCP2_PACKET_RETURN_METHOD_GRE WCCP2_METHOD_GRE -#define WCCP2_PACKET_RETURN_METHOD_L2 WCCP2_METHOD_L2 - -#define WCCP2_HASH_ASSIGNMENT 0x00 -#define WCCP2_MASK_ASSIGNMENT 0x01 - -#define WCCP2_NONE_SECURITY_LEN 0 -#define WCCP2_MD5_SECURITY_LEN 16 - -/* Useful defines */ -#define WCCP2_NUMPORTS 8 -#define WCCP2_PASSWORD_LEN 8 - -/* WCCP v2 packet header */ - -/// \interface WCCPv2_Protocol -struct wccp2_here_i_am_header_t { + + +/** \interface WCCPv2_Protocol + * Sect 5.5 WCCP Message Header + */ +struct wccp2_message_header_t { uint32_t type; uint16_t version; +#define WCCP2_VERSION 0x200 + uint16_t length; }; - -static struct wccp2_here_i_am_header_t wccp2_here_i_am_header; - -/* Security struct for the "no security" option */ - +static struct wccp2_message_header_t wccp2_here_i_am_header; + +/* message types */ +#define WCCP2_HERE_I_AM 10 +#define WCCP2_I_SEE_YOU 11 +#define WCCP2_REDIRECT_ASSIGN 12 +#define WCCP2_REMOVAL_QUERY 13 + + +/** \interface WCCPv2_Protocol + * Sect 5.6.1 Security Info Component + * + * Basic security Header. Matches "no security" case exactly. + */ struct wccp2_security_none_t { uint16_t security_type; uint16_t security_length; uint32_t security_option; }; -/// \interface WCCPv2_Protocol +/* security options */ +#define WCCP2_NO_SECURITY 0 +#define WCCP2_MD5_SECURITY 1 + + +/** \interface WCCPv2_Protocol + * Sect 5.6.1 Security Info Component + * + * Extended security section. Matches "MD5 security" type exactly. + * Including the security header. + */ struct wccp2_security_md5_t { uint16_t security_type; uint16_t security_length; @@ -160,7 +149,9 @@ /* Service info struct */ -/// \interface WCCPv2_Protocol +/** \interface WCCPv2_Protocol + * Sect 5.6.2 Service Info Component + */ struct wccp2_service_info_t { uint16_t service_type; uint16_t service_length; @@ -178,20 +169,52 @@ uint16_t port6; uint16_t port7; }; - -/// \interface WCCPv2_Protocol +/* services */ +#define WCCP2_SERVICE_STANDARD 0 +#define WCCP2_SERVICE_DYNAMIC 1 + +/* service IDs */ +#define WCCP2_SERVICE_ID_HTTP 0x00 + +/* service flags */ +#define WCCP2_SERVICE_SRC_IP_HASH 0x1 +#define WCCP2_SERVICE_DST_IP_HASH 0x2 +#define WCCP2_SERVICE_SRC_PORT_HASH 0x4 +#define WCCP2_SERVICE_DST_PORT_HASH 0x8 +#define WCCP2_SERVICE_PORTS_DEFINED 0x10 +#define WCCP2_SERVICE_PORTS_SOURCE 0x20 +#define WCCP2_SERVICE_SRC_IP_ALT_HASH 0x100 +#define WCCP2_SERVICE_DST_IP_ALT_HASH 0x200 +#define WCCP2_SERVICE_SRC_PORT_ALT_HASH 0x400 +#define WCCP2_SERVICE_DST_PORT_ALT_HASH 0x800 + + +/* TODO the following structures need to be re-defined for correct full operation. + wccp2_cache_identity_element needs to be merged as a sub-struct of + wccp2_identity_info_t (identity_type); which frees up the identifty info + structures so mask_assigment_data_element can become variable length + and cope with multiple fail-over caches hanging off one router. + */ + +/** \interface WCCPv2_Protocol + * Sect 5.7.2 Web-Cache Identity Element + */ struct wccp2_cache_identity_info_t { struct in_addr addr; uint16_t hash_revision; char bits[2]; - char buckets[32]; +// uint16_t bits; +//#define WCCP2_HASH_ASSIGNMENT_DATA 0x0 + +/* 5.7.2 Hash Assignment Data Element */ + char buckets[32]; /* Draft indicates 8x 32-bit buckets. ?? */ uint16_t weight; uint16_t status; }; -/* Web Cache identity info */ - -/// \interface WCCPv2_Protocol +/** \interface WCCPv2_Protocol + * Sect 5.6.4 Web-Cache Identity Info Component + */ struct wccp2_identity_info_t { uint16_t cache_identity_type; uint16_t cache_identity_length; @@ -201,22 +224,46 @@ static struct wccp2_identity_info_t wccp2_identity_info; -/// \interface WCCPv2_Protocol +/** \interface WCCPv2_Protocol + * Sect 5.7.7 Mask Element + */ +struct wccp2_mask_element_t { + uint32_t source_ip_mask; + uint32_t dest_ip_mask; + uint16_t source_port_mask; + uint16_t dest_port_mask; + uint32_t number_values; +}; + + +/** \interface WCCPv2_Protocol + * Sect 5.7.2 Web-Cache Identity Element + */ struct wccp2_cache_mask_identity_info_t { struct in_addr addr; - uint32_t num1; - uint32_t num2; - uint32_t source_ip_mask; - uint32_t dest_ip_mask; - uint16_t source_port_mask; - uint16_t dest_port_mask; - uint32_t num3; - uint32_t num4; + uint16_t hash_revision; + uint16_t bits; +#define WCCP2_MASK_ASSIGNMENT_DATA (0x1 <<14) + +/* Sect 5.7.2 Mask Assignment Data Element + * + * NP: draft specifies a variable-length set of keys here. + * the following fields only matche the special case Squid sends outbound (single-cache). + */ + uint32_t mask_element_count; + +/* Sect 5.7.6 Mask/Value Set Element */ +/* special case: single mask element. no values. */ + struct wccp2_mask_element_t mask; + +/* Sect 5.7.2 Mask Assignment Data Element */ + uint16_t weight; + uint16_t status; }; -/* Web Cache identity info */ - -/// \interface WCCPv2_Protocol +/** \interface WCCPv2_Protocol + * Sect 5.6.4 Web-Cache Identity Info Component + */ struct wccp2_mask_identity_info_t { uint16_t cache_identity_type; uint16_t cache_identity_length; @@ -226,9 +273,12 @@ static struct wccp2_mask_identity_info_t wccp2_mask_identity_info; -/* View header */ - -/// \interface WCCPv2_Protocol +/** \interface WCCPv2_Protocol + * Sect 5.6.5 Router View Info Component + * Sect 5.6.6 Web Cache View Info Component + * + * first three fields. (shared by both view components) + */ struct wccp2_cache_view_header_t { uint16_t cache_view_type; uint16_t cache_view_length; @@ -237,9 +287,8 @@ static struct wccp2_cache_view_header_t wccp2_cache_view_header; -/* View info */ - /// \interface WCCPv2_Protocol +/* NP: special-case 5.6.5 or 5.6.6 * View Info when no routers or caches are advertised? */ struct wccp2_cache_view_info_t { uint32_t num_routers; uint32_t num_caches; @@ -247,9 +296,9 @@ static struct wccp2_cache_view_info_t wccp2_cache_view_info; -/* Router ID element */ - -/// \interface WCCPv2_Protocol +/** \interface WCCPv2_Protocol + * Sect 5.7.1 Router ID Element + */ struct wccp2_router_id_element_t { struct in_addr router_address; uint32_t received_id; @@ -257,49 +306,50 @@ static struct wccp2_router_id_element_t wccp2_router_id_element; -/* Capability info header */ - -/// \interface WCCpv2_Protocol +/** \interface WCCpv2_Protocol + * Sect 5.6.9 Capabilities Info Component + */ struct wccp2_capability_info_header_t { uint16_t capability_info_type; uint16_t capability_info_length; + /* dynamic length capabilities list */ }; static struct wccp2_capability_info_header_t wccp2_capability_info_header; -/* Capability element header */ - -/// \interface WCCPv2_Protocol -struct wccp2_capability_element_header_t { - uint16_t capability_type; - uint16_t capability_length; -}; - -/* Capability element */ - -/// \interface WCCPv2_Protocol +/** \interface WCCPv2_Protocol + * 5.7.5 Capability Element + */ struct wccp2_capability_element_t { uint16_t capability_type; uint16_t capability_length; uint32_t capability_value; }; - static struct wccp2_capability_element_t wccp2_capability_element; -/* Mask Element */ - -/// \interface WCCPv2_Protocol -struct wccp2_mask_element_t { - uint32_t source_ip_mask; - uint32_t dest_ip_mask; - uint16_t source_port_mask; - uint16_t dest_port_mask; - uint32_t number_values; -}; - -/* Value Element */ - -/// \interface WCCPv2_Protocol +/* capability types */ +#define WCCP2_CAPABILITY_FORWARDING_METHOD 0x01 +#define WCCP2_CAPABILITY_ASSIGNMENT_METHOD 0x02 +#define WCCP2_CAPABILITY_RETURN_METHOD 0x03 + +/* capability values */ +#define WCCP2_METHOD_GRE 0x00000001 +#define WCCP2_METHOD_L2 0x00000002 + /* when type=WCCP2_CAPABILITY_FORWARDING_METHOD */ +#define WCCP2_FORWARDING_METHOD_GRE WCCP2_METHOD_GRE +#define WCCP2_FORWARDING_METHOD_L2 WCCP2_METHOD_L2 + /* when type=WCCP2_CAPABILITY_ASSIGNMENT_METHOD */ +#define WCCP2_ASSIGNMENT_METHOD_HASH 0x00000001 +#define WCCP2_ASSIGNMENT_METHOD_MASK 0x00000002 + /* when type=WCCP2_CAPABILITY_RETURN_METHOD */ +#define WCCP2_PACKET_RETURN_METHOD_GRE WCCP2_METHOD_GRE +#define WCCP2_PACKET_RETURN_METHOD_L2 WCCP2_METHOD_L2 + + + +/** \interface WCCPv2_Protocol + * 5.7.8 Value Element + */ struct wccp2_value_element_t { uint32_t source_ip_value; uint32_t dest_ip_value; @@ -311,7 +361,9 @@ /* RECEIVED PACKET STRUCTURE */ -/// \interface WCCPv2_Protocol +/** \interface WCCPv2_Protocol + * 5.2 'I See You' Message + */ struct wccp2_i_see_you_t { uint32_t type; uint16_t version; @@ -321,26 +373,20 @@ static struct wccp2_i_see_you_t wccp2_i_see_you; -/* Router ID element */ - -/// \interface WCCPv2_Protocol +/** \interface WCCPv2_Protocol + * 5.7.4 Router Assignment Element + */ struct wccp2_router_assign_element_t { struct in_addr router_address; uint32_t received_id; uint32_t change_number; }; -/* Generic header struct */ - -/// \interface WCCPv2_Protocol -struct wccp2_item_header_t { - uint16_t type; - uint16_t length; -}; - /* Router identity struct */ -/// \interface WCCPv2_Protocol +/** \interface WCCPv2_Protocol + * 5.6.3 Router Identity Info Component (partial) + */ struct router_identity_info_t { struct wccp2_item_header_t header; @@ -349,11 +395,15 @@ struct in_addr router_address; uint32_t number_caches; + /* dynamic list of cache IP addresses */ }; /* The received packet for a mask assignment is unusual */ -/// \interface WCCPv2_Protocol +/** \interface WCCPv2_Protocol + * Sect 5.7.7 Mask Element ??? + * see code below. apparently the supposed IP address at position num1 can be equal to 3. + */ struct cache_mask_info_t { struct in_addr addr; uint32_t num1; @@ -361,23 +411,22 @@ uint32_t num3; }; -/* assigment key */ - -/// \interface WCCPv2_Protocol +/** \interface WCCPv2_Protocol + * 5.7.3 Assignment Key Element + */ struct assignment_key_t { struct in_addr master_ip; uint32_t master_number; }; -/* Router view of WCCP */ - -/// \interface WCCPv2_Protocol +/** \interface WCCPv2_Protocol + * 5.6.5 Router View Info Component (first three fields) + */ struct router_view_t { - struct wccp2_item_header_t header; uint32_t change_number; - struct assignment_key_t assignment_key; + /* dynamic lists of routers and caches elided */ }; /* Lists used to keep track of caches, routers and services */ @@ -437,7 +486,8 @@ int empty_portlist[WCCP2_NUMPORTS] = {0, 0, 0, 0, 0, 0, 0, 0}; -/* END WCCP V2 */ +/* END WCCP V2 PROTOCL TYPES DEFINITION */ + void wccp2_add_service_list(int service, int service_id, int service_priority, int service_proto, int service_flags, int ports[], int security_type, char *password); static void wccp2SortCacheList(struct wccp2_cache_list_t *head); @@ -748,36 +798,26 @@ wccp2_mask_identity_info.cache_identity_type = htons(WCCP2_WC_ID_INFO); wccp2_mask_identity_info.cache_identity_length = htons(sizeof(wccp2_mask_identity_info.cache_identity)); memset(&wccp2_mask_identity_info.cache_identity.addr, '\0', sizeof(struct in_addr)); - wccp2_mask_identity_info.cache_identity.num1 = htonl(2); - wccp2_mask_identity_info.cache_identity.num2 = htonl(1); + wccp2_mask_identity_info.cache_identity.bits = WCCP2_MASK_ASSIGNMENT_DATA; // num1 = htonl(2); + wccp2_mask_identity_info.cache_identity.mask_element_count = htonl(1); service_flags = ntohl(service_list_ptr->service_info->service_flags); + memset(&wccp2_mask_identity_info.cache_identity.mask, 0, sizeof(struct wccp2_mask_element_t)); + if ((service_flags & WCCP2_SERVICE_SRC_IP_HASH) || (service_flags & WCCP2_SERVICE_SRC_IP_ALT_HASH)) { - wccp2_mask_identity_info.cache_identity.source_ip_mask = htonl(0x00001741); - wccp2_mask_identity_info.cache_identity.dest_ip_mask = 0; - wccp2_mask_identity_info.cache_identity.source_port_mask = 0; - wccp2_mask_identity_info.cache_identity.dest_port_mask = 0; + wccp2_mask_identity_info.cache_identity.mask.source_ip_mask = htonl(0x00001741); } else if ((service_list_ptr->info.service == WCCP2_SERVICE_STANDARD) || (service_flags & WCCP2_SERVICE_DST_IP_HASH) || (service_flags & WCCP2_SERVICE_DST_IP_ALT_HASH)) { - wccp2_mask_identity_info.cache_identity.source_ip_mask = 0; - wccp2_mask_identity_info.cache_identity.dest_ip_mask = htonl(0x00001741); - wccp2_mask_identity_info.cache_identity.source_port_mask = 0; - wccp2_mask_identity_info.cache_identity.dest_port_mask = 0; + wccp2_mask_identity_info.cache_identity.mask.dest_ip_mask = htonl(0x00001741); } else if ((service_flags & WCCP2_SERVICE_SRC_PORT_HASH) || (service_flags & WCCP2_SERVICE_SRC_PORT_ALT_HASH)) { - wccp2_mask_identity_info.cache_identity.source_ip_mask = 0; - wccp2_mask_identity_info.cache_identity.dest_ip_mask = 0; - wccp2_mask_identity_info.cache_identity.source_port_mask = htons(0x1741); - wccp2_mask_identity_info.cache_identity.dest_port_mask = 0; + wccp2_mask_identity_info.cache_identity.mask.source_port_mask = htons(0x1741); } else if ((service_flags & WCCP2_SERVICE_DST_PORT_HASH) || (service_flags & WCCP2_SERVICE_DST_PORT_ALT_HASH)) { - wccp2_mask_identity_info.cache_identity.source_ip_mask = 0; - wccp2_mask_identity_info.cache_identity.dest_ip_mask = 0; - wccp2_mask_identity_info.cache_identity.source_port_mask = 0; - wccp2_mask_identity_info.cache_identity.dest_port_mask = htons(0x1741); + wccp2_mask_identity_info.cache_identity.mask.dest_port_mask = htons(0x1741); } else { fatalf("Unknown service hash method\n"); } - wccp2_mask_identity_info.cache_identity.num3 = 0; - wccp2_mask_identity_info.cache_identity.num4 = 0; + wccp2_mask_identity_info.cache_identity.weight = 0; + wccp2_mask_identity_info.cache_identity.status = 0; xmemcpy(ptr, &wccp2_mask_identity_info, sizeof(struct wccp2_mask_identity_info_t)); service_list_ptr->wccp2_identity_info_ptr = ptr; @@ -1349,7 +1389,7 @@ debugs(80, 1, "Unknown capability type in WCCPv2 Packet (" << ntohs(router_capability_element->capability_type) << ")."); } - router_capability_element = (struct wccp2_capability_element_t *) (((char *) router_capability_element) + sizeof(struct wccp2_capability_element_header_t) + ntohs(router_capability_element->capability_length)); + router_capability_element = (struct wccp2_capability_element_t *) (((char *) router_capability_element) + sizeof(struct wccp2_item_header_t) + ntohs(router_capability_element->capability_length)); } } @@ -1594,7 +1634,7 @@ /* Packet segments */ - struct wccp2_here_i_am_header_t *main_header; + struct wccp2_message_header_t *main_header; struct wccp2_security_md5_t *security = NULL; /* service from service struct */ @@ -1629,7 +1669,7 @@ /* Start main header - fill in length later */ offset = 0; - main_header = (struct wccp2_here_i_am_header_t *) &wccp_packet[offset]; + main_header = (struct wccp2_message_header_t *) &wccp_packet[offset]; main_header->type = htonl(WCCP2_REDIRECT_ASSIGN); main_header->version = htons(WCCP2_VERSION); @@ -1647,7 +1687,7 @@ /* reset the offset */ - offset = sizeof(struct wccp2_here_i_am_header_t); + offset = sizeof(struct wccp2_message_header_t); /* build packet header from hereIam packet */ /* Security info */ @@ -1924,7 +1964,7 @@ /* finish length */ - main_header->length = htons(offset - sizeof(struct wccp2_here_i_am_header_t)); + main_header->length = htons(offset - sizeof(struct wccp2_message_header_t)); /* set the destination address */ router.sin_addr = router_list_ptr->router_sendto_address;