This patch:
- adds a reference to each struct mentioning the exact draft
RFC section where that struct is defined.
- fixes sent mask structure fields to match draft. (bug 2404)
- removes two duplicate useless structs
Submitting as a patch to give anyone interested time to double-check the
code changes.
As a result we are a step closer toward splitting the code into a
separate library. It's highlighted some of the WCCPv2 issues and a
pathway forward now clear:
- move types definitions to a protocol types header (wccp2_types.h ?)
- correct mangled definitions for generic use. including code in that.
- add capability handling
- add hash/mask service negotiation
- add sibling peer discovery through WCCP group details ??
Amos
--
Please be using
Current Stable Squid 2.7.STABLE5 or 3.0.STABLE11
Current Beta Squid 3.1.0.3
=== 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 <netdb.h>
#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;