This patch is generated from the tosaddracl-20011010 branch of HEAD-20011010 in squid Tue Sep 9 11:51:33 2003 GMT See http://devel.squid-cache.org/ Index: squid/src/acl.c diff -u squid/src/acl.c:1.34 squid/src/acl.c:1.28.2.7.2.10 --- squid/src/acl.c:1.34 Mon Sep 3 14:15:37 2001 +++ squid/src/acl.c Wed Oct 10 04:16:53 2001 @@ -51,7 +51,6 @@ static void aclParseTimeSpec(void *curlist); static void aclParseIntRange(void *curlist); static char *strtokFile(void); -static void aclDestroyAclList(acl_list * list); static void aclDestroyTimeList(acl_time_data * data); static void aclDestroyIntRange(intrange *); static void aclLookupProxyAuthStart(aclCheck_t * checklist); @@ -966,9 +965,6 @@ acl_access *A = NULL; acl_access *B = NULL; acl_access **T = NULL; - acl_list *L = NULL; - acl_list **Tail = NULL; - acl *a = NULL; /* first expect either 'allow' or 'deny' */ if ((t = strtok(NULL, w_space)) == NULL) { @@ -990,10 +986,31 @@ cbdataFree(A); return; } + aclParseAclList(&A->acl_list); + if (A->acl_list == NULL) { + debug(28, 0) ("%s line %d: %s\n", + cfg_filename, config_lineno, config_input_line); + debug(28, 0) ("aclParseAccessLine: Access line contains no ACL's, skipping\n"); + cbdataFree(A); + return; + } + A->cfgline = xstrdup(config_input_line); + /* Append to the end of this list */ + for (B = *head, T = head; B; T = &B->next, B = B->next); + *T = A; + /* We lock _acl_access structures in aclCheck() */ +} + +void +aclParseAclList(acl_list ** head) +{ + acl_list *L = NULL; + acl_list **Tail = head; /* sane name in the use below */ + acl *a = NULL; + char *t; /* next expect a list of ACL names, possibly preceeded * by '!' for negation */ - Tail = &A->acl_list; while ((t = strtok(NULL, w_space))) { L = memAllocate(MEM_ACL_LIST); L->op = 1; /* defaults to non-negated */ @@ -1015,18 +1032,6 @@ *Tail = L; Tail = &L->next; } - if (A->acl_list == NULL) { - debug(28, 0) ("%s line %d: %s\n", - cfg_filename, config_lineno, config_input_line); - debug(28, 0) ("aclParseAccessLine: Access line contains no ACL's, skipping\n"); - cbdataFree(A); - return; - } - A->cfgline = xstrdup(config_input_line); - /* Append to the end of this list */ - for (B = *head, T = head; B; T = &B->next, B = B->next); - *T = A; - /* We lock _acl_access structures in aclCheck() */ } /**************/ @@ -2101,13 +2106,13 @@ *head = NULL; } -static void -aclDestroyAclList(acl_list * list) +void +aclDestroyAclList(acl_list ** head) { - acl_list *next = NULL; - for (; list; list = next) { - next = list->next; - memFree(list, MEM_ACL_LIST); + acl_list *l; + for (l = *head; l; l = *head) { + *head = l->next; + memFree(l, MEM_ACL_LIST); } } @@ -2119,8 +2124,7 @@ for (l = *list; l; l = next) { debug(28, 3) ("aclDestroyAccessList: '%s'\n", l->cfgline); next = l->next; - aclDestroyAclList(l->acl_list); - l->acl_list = NULL; + aclDestroyAclList(&l->acl_list); safe_free(l->cfgline); cbdataFree(l); } Index: squid/src/cache_cf.c diff -u squid/src/cache_cf.c:1.33 squid/src/cache_cf.c:1.21.10.1.2.5 --- squid/src/cache_cf.c:1.33 Thu Aug 23 22:54:05 2001 +++ squid/src/cache_cf.c Wed Aug 29 08:45:33 2001 @@ -563,20 +563,26 @@ } static void -dump_acl_access(StoreEntry * entry, const char *name, acl_access * head) +dump_acl_list(StoreEntry * entry, acl_list * head) { acl_list *l; - while (head != NULL) { + for (l = head; l; l = l->next) { + storeAppendPrintf(entry, " %s%s", + l->op ? null_string : "!", + l->acl->name); + } +} + +static void +dump_acl_access(StoreEntry * entry, const char *name, acl_access * head) +{ + acl_access *l; + for (l = head; l; l = l->next) { storeAppendPrintf(entry, "%s %s", name, - head->allow ? "Allow" : "Deny"); - for (l = head->acl_list; l != NULL; l = l->next) { - storeAppendPrintf(entry, " %s%s", - l->op ? null_string : "!", - l->acl->name); - } + l->allow ? "Allow" : "Deny"); + dump_acl_list(entry, l->acl_list); storeAppendPrintf(entry, "\n"); - head = head->next; } } @@ -618,6 +624,110 @@ free_address(struct in_addr *addr) { memset(addr, '\0', sizeof(struct in_addr)); +} + +CBDATA_TYPE(acl_address); + +static void +dump_acl_address(StoreEntry * entry, const char *name, acl_address * head) +{ + acl_address *l; + for (l = head; l; l = l->next) { + if (l->addr.s_addr != INADDR_ANY) + storeAppendPrintf(entry, "%s %s", name, inet_ntoa(l->addr)); + else + storeAppendPrintf(entry, "%s autoselect", name); + dump_acl_list(entry, l->acl_list); + storeAppendPrintf(entry, "\n"); + } +} + +static void +freed_acl_address(void *data) +{ + acl_address *l = data; + aclDestroyAclList(&l->acl_list); +} + +static void +parse_acl_address(acl_address ** head) +{ + acl_address *l; + acl_address **tail = head; /* sane name below */ + CBDATA_INIT_TYPE_FREECB(acl_address, freed_acl_address); + l = cbdataAlloc(acl_address); + parse_address(&l->addr); + aclParseAclList(&l->acl_list); + while(*tail) + tail = &(*tail)->next; + *tail = l; +} + +static void +free_acl_address(acl_address ** head) +{ + while (*head) { + acl_address *l = *head; + *head = l->next; + cbdataFree(l); + } +} + +CBDATA_TYPE(acl_tos); + +static void +dump_acl_tos(StoreEntry * entry, const char *name, acl_tos * head) +{ + acl_tos *l; + for (l = head; l; l = l->next) { + if (l->tos > 0) + storeAppendPrintf(entry, "%s 0x%02X", name, l->tos); + else + storeAppendPrintf(entry, "%s none", name); + dump_acl_list(entry, l->acl_list); + storeAppendPrintf(entry, "\n"); + } +} + +static void +freed_acl_tos(void *data) +{ + acl_tos *l = data; + aclDestroyAclList(&l->acl_list); +} + +static void +parse_acl_tos(acl_tos ** head) +{ + acl_tos *l; + acl_tos **tail = head; /* sane name below */ + int tos; + char junk; + char *token = strtok(NULL, w_space); + if (!token) + self_destruct(); + if (sscanf(token, "0x%x%c", &tos, &junk) != 1) + self_destruct(); + if (tos < 0 || tos > 255) + self_destruct(); + CBDATA_INIT_TYPE_FREECB(acl_tos, freed_acl_tos); + l = cbdataAlloc(acl_tos); + l->tos = tos; + aclParseAclList(&l->acl_list); + while(*tail) + tail = &(*tail)->next; + *tail = l; +} + +static void +free_acl_tos(acl_tos ** head) +{ + while (*head) { + acl_tos *l = *head; + *head = l->next; + l->next = NULL; + cbdataFree(l); + } } #if DELAY_POOLS Index: squid/src/cf.data.pre diff -u squid/src/cf.data.pre:1.36 squid/src/cf.data.pre:1.24.2.5.2.5 --- squid/src/cf.data.pre:1.36 Thu Oct 4 23:42:57 2001 +++ squid/src/cf.data.pre Wed Oct 10 04:16:53 2001 @@ -94,7 +94,7 @@ The socket address where Squid will listen for HTTPS client requests. - + This is really only useful for situations where you are running squid in accelerator mode and you want to do the SSL work at the accelerator level. @@ -173,12 +173,6 @@ DOC_END -NAME: tcp_outgoing_address outbound_address -TYPE: address -LOC: Config.Addrs.tcp_outgoing -DEFAULT: 255.255.255.255 -DOC_NONE - NAME: udp_incoming_address TYPE: address LOC:Config.Addrs.udp_incoming @@ -193,8 +187,6 @@ Usage: tcp_incoming_address 10.20.30.40 udp_outgoing_address fully.qualified.domain.name - tcp_outgoing_address is used for connections made to remote - servers and other caches. udp_incoming_address is used for the ICP socket receiving packets from other caches. udp_outgoing_address is used for ICP packets sent out to other @@ -2100,6 +2092,60 @@ the configure script. DOC_END +NAME: tcp_outgoing_tos tcp_outgoing_ds tcp_outgoin_dscp +TYPE: acl_tos +DEFAULT: none +LOC: Config.accessList.outgoing_tos +DOC_START + Allows you to select a TOS/Diffserv value to mark outgoing + connections with, based on the username or source address + making the request. + + tcp_outgoing_tos ds-field [!]aclname ... + + Example where normal_service_net uses the TOS value 0x00 + and normal_service_net uses 0x20 + + acl normal_service_net src 10.0.0.0/255.255.255.0 + acl good_service_net src 10.0.1.0/255.255.255.0 + tcp_outgoing_tos 0x00 normal_service_net 0x00 + tcp_outgoing_tos 0x20 good_service_net + + TOS/DSCP values really only have local significance - so you should + know what you're specifying. For more, see RFC 2474 + + The TOS/DSCP byte must be exactly that - a byte, value 0 - 255, or + "default" to use whatever default your host has. + + Processing proceeds in the order specified, and stops at first fully + matching line. +DOC_END + +NAME: tcp_outgoing_address +TYPE: acl_address +DEFAULT: none +LOC: Config.accessList.outgoing_address +DOC_START + Allows you to map requests to different outgoing IP addresses + based on the username or sourceaddress of the user making + the request. + + tcp_outgoing_address ipaddr [[!]aclname] ... + + Example where requests from 10.0.0.0/24 will be forwareded + with source address 10.1.0.1, 10.0.2.0/24 forwarded with + source address 10.1.0.2 and the rest will be forwarded with + source address 10.1.0.3. + + acl normal_service_net src 10.0.0.0/255.255.255.0 + acl good_service_net src 10.0.1.0/255.255.255.0 + tcp_outgoing_address 10.0.0.1 normal_service_net + tcp_outgoing_address 10.0.0.2 good_service_net + tcp_outgoing_address 10.0.0.3 + + Processing proceeds in the order specified, and stops at first fully + matching line. +DOC_END NAME: reply_body_max_size COMMENT: bytes allow|deny acl acl... Index: squid/src/comm.c diff -u squid/src/comm.c:1.14 squid/src/comm.c:1.11.2.2.2.4 --- squid/src/comm.c:1.14 Sun Aug 26 15:24:05 2001 +++ squid/src/comm.c Wed Aug 29 08:45:34 2001 @@ -148,7 +148,7 @@ } /* Create a socket. Default is blocking, stream (TCP) socket. IO_TYPE - * is OR of flags specified in comm.h. */ + * is OR of flags specified in comm.h. Defaults TOS */ int comm_open(int sock_type, int proto, @@ -157,7 +157,23 @@ int flags, const char *note) { + return comm_openex(sock_type, proto, addr, port, flags, 0, note); +} + + +/* Create a socket. Default is blocking, stream (TCP) socket. IO_TYPE + * is OR of flags specified in defines.h:COMM_* */ +int +comm_openex(int sock_type, + int proto, + struct in_addr addr, + u_short port, + int flags, + unsigned char TOS, + const char *note) +{ int new_socket; + int tos; fde *F = NULL; /* Create socket for accepting new connections. */ @@ -177,10 +193,23 @@ } return -1; } + /* set TOS if needed */ + if (TOS) { +#ifdef IP_TOS + tos = TOS; + if (setsockopt(new_socket, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof(int)) < 0) + debug(50, 1) ("comm_open: setsockopt(IP_TOS) on FD %d: %s\n", + new_socket, xstrerror()); +#else + debug(50, 0) ("comm_open: setsockopt(IP_TOS) not supported on this platform\n"); +#endif + } /* update fdstat */ debug(5, 5) ("comm_open: FD %d is a new socket\n", new_socket); fd_open(new_socket, FD_SOCKET, note); F = &fd_table[new_socket]; + F->local_addr = addr; + F->tos = tos; if (!(flags & COMM_NOCLOEXEC)) commSetCloseOnExec(new_socket); if ((flags & COMM_REUSEADDR)) @@ -303,6 +332,7 @@ commResetFD(ConnectStateData * cs) { int fd2; + fde *F; if (!cbdataValid(cs->data)) return 0; statCounter.syscalls.sock.sockets++; @@ -318,23 +348,34 @@ debug(5, 0) ("commResetFD: dup2: %s\n", xstrerror()); if (ENFILE == errno || EMFILE == errno) fdAdjustReserved(); + close(fd2); return 0; } close(fd2); + F = &fd_table[cs->fd]; fd_table[cs->fd].flags.called_connect = 0; /* * yuck, this has assumptions about comm_open() arguments for * the original socket */ - commSetCloseOnExec(cs->fd); - if (Config.Addrs.tcp_outgoing.s_addr != no_addr.s_addr) { - if (commBind(cs->fd, Config.Addrs.tcp_outgoing, 0) != COMM_OK) { - return 0; - } + if (commBind(cs->fd, F->local_addr, F->local_port) != COMM_OK) { + debug(5, 0) ("commResetFD: bind: %s\n", xstrerror()); + return 0; } - commSetNonBlocking(cs->fd); +#ifdef IP_TOS + if (F->tos) { + int tos = F->tos; + if (setsockopt(cs->fd, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof(int)) < 0) + debug(50, 1) ("commResetFD: setsockopt(IP_TOS) on FD %d: %s\n", cs->fd, xstrerror()); + } +#endif + if (F->flags.close_on_exec) + commSetCloseOnExec(cs->fd); + if (F->flags.nonblocking) + commSetNonBlocking(cs->fd); #ifdef TCP_NODELAY - commSetTcpNoDelay(cs->fd); + if (F->flags.nodelay) + commSetTcpNoDelay(cs->fd); #endif if (Config.tcpRcvBufsz > 0) commSetTcpRcvbuf(cs->fd, Config.tcpRcvBufsz); @@ -786,6 +827,7 @@ } if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) debug(50, 0) ("FD %d: set close-on-exec failed: %s\n", fd, xstrerror()); + fd_table[fd].flags.close_on_exec = 1; #endif } @@ -796,6 +838,7 @@ int on = 1; if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &on, sizeof(on)) < 0) debug(50, 1) ("commSetTcpNoDelay: FD %d: %s\n", fd, xstrerror()); + fd_table[fd].flags.nodelay = 1; } #endif Index: squid/src/forward.c diff -u squid/src/forward.c:1.12 squid/src/forward.c:1.12.2.3.2.2 --- squid/src/forward.c:1.12 Fri Mar 30 14:29:38 2001 +++ squid/src/forward.c Sat May 12 18:04:51 2001 @@ -266,6 +266,58 @@ comm_close(fd); } +static struct in_addr +aclMapAddr(acl_address * head, aclCheck_t *ch) +{ + acl_address *l; + struct in_addr addr; + for (l = head; l; l = l->next) { + if (aclMatchAclList(l->acl_list, ch)) + return l->addr; + } + addr.s_addr = INADDR_ANY; + return addr; +} + +static int +aclMapTOS(acl_tos * head, aclCheck_t *ch) +{ + acl_tos *l; + for (l = head; l; l = l->next) { + if (aclMatchAclList(l->acl_list, ch)) + return l->tos; + } + return 0; +} + +struct in_addr +getOutgoingAddr(request_t *request) +{ + aclCheck_t ch; + memset(&ch, '\0', sizeof(aclCheck_t)); + if (request) { + ch.src_addr = request->client_addr; + ch.my_addr = request->my_addr; + ch.my_port = request->my_port; + ch.request = request; + } + return aclMapAddr(Config.accessList.outgoing_address, &ch); +} + +unsigned long +getOutgoingTOS(request_t *request) +{ + aclCheck_t ch; + memset(&ch, '\0', sizeof(aclCheck_t)); + if (request) { + ch.src_addr = request->client_addr; + ch.my_addr = request->my_addr; + ch.my_port = request->my_port; + ch.request = request; + } + return aclMapTOS(Config.accessList.outgoing_tos, &ch); +} + static void fwdConnectStart(void *data) { @@ -277,6 +329,8 @@ const char *host; unsigned short port; time_t ctimeout; + struct in_addr outgoing; + unsigned short tos; assert(fs); assert(fwdState->server_fd == -1); debug(17, 3) ("fwdConnectStart: %s\n", url); @@ -306,11 +360,17 @@ #if URL_CHECKSUM_DEBUG assert(fwdState->entry->mem_obj->chksum == url_checksum(url)); #endif - fd = comm_open(SOCK_STREAM, + outgoing = getOutgoingAddr(fwdState->request); + tos = getOutgoingTOS(fwdState->request); + + debug(17, 3) ("fwdConnectStart: got addr %s, tos %d\n", + inet_ntoa(outgoing), tos); + fd = comm_openex(SOCK_STREAM, 0, - Config.Addrs.tcp_outgoing, + outgoing, 0, COMM_NONBLOCKING, + tos, url); if (fd < 0) { debug(50, 4) ("fwdConnectStart: %s\n", xstrerror()); Index: squid/src/ftp.c diff -u squid/src/ftp.c:1.14 squid/src/ftp.c:1.12.10.1.2.2 --- squid/src/ftp.c:1.14 Tue Sep 18 23:43:33 2001 +++ squid/src/ftp.c Wed Oct 10 04:16:53 2001 @@ -1680,7 +1680,8 @@ if (getsockname(ftpState->ctrl.fd, (struct sockaddr *) &addr, &addr_len)) { debug(9, 0) ("ftpSendPasv: getsockname(%d,..): %s\n", ftpState->ctrl.fd, xstrerror()); - addr.sin_addr = Config.Addrs.tcp_outgoing; + ftpFail(ftpState); + return; } /* Open data channel with the same local address as control channel */ fd = comm_open(SOCK_STREAM, Index: squid/src/neighbors.c diff -u squid/src/neighbors.c:1.12 squid/src/neighbors.c:1.10.4.1.2.3 --- squid/src/neighbors.c:1.12 Tue Jun 26 23:49:54 2001 +++ squid/src/neighbors.c Wed Aug 29 08:45:34 2001 @@ -1072,7 +1072,7 @@ return; /* probe already running */ if (squid_curtime - p->stats.last_connect_probe < Config.Timeout.connect) return; /* don't probe to often */ - fd = comm_open(SOCK_STREAM, 0, Config.Addrs.tcp_outgoing, + fd = comm_open(SOCK_STREAM, 0, getOutgoingAddr(NULL), 0, COMM_NONBLOCKING, p->host); if (fd < 0) return; Index: squid/src/protos.h diff -u squid/src/protos.h:1.35 squid/src/protos.h:1.23.2.4.2.7 --- squid/src/protos.h:1.35 Tue Oct 9 14:18:00 2001 +++ squid/src/protos.h Wed Oct 10 04:16:53 2001 @@ -59,7 +59,9 @@ extern int aclMatchAclList(const acl_list * list, aclCheck_t * checklist); extern void aclDestroyAccessList(struct _acl_access **list); extern void aclDestroyAcls(acl **); +extern void aclDestroyAclList(acl_list **); extern void aclParseAccessLine(struct _acl_access **); +extern void aclParseAclList(acl_list **); extern void aclParseAclLine(acl **); extern int aclIsProxyAuth(const char *name); extern err_type aclGetDenyInfoPage(acl_deny_info_list ** head, const char *name); @@ -153,6 +155,7 @@ extern void comm_init(void); extern int comm_listen(int sock); extern int comm_open(int, int, struct in_addr, u_short port, int, const char *note); +extern int comm_openex(int, int, struct in_addr, u_short, int, unsigned char TOS, const char *); extern u_short comm_local_port(int fd); extern void commSetSelect(int, unsigned int, PF *, void *, time_t); @@ -720,6 +723,8 @@ extern void fwdLogRotate(void); extern void fwdStatus(FwdState *, http_status); #endif +struct in_addr getOutgoingAddr(request_t *request); +unsigned long getOutgoingTOS(request_t *request); extern void urnStart(request_t *, StoreEntry *); Index: squid/src/ssl.c diff -u squid/src/ssl.c:1.9 squid/src/ssl.c:1.7.10.1.2.2 --- squid/src/ssl.c:1.9 Tue Jul 17 03:37:01 2001 +++ squid/src/ssl.c Wed Aug 29 08:45:35 2001 @@ -468,11 +468,12 @@ statCounter.server.all.requests++; statCounter.server.other.requests++; /* Create socket. */ - sock = comm_open(SOCK_STREAM, + sock = comm_openex(SOCK_STREAM, 0, - Config.Addrs.tcp_outgoing, + getOutgoingAddr(request), 0, COMM_NONBLOCKING, + getOutgoingTOS(request), url); if (sock == COMM_ERROR) { debug(26, 4) ("sslStart: Failed because we're out of sockets.\n"); Index: squid/src/structs.h diff -u squid/src/structs.h:1.43 squid/src/structs.h:1.28.2.7.2.6 --- squid/src/structs.h:1.43 Tue Oct 9 14:18:00 2001 +++ squid/src/structs.h Wed Oct 10 04:16:53 2001 @@ -260,6 +260,18 @@ acl_access *next; }; +struct _acl_address { + acl_address *next; + acl_list *acl_list; + struct in_addr addr; +}; + +struct _acl_tos { + acl_tos *next; + acl_list *acl_list; + int tos; +}; + struct _aclCheck_t { const acl_access *access_list; struct in_addr src_addr; @@ -490,7 +502,6 @@ u_short port; } Announce; struct { - struct in_addr tcp_outgoing; struct in_addr udp_incoming; struct in_addr udp_outgoing; #if SQUID_SNMP @@ -589,6 +600,8 @@ #endif acl_access *redirector; acl_access *reply; + acl_address *outgoing_address; + acl_tos *outgoing_tos; } accessList; acl_deny_info_list *denyInfoList; struct _authConfig { @@ -733,6 +746,8 @@ unsigned int type; u_short local_port; u_short remote_port; + struct in_addr local_addr; + unsigned char tos; char ipaddr[16]; /* dotted decimal address of peer */ char desc[FD_DESC_SZ]; struct { @@ -745,6 +760,8 @@ unsigned int nonblocking:1; unsigned int ipc:1; unsigned int called_connect:1; + unsigned int nodelay:1; + unsigned int close_on_exec:1; } flags; int bytes_read; int bytes_written; Index: squid/src/typedefs.h diff -u squid/src/typedefs.h:1.24 squid/src/typedefs.h:1.17.10.2.2.4 --- squid/src/typedefs.h:1.24 Tue Oct 9 14:18:00 2001 +++ squid/src/typedefs.h Wed Oct 10 04:16:53 2001 @@ -75,6 +75,8 @@ typedef struct _acl_snmp_comm acl_snmp_comm; typedef struct _acl_list acl_list; typedef struct _acl_access acl_access; +typedef struct _acl_address acl_address; +typedef struct _acl_tos acl_tos; typedef struct _aclCheck_t aclCheck_t; typedef struct _wordlist wordlist; typedef struct _intlist intlist; squid-tosaddracl-20011010-HEAD-20011010.new squid-tosaddracl-20011010-HEAD-20011010 differ: char 87, line 2