The unified diff between revisions [29abc3f7..] and [9bba4294..] is displayed below. It can also be downloaded as a raw diff.
This diff has been restricted to the following files: 'src/wccp2.c'
#
#
# patch "src/wccp2.c"
# from [5796dfc2979401a6e06ddb4a2a7bb0aa99a4c277]
# to [f112be20d825e37902f8832e99aa49f7445f03eb]
#
============================================================
--- src/wccp2.c 5796dfc2979401a6e06ddb4a2a7bb0aa99a4c277
+++ src/wccp2.c f112be20d825e37902f8832e99aa49f7445f03eb
@@ -106,6 +106,9 @@ static EVH wccp2AssignBuckets;
#define WCCP2_CAPABILITY_L2 0x00000002
+/* Useful defines */
+#define WCCP2_NUMPORTS 8
+
/* WCCP v2 packet header */
struct wccp2_here_i_am_header_t {
uint32_t type;
@@ -281,9 +284,13 @@ struct wccp2_service_list_t {
struct wccp2_service_list_t *next;
};
-static struct wccp2_service_list_t wccp2_service_list_head;
+static struct wccp2_service_list_t *wccp2_service_list_head = NULL;
+int empty_portlist[WCCP2_NUMPORTS] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
/* END WCCP V2 */
+void wccp2_add_service_list(int service, int service_id, int service_priority,
+ int service_proto, int service_flags, int ports[]);
/*
* The functions used during startup:
@@ -296,102 +303,65 @@ wccp2InitServices(void)
static void
wccp2InitServices(void)
{
+ debug(80, 5) ("wccp2InitServices: called\n");
+}
+
+void
+wccp2_update_service(struct wccp2_service_list_t *srv, int service,
+ int service_id, int service_priority, int service_proto, int service_flags,
+ int ports[])
+{
+ /* XXX check what needs to be wrapped in htons()! */
+ srv->info.service = service;
+ srv->info.service_id = service_id;
+ srv->info.service_priority = service_priority;
+ srv->info.service_protocol = service_proto;
+ srv->info.service_flags = htonl(service_flags);
+ srv->info.port0 = htons(ports[0]);
+ srv->info.port1 = htons(ports[1]);
+ srv->info.port2 = htons(ports[2]);
+ srv->info.port3 = htons(ports[3]);
+ srv->info.port4 = htons(ports[4]);
+ srv->info.port5 = htons(ports[5]);
+ srv->info.port6 = htons(ports[6]);
+ srv->info.port7 = htons(ports[7]);
+}
+
+void
+wccp2_add_service_list(int service, int service_id, int service_priority,
+ int service_proto, int service_flags, int ports[])
+{
struct wccp2_service_list_t *wccp2_service_list_ptr;
- wccp2_service_list_ptr=&wccp2_service_list_head;
- // TODO: Need to do something like this here:
- // for each wccp_service configured {
- // if(wccp2_service_list_ptr != &wccp2_service_list_head) {
- // wccp2_service_list_ptr->next=xcalloc(1,sizeof(struct wccp2_service_list_t));
- // wccp2_service_list_ptr=wccp2_service_list_ptr->next;
- // wccp2_service_list_ptr->next=NULL;
- // }
- // wccp2_service_list_ptr->info.service_type = htons(WCCP2_SERVICE_INFO);
- // wccp2_service_list_ptr->info.service_length = htons(sizeof(struct wccp2_service_info_t)-4);
- // wccp2_service_list_ptr->info.service = Config.wccp2.service_type; (dynamic/standard)
- // wccp2_service_list_ptr->info.service_id = Config.wccp2.service_type; (WCCP2_SERVICE_ID_HTTP for http, or user-defined value for configured)
- // wccp2_service_list_ptr->info.service_priority = Config.wccp2.service_priority;
- // wccp2_service_list_ptr->info.service_protocol = Config.wccp2.service_protocol; (0 if service_type is WCCP2_SERVICE_ID_HTTP, or IPPROTO_TCP/IPPROTO_UDP)
- // wccp2_service_list_ptr->info.service_flags = htonl(Config.wccp2.service_flags); (must be 0 if service_type is WCCP2_SERVICE_ID_HTTP, else must include WCCP2_SERVICE_PORTS_DEFINED to use the ports below. This deteries the hash method and whether the has is based on source or destination ports).
- //
- // Possibly have another loop here to define the ports?
- //
- // wccp2_service_list_ptr->info.port0 = htons(Config.wccp2.service_port1);
- // wccp2_service_list_ptr->info.port1 = htons(Config.wccp2.service_port2);
- // wccp2_service_list_ptr->info.port2 = htons(Config.wccp2.service_port3);
- // wccp2_service_list_ptr->info.port3 = htons(Config.wccp2.service_port4);
- // wccp2_service_list_ptr->info.port4 = htons(Config.wccp2.service_port5);
- // wccp2_service_list_ptr->info.port5 = htons(Config.wccp2.service_port6);
- // wccp2_service_list_ptr->info.port6 = htons(Config.wccp2.service_port7);
- // wccp2_service_list_ptr->info.port7 = htons(Config.wccp2.service_port8);
- // wccp2_service_list_ptr->change_num=0;
- // }
- //
- // The first thing that needs doing is to define a struct in the Config code
- // to store the above information in some form of a linked list.
- //
- // Most people will only need to define something like:
- // wccp2_service 0 100
- //
- // This defines the service type as the standard http service with a
- // priority of 100. If the service number is 0, no other flags will be
- // parsed.
- //
- // If anyone wanted to define a custom service, we would want the following
- // options
- // wccp2_service number priority [flags] [ports]
- //
- // [flags] should include:
- // hash_source_ip - to use the source ip address to determine which cache to send the packet to (can be used to make sure the same ip always hits the same cache). This would override the default beahviour of using the destination ip.
- // defined_ports_source - to use the source port to determine whether a packet will be redirected by WCCP (useful for catching reply packets if the proxy server is forging the source ip address)
- // proto_udp - to override the default protocol type of tcp
- //
- // [ports] would be up to 8 ports used to determine which packets to redirect
+ wccp2_service_list_ptr = xcalloc(1,sizeof(struct wccp2_service_list_t));
- /* This defines WCCP service number 80 (redirect traffic going to tcp port
- 80, using the client ip as the hash) */
+ debug(80, 5) ("wccp2_add_service_list: added service id %d\n", service_id);
+
+ /* XXX check what needs to be wrapped in htons()! */
wccp2_service_list_ptr->info.service_type = htons(WCCP2_SERVICE_INFO);
wccp2_service_list_ptr->info.service_length = htons(sizeof(struct wccp2_service_info_t)-4);
- wccp2_service_list_ptr->info.service = WCCP2_SERVICE_DYNAMIC;
- wccp2_service_list_ptr->info.service_id = 80;
- wccp2_service_list_ptr->info.service_priority = 240;
- wccp2_service_list_ptr->info.service_protocol = IPPROTO_TCP;
- wccp2_service_list_ptr->info.service_flags = htonl(WCCP2_SERVICE_SRC_IP_HASH + WCCP2_SERVICE_PORTS_DEFINED);
- wccp2_service_list_ptr->info.port0 = htons(80);
- wccp2_service_list_ptr->info.port1 = htons(0);
- wccp2_service_list_ptr->info.port2 = htons(0);
- wccp2_service_list_ptr->info.port3 = htons(0);
- wccp2_service_list_ptr->info.port4 = htons(0);
- wccp2_service_list_ptr->info.port5 = htons(0);
- wccp2_service_list_ptr->info.port6 = htons(0);
- wccp2_service_list_ptr->info.port7 = htons(0);
wccp2_service_list_ptr->change_num=0;
+ wccp2_update_service(wccp2_service_list_ptr, service, service_id,
+ service_priority, service_proto, service_flags, ports);
- wccp2_service_list_ptr->next=xcalloc(1,sizeof(struct wccp2_service_list_t));
- wccp2_service_list_ptr=wccp2_service_list_ptr->next;
- wccp2_service_list_ptr->next=NULL;
+ /* add to linked list - XXX this should use the Squid dlink* routines! */
+ wccp2_service_list_ptr->next = wccp2_service_list_head;
+ wccp2_service_list_head = wccp2_service_list_ptr;
+}
- /* This defines WCCP service number 90 (redirect traffic coming from tcp
- port 80, using the client ip as the hash) */
- wccp2_service_list_ptr->info.service_type = htons(WCCP2_SERVICE_INFO);
- wccp2_service_list_ptr->info.service_length = htons(sizeof(struct wccp2_service_info_t)-4);
- wccp2_service_list_ptr->info.service = WCCP2_SERVICE_DYNAMIC;
- wccp2_service_list_ptr->info.service_id = 90;
- wccp2_service_list_ptr->info.service_priority = 240;
- wccp2_service_list_ptr->info.service_protocol = IPPROTO_TCP;
- wccp2_service_list_ptr->info.service_flags = htonl(WCCP2_SERVICE_DST_IP_HASH + WCCP2_SERVICE_PORTS_DEFINED + WCCP2_SERVICE_PORTS_SOURCE);
- wccp2_service_list_ptr->info.port0 = htons(80);
- wccp2_service_list_ptr->info.port1 = htons(0);
- wccp2_service_list_ptr->info.port2 = htons(0);
- wccp2_service_list_ptr->info.port3 = htons(0);
- wccp2_service_list_ptr->info.port4 = htons(0);
- wccp2_service_list_ptr->info.port5 = htons(0);
- wccp2_service_list_ptr->info.port6 = htons(0);
- wccp2_service_list_ptr->info.port7 = htons(0);
- wccp2_service_list_ptr->change_num=0;
- wccp2_service_list_ptr->next=xcalloc(1,sizeof(struct wccp2_service_list_t));
- wccp2_service_list_ptr=wccp2_service_list_ptr->next;
- wccp2_service_list_ptr->next=NULL;
+struct wccp2_service_list_t *
+wccp2_get_service_by_id(int service, int service_id)
+{
+ struct wccp2_service_list_t *p;
+
+ p = wccp2_service_list_head;
+ while (p != NULL) {
+ if (p->info.service == service && p->info.service_id == service_id) {
+ return p;
+ }
+ p = p->next;
+ }
+ return NULL;
}
void
@@ -421,7 +391,8 @@ wccp2Init(void)
/* Initialise the list of services */
wccp2InitServices();
- for(service_list_ptr=&wccp2_service_list_head;service_list_ptr->next;service_list_ptr=service_list_ptr->next) {
+ service_list_ptr = wccp2_service_list_head;
+ while (service_list_ptr != NULL) {
/* Set up our list pointers */
router_list_ptr=&service_list_ptr->router_list_head;
@@ -549,6 +520,7 @@ wccp2Init(void)
eventAdd("wccp2HereIam", wccp2HereIam, NULL, 10.0, 1);
}
}
+ service_list_ptr = service_list_ptr->next;
}
}
@@ -606,7 +578,8 @@ wccp2ConnectionOpen(void)
debug(80, 1) ("Initialising all WCCPv2 lists\n");
/* Initialise all routers on all services */
- for(service_list_ptr=&wccp2_service_list_head;service_list_ptr->next;service_list_ptr=service_list_ptr->next) {
+ service_list_ptr = wccp2_service_list_head;
+ while (service_list_ptr != NULL) {
for (router_list_ptr=&service_list_ptr->router_list_head;router_list_ptr->next != NULL;router_list_ptr=router_list_ptr->next) {
router_len = sizeof(router);
memset(&router, '\0', router_len);
@@ -627,6 +600,7 @@ wccp2ConnectionOpen(void)
if (connect(theOutWccp2Connection, (struct sockaddr *) &router, router_len))
fatal("Unable to disconnect WCCP out socket");
}
+ service_list_ptr = service_list_ptr->next;
}
wccp2_connected=1;
}
@@ -665,7 +639,8 @@ wccp2ConnectionClose(void)
comm_close(theOutWccp2Connection);
}
/* for each router on each service send a packet */
- for(service_list_ptr=&wccp2_service_list_head;service_list_ptr;service_list_ptr=service_list_ptr_next) {
+ service_list_ptr = wccp2_service_list_head;
+ while (service_list_ptr != NULL) {
for (router_list_ptr=&service_list_ptr->router_list_head;router_list_ptr != NULL;router_list_ptr=router_list_next) {
for(cache_list_ptr=&router_list_ptr->cache_list_head;cache_list_ptr;cache_list_ptr=cache_list_ptr_next) {
cache_list_ptr_next=cache_list_ptr->next;
@@ -687,14 +662,10 @@ wccp2ConnectionClose(void)
}
}
service_list_ptr_next=service_list_ptr->next;
- if(service_list_ptr != &wccp2_service_list_head) {
- xfree(service_list_ptr);
- }
- else
- {
- memset(service_list_ptr,'\0',sizeof(struct wccp2_service_list_t));
- }
+ xfree(service_list_ptr);
+ service_list_ptr = service_list_ptr_next;
}
+ wccp2_service_list_head = NULL;
wccp2_connected=0;
}
@@ -825,13 +796,16 @@ wccp2HandleUdp(int sock, void *not_used)
debug (80,5) ("Complete packet received\n");
/* Check that the service in the packet is configured on this router */
- for(service_list_ptr=&wccp2_service_list_head;service_list_ptr->next;service_list_ptr=service_list_ptr->next) {
+ service_list_ptr = wccp2_service_list_head;
+ while (service_list_ptr != NULL) {
+ //debug(80, 5) ("wccpv2: checking %d against %d\n", service_info->service_id, service_list_ptr->service_info->service_id);
if(service_info->service_id == service_list_ptr->service_info->service_id) {
break;
}
+ service_list_ptr = service_list_ptr->next;
}
- if(!(service_list_ptr->next)) {
- debug(80, 1) ("WCCPv2 Unknown service received from router\n");
+ if(service_list_ptr == NULL) {
+ debug(80, 1) ("WCCPv2 Unknown service received from router (%d)\n", service_info->service_id);
return;
}
@@ -1006,7 +980,9 @@ wccp2HereIam(void *voidnotused)
router.sin_port = htons(port);
/* for each router on each service send a packet */
- for(service_list_ptr=&wccp2_service_list_head;service_list_ptr->next;service_list_ptr=service_list_ptr->next) {
+ service_list_ptr = wccp2_service_list_head;
+ while (service_list_ptr != NULL) {
+ debug(80, 5) ("wccp2HereIam: sending to service id %d\n", service_list_ptr->info.service_id);
for (router_list_ptr=&service_list_ptr->router_list_head;router_list_ptr->next != NULL;router_list_ptr=router_list_ptr->next) {
router.sin_addr = router_list_ptr->router_sendto_address;
@@ -1022,6 +998,7 @@ wccp2HereIam(void *voidnotused)
(struct sockaddr *)&router,
router_len);
}
+ service_list_ptr = service_list_ptr->next;
}
if (!eventFind(wccp2HereIam, NULL))
@@ -1065,11 +1042,13 @@ wccp2AssignBuckets(void *voidnotused)
main_header->version=htons(WCCP2_VERSION);
debug(80,2) ("Running wccp2AssignBuckets\n");
- for(service_list_ptr=&wccp2_service_list_head;service_list_ptr->next;service_list_ptr=service_list_ptr->next) {
-
+ service_list_ptr = wccp2_service_list_head;
+ while (service_list_ptr != NULL) {
/* If we're not the lowest, we don't need to worry */
if(service_list_ptr->lowest_ip == 0) {
- continue;
+ /* XXX eww */
+ service_list_ptr = service_list_ptr->next;
+ continue;
}
/* reset the offset */
@@ -1162,6 +1141,353 @@ wccp2AssignBuckets(void *voidnotused)
router_len);
}
}
+ service_list_ptr = service_list_ptr->next;
}
}
+
+
+/*
+ * Configuration option parsing code
+ */
+
+/*
+ * Format:
+ *
+ * wccp2_service {standard|dynamic} {id}
+ */
+void
+parse_wccp2_service(void *v)
+{
+ char *t;
+ int service = 0;
+ int service_id = 0;
+
+ if (wccp2_connected == 1) {
+ debug(80, 1) ("WCCPv2: Somehow reparsing the configuration "
+ "without having shut down WCCP! Try reloading squid again.\n");
+ return;
+ }
+ /* Snarf the type */
+ if ((t = strtok(NULL, w_space)) == NULL) {
+ debug(80, 0) ("wccp2ParseServiceInfo: missing service info type (standard|dynamic)\n");
+ self_destruct();
+ }
+ if (strcmp(t, "standard") == 0) {
+ service = WCCP2_SERVICE_STANDARD;
+ } else if (strcmp(t, "dynamic") == 0) {
+ service = WCCP2_SERVICE_DYNAMIC;
+ } else {
+ debug(80, 0) ("wccp2ParseServiceInfo: bad service info type (expected standard|dynamic, got %s)\n", t);
+ self_destruct();
+ }
+
+ /* Snarf the ID */
+ service_id = GetInteger();
+ if (service_id < 0 || service_id > 255) {
+ debug(80, 0) ("wccp2ParseServiceInfo: service info id %d is out of range (0..255)\n", service_id);
+ self_destruct();
+ }
+
+ /* Create a placeholder service record */
+ wccp2_add_service_list(service, service_id, 0, 0, 0, empty_portlist);
+}
+
+void
+dump_wccp2_service(StoreEntry *e, const char *label, void *v)
+{
+ struct wccp2_service_list_t *srv;
+ srv = wccp2_service_list_head;
+ while (srv != NULL) {
+ debug(80, 3) ("dump_wccp2_service: id %d, type %d\n", srv->info.service_id, srv->info.service);
+ storeAppendPrintf(e, "%s %s %d\n", label,
+ (srv->info.service == WCCP2_SERVICE_DYNAMIC) ? "dynamic" : "standard",
+ srv->info.service_id);
+ srv = srv->next;
+ }
+}
+
+void
+free_wccp2_service(void *v)
+{
+}
+
+/*
+ * Format:
+ *
+ * wccp2_service_info {id} stuff..
+ *
+ * Where stuff is:
+ *
+ * + flags=flag,flag,flag..
+ * + proto=protocol (tcp|udp)
+ * + ports=port,port,port (up to a max of 8)
+ * + priority=priority (0->255)
+ *
+ * The flags here are:
+ * src_ip_hash, dst_ip_hash, source_port_hash, dst_port_hash, ports_defined,
+ * ports_source, src_ip_alt_hash, dst_ip_alt_hash, src_port_alt_hash, dst_port_alt_hash
+ */
+static int
+parse_wccp2_service_flags(char *flags)
+{
+ char *tmp, *tmp2;
+ char *flag;
+ int retflag = 0;
+
+ if (! flags) {
+ return 0;
+ }
+
+ tmp = xstrdup(flags);
+ tmp2 = tmp;
+
+ flag = strsep(&tmp2, ",");
+ while (flag) {
+ if (strcmp(flag, "src_ip_hash") == 0) {
+ retflag |= WCCP2_SERVICE_SRC_IP_HASH;
+ } else if (strcmp(flag, "dst_ip_hash") == 0) {
+ retflag |= WCCP2_SERVICE_DST_IP_HASH;
+ } else if (strcmp(flag, "source_port_hash") == 0) {
+ retflag |= WCCP2_SERVICE_SOURCE_PORT_HASH;
+ } else if (strcmp(flag, "dst_port_hash") == 0) {
+ retflag |= WCCP2_SERVICE_DST_PORT_HASH;
+ } else if (strcmp(flag, "ports_defined") == 0) {
+ retflag |= WCCP2_SERVICE_PORTS_DEFINED;
+ } else if (strcmp(flag, "ports_source") == 0) {
+ retflag |= WCCP2_SERVICE_PORTS_SOURCE;
+ } else if (strcmp(flag, "src_ip_alt_hash") == 0) {
+ retflag |= WCCP2_SERVICE_SRC_IP_ALT_HASH;
+ } else if (strcmp(flag, "dst_ip_alt_hash") == 0) {
+ retflag |= WCCP2_SERVICE_DST_IP_ALT_HASH;
+ } else if (strcmp(flag, "src_port_alt_hash") == 0) {
+ retflag |= WCCP2_SERVICE_SRC_PORT_ALT_HASH;
+ } else if (strcmp(flag, "dst_port_alt_hash") == 0) {
+ retflag |= WCCP2_SERVICE_DST_PORT_ALT_HASH;
+ } else {
+ fatalf("Unknown wccp2 service flag: %s\n", flag);
+ }
+ flag = strsep(&tmp2, ",");
+ }
+ xfree(tmp);
+ return retflag;
+}
+
+void
+parse_wccp2_service_ports(char *options, int portlist[])
+{
+ int i = 0;
+ int p;
+ char *tmp, *tmp2, *port, *end;
+
+ if (!options) {
+ return;
+ }
+ tmp = xstrdup(options);
+ tmp2 = tmp;
+
+ port = strsep(&tmp2, ",");
+ while (port && i < WCCP2_NUMPORTS) {
+ p = strtol(port, &end, 0);
+ if (p < 1 || p > 65535) {
+ fatalf("parse_wccp2_service_ports: port value '%s' isn't valid (1..65535)\n", port);
+ }
+ portlist[i] = p;
+ i++;
+ port = strsep(&tmp2, ",");
+ }
+ if (i == 8) {
+ fatalf("parse_wccp2_service_ports: too many ports (maximum: 8) in list '%s'\n", options);
+ }
+ xfree(tmp);
+}
+
+void
+parse_wccp2_service_info(void *v)
+{
+ char *t, *end;
+ int service_id = 0;
+ int flags = 0;
+ int portlist[WCCP2_NUMPORTS];
+ int protocol = -1; /* IPPROTO_TCP | IPPROTO_UDP */
+ struct wccp2_service_list_t *srv;
+ int priority = -1;
+
+ if (wccp2_connected == 1) {
+ debug(80, 1) ("WCCPv2: Somehow reparsing the configuration "
+ "without having shut down WCCP! Try reloading squid again.\n");
+ return;
+ }
+ srv = wccp2_service_list_head;
+ debug(80, 5) ("parse_wccp2_service_info: called\n");
+ bzero(portlist, sizeof(portlist));
+ /* First argument: id */
+ service_id = GetInteger();
+ if (service_id < 0 || service_id > 255) {
+ debug(80, 1) ("parse_wccp2_service_info: invalid service id %d (must be between 0 .. 255)\n", service_id);
+ self_destruct();
+ }
+
+ /* Next: find the (hopefully!) existing service */
+ srv = wccp2_get_service_by_id(WCCP2_SERVICE_DYNAMIC, service_id);
+ if (srv == NULL) {
+ fatalf("parse_wccp2_service_info: unknown dynamic service id %d: you need to define it using wccp2_service (and make sure you wish to configure it as a dynamic service.)\n", service_id);
+ }
+
+ /* Next: loop until we don't have any more tokens */
+ while ( (t = strtok(NULL, w_space)) != NULL) {
+ if (strncmp(t, "flags=", 6) == 0) {
+ /* XXX eww, string pointer math */
+ flags = parse_wccp2_service_flags(t + 6);
+ } else if (strncmp(t, "ports=", 6) == 0) {
+ parse_wccp2_service_ports(t + 6, portlist);
+ } else if (strncmp(t, "protocol=tcp", 12) == 0) {
+ protocol = IPPROTO_TCP;
+ } else if (strncmp(t, "protocol=udp", 12) == 0) {
+ protocol = IPPROTO_UDP;
+ } else if (strncmp(t, "protocol=", 9) == 0) {
+ fatalf("parse_wccp2_service_info: id %d: unknown protocol (%s) - must be tcp or udp!\n", service_id, t);
+ } else if (strncmp(t, "priority=", 9) == 0) {
+ priority = strtol(t + 9, &end, 0);
+ if (priority < 0 || priority > 255) {
+ fatalf("parse_wccp2_service_info: id %d: %s out of range (0..255)!\n", service_id, t);
+ }
+ } else {
+ fatalf("parse_wccp2_service_info: id %d: unknown option '%s'\n", service_id, t);
+ }
+ }
+
+ /* Check everything is set */
+ if (priority == -1) {
+ fatalf("parse_wccp2_service_info: service %d: no priority defined (valid: 0..255)!\n", service_id);
+ }
+ if (protocol == -1) {
+ fatalf("parse_wccp2_service_info: service %d: no protocol defined (valid: tcp or udp)!\n", service_id);
+ }
+
+ /* rightio! now we can update */
+ wccp2_update_service(srv, WCCP2_SERVICE_DYNAMIC, service_id, priority,
+ protocol, flags, portlist);
+
+ /* Done! */
+}
+
+void
+dump_wccp2_service_info(StoreEntry *e, const char *label, void *v)
+{
+ char comma;
+ struct wccp2_service_list_t *srv;
+ int flags;
+ srv = wccp2_service_list_head;
+ while (srv != NULL) {
+ debug(80, 3) ("dump_wccp2_service_info: id %d (type %d)\n", srv->info.service_id, srv->info.service);
+
+ /* We don't need to spit out information for standard services */
+ if (srv->info.service == WCCP2_SERVICE_STANDARD) {
+ debug(80, 3) ("dump_wccp2_service_info: id %d: standard service, not dumping info\n", srv->info.service_id);
+ /* XXX eww */
+ srv = srv->next;
+ continue;
+ }
+
+ storeAppendPrintf(e, "%s %d", label, srv->info.service_id);
+
+ /* priority */
+ storeAppendPrintf(e, " priority=%d", srv->info.service_priority);
+
+ /* flags */
+ flags = ntohl(srv->info.service_flags);
+ if (flags != 0) {
+ comma = 0;
+ storeAppendPrintf(e, " flags=");
+ if (flags & WCCP2_SERVICE_SRC_IP_HASH) {
+ storeAppendPrintf(e, "%ssrc_ip_hash", comma ? "," : "");
+ comma = 1;
+ }
+ if (flags & WCCP2_SERVICE_DST_IP_HASH) {
+ storeAppendPrintf(e, "%sdst_ip_hash", comma ? "," : "");
+ comma = 1;
+ }
+ if (flags & WCCP2_SERVICE_SOURCE_PORT_HASH) {
+ storeAppendPrintf(e, "%ssource_port_hash", comma ? "," : "");
+ comma = 1;
+ }
+ if (flags & WCCP2_SERVICE_DST_PORT_HASH) {
+ storeAppendPrintf(e, "%sdst_port_hash", comma ? "," : "");
+ comma = 1;
+ }
+ if (flags & WCCP2_SERVICE_PORTS_DEFINED) {
+ storeAppendPrintf(e, "%sports_defined", comma ? "," : "");
+ comma = 1;
+ }
+ if (flags & WCCP2_SERVICE_PORTS_SOURCE) {
+ storeAppendPrintf(e, "%sports_source", comma ? "," : "");
+ comma = 1;
+ }
+ if (flags & WCCP2_SERVICE_SRC_IP_ALT_HASH) {
+ storeAppendPrintf(e, "%ssrc_ip_alt_hash", comma ? "," : "");
+ comma = 1;
+ }
+ if (flags & WCCP2_SERVICE_DST_IP_ALT_HASH) {
+ storeAppendPrintf(e, "%ssrc_ip_alt_hash", comma ? "," : "");
+ comma = 1;
+ }
+ if (flags & WCCP2_SERVICE_SRC_PORT_ALT_HASH) {
+ storeAppendPrintf(e, "%ssrc_port_alt_hash", comma ? "," : "");
+ comma = 1;
+ }
+ if (flags & WCCP2_SERVICE_DST_PORT_ALT_HASH) {
+ storeAppendPrintf(e, "%sdst_port_alt_hash", comma ? "," : "");
+ comma = 1;
+ }
+
+ }
+ /* ports */
+ comma = 0;
+ if (srv->info.port0 != 0) {
+ storeAppendPrintf(e, "%s%d", comma ? "," : " ports=", ntohs(srv->info.port0));
+ comma = 1;
+ }
+ if (srv->info.port1 != 0) {
+ storeAppendPrintf(e, "%s%d", comma ? "," : "ports=", ntohs(srv->info.port1));
+ comma = 1;
+ }
+ if (srv->info.port2 != 0) {
+ storeAppendPrintf(e, "%s%d", comma ? "," : "ports=", ntohs(srv->info.port2));
+ comma = 1;
+ }
+ if (srv->info.port3 != 0) {
+ storeAppendPrintf(e, "%s%d", comma ? "," : "ports=", ntohs(srv->info.port3));
+ comma = 1;
+ }
+ if (srv->info.port4 != 0) {
+ storeAppendPrintf(e, "%s%d", comma ? "," : "ports=", ntohs(srv->info.port4));
+ comma = 1;
+ }
+ if (srv->info.port5 != 0) {
+ storeAppendPrintf(e, "%s%d", comma ? "," : "ports=", ntohs(srv->info.port5));
+ comma = 1;
+ }
+ if (srv->info.port6 != 0) {
+ storeAppendPrintf(e, "%s%d", comma ? "," : "ports=", ntohs(srv->info.port6));
+ comma = 1;
+ }
+ if (srv->info.port7 != 0) {
+ storeAppendPrintf(e, "%s%d", comma ? "," : "ports=", ntohs(srv->info.port7));
+ comma = 1;
+ }
+
+ /* protocol */
+ storeAppendPrintf(e, " protocol=%s", (srv->info.service_protocol == IPPROTO_TCP) ? "tcp" : "udp");
+
+ storeAppendPrintf(e, "\n");
+
+ srv = srv->next;
+ }
+}
+
+void
+free_wccp2_service_info(void *v)
+{
+}
+
#endif /* USE_WCCPv2 */