diff -ruN ipvs-0.9.5/ipvs/ipvsadm/Makefile ipvs-0.9.5.new/ipvs/ipvsadm/Makefile --- ipvs-0.9.5/ipvs/ipvsadm/Makefile Sat Oct 20 04:14:00 2001 +++ ipvs-0.9.5.new/ipvs/ipvsadm/Makefile Sat Oct 27 20:31:58 2001 @@ -63,7 +63,7 @@ POPT_DEFINE = -DHAVE_POPT endif -OBJS = ipvsadm.o config_stream.o dynamic_array.o +OBJS = ipvsadm.o config_stream.o dynamic_array.o fwmark_lookup.o LIBS = $(POPT_LIB) DEFINES = -DVERSION=\"$(VERSION)\" -DSCHEDULERS=\"$(SCHEDULERS)\" \ $(POPT_DEFINE) $(IP_VS_H_DEFINE) diff -ruN ipvs-0.9.5/ipvs/ipvsadm/VERSION ipvs-0.9.5.new/ipvs/ipvsadm/VERSION --- ipvs-0.9.5/ipvs/ipvsadm/VERSION Wed Sep 19 03:42:54 2001 +++ ipvs-0.9.5.new/ipvs/ipvsadm/VERSION Sat Oct 27 20:31:56 2001 @@ -1 +1 @@ -1.20 +1.21 diff -ruN ipvs-0.9.5/ipvs/ipvsadm/config_stream.c ipvs-0.9.5.new/ipvs/ipvsadm/config_stream.c --- ipvs-0.9.5/ipvs/ipvsadm/config_stream.c Fri Mar 23 00:57:46 2001 +++ ipvs-0.9.5.new/ipvs/ipvsadm/config_stream.c Mon Oct 29 10:49:29 2001 @@ -1,12 +1,29 @@ /* - * Code to convert a stream input into a dynamic array - * that can be parsed as argc and argv. + * dynamic_array.c - Code to convert a stream input into a + * that can be parsed as argc and argv. * * Authors: Horms * - * Released under the terms of the GNU GPL + * Version: $Id: config_stream.c,v Exp $ * - * ChangeLog + * Copyright (c) 2001 Horms + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Changes: * Horms : scanf Glibc under Red Hat 7 does not appear * to return EOF when input ends. Fall through * code has been added to handle this case correctly diff -ruN ipvs-0.9.5/ipvs/ipvsadm/config_stream.h ipvs-0.9.5.new/ipvs/ipvsadm/config_stream.h --- ipvs-0.9.5/ipvs/ipvsadm/config_stream.h Wed May 31 14:36:21 2000 +++ ipvs-0.9.5.new/ipvs/ipvsadm/config_stream.h Mon Oct 29 10:50:10 2001 @@ -1,14 +1,33 @@ /* - * Code to convert a stream input into a dynamic array - * that can be parsed as argc and argv. + * dynamic_array.h - Code to convert a stream input into a + * that can be parsed as argc and argv. * * Authors: Horms * - * Released under the terms of the GNU GPL + * Version: $Id: config_stream.h,v Exp $ + * + * Copyright (c) 2001 Horms + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Changes: */ -#ifndef CONFIG_STREAM_FLIM -#define CONFIG_STREAM_FLIM +#ifndef _CONFIG_STREAM_H +#define _CONFIG_STREAM_H #include "dynamic_array.h" @@ -16,4 +35,4 @@ dynamic_array_t *config_stream_read (FILE *stream, const char *first_element); -#endif +#endif /* _CONFIG_STREAM_H */ diff -ruN ipvs-0.9.5/ipvs/ipvsadm/del ipvs-0.9.5.new/ipvs/ipvsadm/del --- ipvs-0.9.5/ipvs/ipvsadm/del Thu Jan 1 12:00:00 1970 +++ ipvs-0.9.5.new/ipvs/ipvsadm/del Mon Oct 29 10:42:13 2001 @@ -0,0 +1,30 @@ +/* + * dynamic_array.c - Code to convert a stream input into a + * that can be parsed as argc and argv. + * + * Author: Horms + * + * Version: $Id: config_stream.c,v Exp $ + * + * Copyright (c) 2001 Horms + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Changes: + * Horms : scanf Glibc under Red Hat 7 does not appear + * to return EOF when input ends. Fall through + * code has been added to handle this case correctly + */ diff -ruN ipvs-0.9.5/ipvs/ipvsadm/dynamic_array.c ipvs-0.9.5.new/ipvs/ipvsadm/dynamic_array.c --- ipvs-0.9.5/ipvs/ipvsadm/dynamic_array.c Fri Mar 23 00:57:46 2001 +++ ipvs-0.9.5.new/ipvs/ipvsadm/dynamic_array.c Mon Oct 29 10:49:33 2001 @@ -1,4 +1,6 @@ /* + * dynamic_array.c + * * Dynamic array, to store all your flims in Includes macros required * to create an array of strings but as the primitive type for the * array is void * providing your own duplicate_primitive and @@ -7,8 +9,29 @@ * * Authors: Horms * - * Released under the terms of the GNU GPL + * Version: $Id: dynamic_array.c,v Exp $ * + * Copyright (c) 2001 Horms + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Changes: + * Horms : scanf Glibc under Red Hat 7 does not appear + * to return EOF when input ends. Fall through + * code has been added to handle this case correctly */ #include "dynamic_array.h" diff -ruN ipvs-0.9.5/ipvs/ipvsadm/dynamic_array.h ipvs-0.9.5.new/ipvs/ipvsadm/dynamic_array.h --- ipvs-0.9.5/ipvs/ipvsadm/dynamic_array.h Fri Mar 23 00:57:46 2001 +++ ipvs-0.9.5.new/ipvs/ipvsadm/dynamic_array.h Mon Oct 29 10:50:11 2001 @@ -1,4 +1,7 @@ + /* + * dynamic_array.h + * * Dynamic array, to store all your flims in Includes macros required * to create an array of strings but as the primitive type for the * array is void * providing your own duplicate_primitive and @@ -7,12 +10,33 @@ * * Authors: Horms * - * Released under the terms of the GNU GPL + * Version: $Id: dynamic_array.h,v Exp $ + * + * Copyright (c) 2001 Horms + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * + * Changes: + * Horms : scanf Glibc under Red Hat 7 does not appear + * to return EOF when input ends. Fall through + * code has been added to handle this case correctly */ -#ifndef DYNAMIC_ARRAY_FLIM -#define DYNAMIC_ARRAY_FLIM +#ifndef _DYNAMIC_ARRAY_H +#define _DYNAMIC_ARRAY_H #include #include @@ -174,4 +198,4 @@ dynamic_array_t *dynamic_array_split_str(char *string, const char delimiter); -#endif +#endif /* _DYNAMIC_ARRAY_H */ diff -ruN ipvs-0.9.5/ipvs/ipvsadm/fwmark_lookup.c ipvs-0.9.5.new/ipvs/ipvsadm/fwmark_lookup.c --- ipvs-0.9.5/ipvs/ipvsadm/fwmark_lookup.c Thu Jan 1 12:00:00 1970 +++ ipvs-0.9.5.new/ipvs/ipvsadm/fwmark_lookup.c Mon Oct 29 10:49:36 2001 @@ -0,0 +1,786 @@ +/* + * fwmark_lookup.c + * + * Look up firwall marks in /etc/fwmarks. This is intended to be + * analogous to /etc/hosts + * + * Authors: Horms + * + * Version: $Id: fwmark_lookup.c,v Exp $ + * + * Copyright (c) 2001 Horms + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Changes: + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fwmark_lookup.h" + +#define __FWM_LOOKUP_MAX_LINE_LENGTH 4096 +#define __FWM_BLOCKING ((size_t) 7) + +static struct hostent __fwm_hostent; +static char **__fwm_h_aliases = NULL; +static size_t __fwm_no_h_aliases = 0; +static char **__fwm_h_addr_list = NULL; +static size_t __fwm_no_h_addr_list = 0; +static int __fwm_fd = -1; + +static struct hostent *__fwm_simple_hostent(const fwm_t fwm, const char *name); +static int __fwm_beginfwment(void); + +static unsigned char __fwm_getc_buffer[__FWM_LOOKUP_MAX_LINE_LENGTH]; +static ssize_t __fwm_getc_nread = 0; +static ssize_t __fwm_getc_offset = 0; + +static int __fwm_getc(void); + +static int __fwm_add_fwmark(fwm_t key); +static int __fwm_add_fwmark_str(char *key); +static int __fwm_add_name(const char *name); + +static void __fwm_reset_global(void); +static struct hostent *__fwm_reset_hostent(struct hostent *hostent); +static void __fwm_array_destroy(void **a, const size_t count, + const size_t fixed_size); +static void **__fwm_array_add_element(void **a, size_t * count, + void *new_elem, size_t fixed_size); + + +/********************************************************************** + * __fwm_reset_global + * Reset the global hostent structure and associated arrays. + * pre: none + * post: __fwm_hostent is reset + * __fwm_h_aliases and __fwm_h_addr_list are freed and set to NULL + * __fwm_no_h_aliases and __fwm_no_h_addr_list are set to 0 + * return: none + **********************************************************************/ + +static void __fwm_reset_global(void) +{ + __fwm_reset_hostent(&__fwm_hostent); + + __fwm_array_destroy((void **) __fwm_h_aliases, __fwm_no_h_aliases, + 0); + __fwm_h_aliases = NULL; + __fwm_no_h_aliases = 0; + + __fwm_array_destroy((void **) __fwm_h_addr_list, + __fwm_no_h_addr_list, sizeof(fwm_t)); + __fwm_h_addr_list = NULL; + __fwm_no_h_addr_list = 0; +} + + +/********************************************************************** + * __fwm_reset_hostent + * Zero a hostent structure + * pre: hostent: hostent to zero + * post: values of hostent are zeroed + * return: hostent + * Note: Any memory associated with elements of hostent are + * not freed. + **********************************************************************/ + +static struct hostent *__fwm_reset_hostent(struct hostent *hostent) +{ + if (hostent == NULL) { + return (NULL); + } + + hostent->h_name = NULL; + hostent->h_aliases = NULL; + hostent->h_addrtype = AF_INET; + hostent->h_length = sizeof(fwm_t); + hostent->h_addr_list = NULL; + + return (hostent); +} + + +/********************************************************************** + * __fwm_array_destroy + * Destroy an array of strings + * pre: a: array of strings to free + * count: number of elements allocated in the array + * fixed_size: Size of elements if they are a fixed size + * 0 if they are variable size + * post: If fixed_size is zero free each element in the array + * Free the array. + * Note: If elements are fixed size they are allocated as part + * of the array itself and hence are freed anyway, + * return: none + **********************************************************************/ + +static void __fwm_array_destroy(void **a, const size_t count, + const size_t fixed_size) +{ + int i; + + if (a == NULL) { + return; + } + + if (!fixed_size) { + for (i = 0; i < count; i++) { + if (a[i] != NULL) { + free(a[i]); + } + } + } + + free(a); +} + + +/********************************************************************** + * __fwm_array_add_element + * Add an element to an array of strings. + * If the array is empty create it, if there is not enough space + * allocate more space. + * pre: a: array to add element to + * count: number of elements allocated in the array + * new_elem: element to add to the array + * fixed_size: Size of elements if they are a fixed size + * 0 if they are variable size + * post: If a is NULL + * allocate a block of elements in the array and + * make elem the fist element + * Else + * Find the last unused element + * If this is the last allocated element in the array + * Allocate another block of elemnts + * Make the last unused element in the array new_elem + * Note: If elements are fixed size they are allocated as part + * of the array itself and copied into the array + * using memcpy. Otherewise the only the pointer + * to the element is stored and well be freed by + * __fwm_array_destroy. + * return: none + **********************************************************************/ + +static void **__fwm_array_add_element(void **a, size_t * count, + void *new_elem, size_t fixed_size) +{ + void **old_a; + size_t elem; + size_t elem_alloc; + + elem_alloc = (fixed_size ? fixed_size : sizeof(void *)); + + if (a == NULL || *count == 0) { + *count = __FWM_BLOCKING; + a = (void **) malloc(__FWM_BLOCKING * elem_alloc); + if (a == NULL) { + *count = 0; + return (NULL); + } + memset(a, '\0', __FWM_BLOCKING * elem_alloc); + elem = 0; + } else { + old_a = a; + + for (elem = 0; elem < *count; elem++) { + if (a[elem] == NULL) { + break; + } + } + + if (elem + 2 > *count) { + *count += __FWM_BLOCKING; + a = (void **) realloc((void *) a, + *count * elem_alloc); + if (a == NULL) { + __fwm_array_destroy(old_a, + *count - + __FWM_BLOCKING, + fixed_size); + *count = 0; + return (NULL); + } + memset(a + (*count) - __FWM_BLOCKING, '\0', + __FWM_BLOCKING * elem_alloc); + } + } + + if (fixed_size) { + memcpy(&(a[elem]), new_elem, fixed_size); + } else { + a[elem] = new_elem; + } + + return (a); +} + + +/********************************************************************** + * __fwm_str_to_fwm + * Convert a string to a fwmark + * pre: str: ASCII representation of a fwmark + * fwm: pointer to fwm_t to store result in + * post: str is converted to a fwm + * return: 0 on success + * -1 on erroe + **********************************************************************/ + +static int __fwm_str_to_fwm(const char *str, fwm_t *fwm) +{ + long l; + char *end; + + if(str == NULL || *str == '\0' || fwm == NULL) { + return(-1); + } + + l = strtol(str, &end, 10); + if(*end != '\0' || errno == ERANGE || l < 0 || l > UINT_MAX) { + return(-1); + } + + *fwm = (fwm_t) l; + return(0); +} + + +/********************************************************************** + * __fwm_getc + * read a single character from the fwmarks file + * Note: This is buffered internally and hence should + * be reasonably efficient. + * pre: fwmarks file is open. + * post: If __fwm_getc_buffer is empty or has been exhausted + * then it is filled by reding + * __FWM_LOOKUP_MAX_LINE_LENGTH bytes from __fwm_fd. + * One character is returned from __fwm_getc_buffer and + * the offset is advanced. + * return: Once character from the fwmarks file. + * EOF on error or end of file. + **********************************************************************/ + +static int __fwm_getc(void) +{ + ssize_t nread; + + if (__fwm_getc_offset < __fwm_getc_nread) { + return ((int) (__fwm_getc_buffer[__fwm_getc_offset++])); + } + + while (1) { + nread = read(__fwm_fd, __fwm_getc_buffer, + __FWM_LOOKUP_MAX_LINE_LENGTH); + if (nread < 0) { + if (errno == EINTR) { + continue; + } + return (EOF); + } + if (nread == 0) { + return (EOF); + } + + __fwm_getc_offset = 0; + __fwm_getc_nread = nread; + break; + } + + return ((int) (__fwm_getc_buffer[__fwm_getc_offset++])); +} + + +/********************************************************************** + * __fwm_add_fwmark + * Add a fwmark to __fwm_hostent + * pre: fwm to add to the __fwm_hostent + * post: fwm is added to h_addr_list + * return: 0 on success + * -1 on error + **********************************************************************/ + +static int __fwm_add_fwmark(fwm_t fwm) +{ + void **a; + + fwm = htonl(fwm); + + a = __fwm_array_add_element((void **) __fwm_h_addr_list, + &__fwm_no_h_addr_list, (void *) &fwm, + sizeof(fwm_t)); + if (a == NULL) { + __fwm_reset_global(); + endfwment(); + return (-1); + } + + __fwm_h_addr_list = (char **) a; + __fwm_hostent.h_addr_list = __fwm_h_addr_list; + + return (0); +} + + +/********************************************************************** + * __fwm_add_fwmark_str + * Add a fwmark to __fwm_hostent + * pre: fwm_str: fwm to add to the __fwm_hostent, as a string. + * The string must be the ASCII representation a posigive integer. + * post: fwm is added to h_addr_list + * return: 0 on success + * -1 on error + **********************************************************************/ + +static int __fwm_add_fwmark_str(char *fwm_str) +{ + fwm_t fwm; + + if(__fwm_str_to_fwm(fwm_str, &fwm) < 0) { + return(-1); + } + + return (__fwm_add_fwmark(fwm)); +} + + +/********************************************************************** + * __fwm_add_name + * Add a name to __fwm_hostent + * pre: name: name to add to __fwm_hostent + * post: name is copied using strcpy. + * __fwm_hostent is added to h_addr_list. If h_name is + * null, it is set to name. + * return: 0 on success + * -1 on error + **********************************************************************/ + +static int __fwm_add_name(const char *name) +{ + void **a; + char *name_cpy; + + name_cpy = strdup(name); + if (name_cpy == NULL) { + return (-1); + } + + a = __fwm_array_add_element((void **) __fwm_h_aliases, + &__fwm_no_h_aliases, (void *) name_cpy, 0); + if (a == NULL) { + __fwm_reset_global(); + endfwment(); + return (-1); + } + + __fwm_h_aliases = (char **) a; + __fwm_hostent.h_aliases = __fwm_h_aliases; + + if (__fwm_hostent.h_name == NULL) { + __fwm_hostent.h_name = __fwm_hostent.h_aliases[0]; + } + + return (0); +} + + +/********************************************************************** + * __fwm_simple_hostent + * hostent with fwm as the only entry in h_addr_list and + * name as the h_name and only entry in h_aliases + * pre: fwm: fwm to be the "address" in the hostent + * name: "name" for the hostent + * post: The global __fwm_hostent is set with fwm and name + * return: pointer to __fwm_hostent + * NULL on error + **********************************************************************/ + +static struct hostent *__fwm_simple_hostent(const fwm_t fwm, const char *name) +{ + __fwm_reset_global(); + if (__fwm_add_fwmark(fwm) < 0) { + endfwment(); + return (NULL); + } + if (__fwm_add_name(name) < 0) { + endfwment(); + return (NULL); + } + return(&__fwm_hostent); +} + +/********************************************************************** + * __fwm_beginfwment + * Open the fwmarks file and reset the read buffers. + * pre: FWMARKS_FILE is defined + * post: globals __fwm_getc_* globals are zeroed + * __fwm_fd is an open, read-only file descriptor to FWMARKS_FILE. + * return: none. + **********************************************************************/ + +static int __fwm_beginfwment(void) +{ + __fwm_getc_nread = 0; + __fwm_getc_offset = 0; + memset(__fwm_getc_buffer, '\0', __FWM_LOOKUP_MAX_LINE_LENGTH); + + if (__fwm_fd > 0) { + endfwment(); + } + + if ((__fwm_fd = open(FWMARKS_FILE, O_RDONLY)) < 0) { + endfwment(); + } + + return (__fwm_fd); +} + + +/********************************************************************** + * setfwment + * Rewind the fwmarks file + * pre: FWMARKS_FILE is defined + * post: If fwmarks file is already open it is rewound to the begining + * else it is opened. + * return: none + **********************************************************************/ + +void setfwment(void) +{ + if (__fwm_fd > -1) { + if (lseek(__fwm_fd, SEEK_SET, 0) < 0) { + endfwment(); + } + } else { + __fwm_beginfwment(); + } +} + + +/********************************************************************** + * endfwment + * Close the fwmarks file + * pre: none + * post: fwmarks file is closed if it was open. + * return: none + **********************************************************************/ + +void endfwment(void) +{ + if (__fwm_fd > -1) { + close(__fwm_fd); + } + __fwm_fd = -1; +} + + +/********************************************************************** + * getfwment + * Read the next valid line from the fwmarks file + * pre: none + * return: hostent for line for fwmarks file if a valid line is found + * NULL if the end of the file is reached without finding a new + * line, or on error. + * + * Note: Values are stored in internally allocated memory which is not + * persistant across calls. If you wish to keep values you should + * copy them. Don not free the memory returned by this function. + **********************************************************************/ + + +/* Mark the begining of a key */ +#define BEGIN_KEY \ + if(!in_escape && !in_comment && !in_quote){ \ + in_key=1; \ + valid_key = 0; \ + } + +/* Mark the end of a key. + * If a valid key has been read then store it */ +#define END_KEY \ + if(!in_escape && in_key && !in_quote){ \ + if(in_key && token_pos){ \ + *(token_buffer+token_pos)='\0'; \ + if(__fwm_add_fwmark_str(token_buffer) < 0) { \ + __fwm_reset_global(); \ + endfwment(); \ + return(NULL); \ + } \ + else { \ + valid_key = 1; \ + } \ + } \ + token_pos=0; \ + in_key=0; \ + } + +/* Mark the begining of a value */ +#define BEGIN_VALUE \ + if(!in_key && !in_comment && !in_quote){ \ + in_value=1; \ + } \ + +/* Mark the end of a key. + * If a valid value and a valid key have been read then store the value */ + +#define END_VALUE \ + if(!in_escape && in_value && !in_quote){ \ + if(in_value && valid_key){ \ + *(token_buffer+token_pos)='\0'; \ + if(__fwm_add_name(token_buffer) < 0 ) { \ + __fwm_reset_global(); \ + endfwment(); \ + return(NULL); \ + } \ + } \ + token_pos=0; \ + in_value=0; \ + } + +/* Mark the end of a comment if it is not escaped*/ +#define END_COMMENT \ + if(!in_escape){ \ + in_comment=0; \ + } + +/* Mark the begining of a comment if it is not escaped or in a commnet */ +#define BEGIN_COMMENT \ + if(!in_escape && !in_quote){ \ + in_comment=1; \ + } + +/* Mark the begining of an escape */ +#define BEGIN_ESCAPE \ + in_escape=1; + +/* Mark the end of an escape */ +#define END_ESCAPE \ + in_escape=0; + +#define __FWM_SINGLE_QUOTE 1 +#define __FWM_DOUBLE_QUOTE 2 + +struct hostent *getfwment(void) +{ + ssize_t token_pos; + char token_buffer[__FWM_LOOKUP_MAX_LINE_LENGTH]; + char c; + int max_token_pos = __FWM_LOOKUP_MAX_LINE_LENGTH - 3; + int i; + + int in_escape = 0; + int in_comment = 0; + int skip_char = 0; + int in_value = 0; + int in_quote = 0; + int in_key = 0; + int valid_key = 0; + + if (__fwm_fd < 0 && __fwm_beginfwment() < 0) { + return (NULL); + } + + token_pos = 0; + + __fwm_reset_global(); + + BEGIN_KEY; + + while ((i = __fwm_getc()) != EOF) { + c = (char) i; + + switch (c) { + case ' ': + case '\t': + END_KEY; + END_VALUE; + if (in_escape) { + BEGIN_VALUE; + } + END_ESCAPE; + break; + case '\n': + case '\r': + END_KEY; + END_COMMENT; + END_VALUE; + if (!in_escape && !in_quote && valid_key) { + if (__fwm_hostent.h_aliases == NULL) { + return (NULL); + } + return (&__fwm_hostent); + } + BEGIN_KEY; + END_ESCAPE; + break; + case '\\': + if (in_escape || in_quote) { + END_ESCAPE; + } else { + BEGIN_ESCAPE; + } + BEGIN_VALUE; + break; + case '#': + BEGIN_COMMENT; + END_KEY; + END_VALUE; + BEGIN_VALUE; + END_ESCAPE; + break; + case '"': + BEGIN_VALUE; + if (!in_escape && !in_comment + && !(in_quote & __FWM_SINGLE_QUOTE)) { + if (in_quote & __FWM_DOUBLE_QUOTE) { + in_quote ^= + in_quote & __FWM_DOUBLE_QUOTE; + } else { + in_quote |= __FWM_DOUBLE_QUOTE; + } + skip_char = 1; + } + END_ESCAPE; + break; + case '\'': + BEGIN_VALUE; + if (!in_escape && !in_comment) { + if (in_quote & __FWM_SINGLE_QUOTE) { + in_quote ^= __FWM_SINGLE_QUOTE; + } else { + in_quote |= __FWM_SINGLE_QUOTE; + } + skip_char = 1; + } + END_ESCAPE; + break; + default: + BEGIN_VALUE; + END_ESCAPE; + break; + } + + if (in_key | in_value && + c != '\n' && + c != '\r' && + !in_escape && !skip_char + && token_pos < max_token_pos) { + *(token_buffer + token_pos) = c; + token_pos++; + } + skip_char = 0; + + } + + __fwm_reset_global(); + return (NULL); +} + + +/********************************************************************** + * getfwmbyfwm + * Find a the names for a firewall mark + * pre: fwm: firewall mark to find names of + * post: fwmarks file is serached for the first line corresponding + * to fwm + * return: hostent connresponding to fwm as per the fwmarks file. + * + * Note: Values are stored in internally allocated memory which is not + * persistant across calls. If you wish to keep values you should + * copy them. Don not free the memory returned by this function. + **********************************************************************/ + +struct hostent *getfwmbyfwm(fwm_t fwm) +{ + struct hostent *hostent; + char **elem; + char buf[11]; + + setfwment(); + while ((hostent = getfwment()) != NULL) { + for (elem = hostent->h_addr_list; *elem != NULL; elem++) { + if (ntohl((fwm_t) * elem) == fwm) { + endfwment(); + return (hostent); + } + } + } + + endfwment(); + + /* No entry was found in the fwmarks file, so return + * the fwm as its own name */ + if (snprintf(buf, 11, "%u", fwm) < 0) { + endfwment(); + return (NULL); + } + buf[10] = '\0'; + return(__fwm_simple_hostent(fwm, buf)); +} + + +/********************************************************************** + * getfwmbyname + * Find a the fwmark and aliases for a name + * pre: fwm: name to find the firewall mark and aliases of + * post: If name is the ASCII representation of a fwm + * A hostent with that as the name and fwm is returned. + * Else + * fwmarks file is serached for the first line corresponding + * to name + * return: hostent connresponding to name as per the fwmarks file. + * + * Note: Values are stored in internally allocated memory which is not + * persistant across calls. If you wish to keep values you should + * copy them. Don not free the memory returned by this function. + **********************************************************************/ + +struct hostent *getfwmbyname(const char *name) +{ + struct hostent *hostent; + char **elem; + fwm_t fwm; + + /* If name is just the ASCII representation of an fwm then + * use that as the fwm */ + if(__fwm_str_to_fwm(name, &fwm) > -1) { + return(__fwm_simple_hostent(fwm, name)); + } + + setfwment(); + while ((hostent = getfwment()) != NULL) { + for (elem = hostent->h_aliases; *elem != NULL; elem++) { + if (strcmp(name, *elem) == 0) { + endfwment(); + fflush(NULL); + return (hostent); + } + } + } + + endfwment(); + return (NULL); + +} diff -ruN ipvs-0.9.5/ipvs/ipvsadm/fwmark_lookup.h ipvs-0.9.5.new/ipvs/ipvsadm/fwmark_lookup.h --- ipvs-0.9.5/ipvs/ipvsadm/fwmark_lookup.h Thu Jan 1 12:00:00 1970 +++ ipvs-0.9.5.new/ipvs/ipvsadm/fwmark_lookup.h Mon Oct 29 10:50:23 2001 @@ -0,0 +1,144 @@ +/* + * fwmark_lookup.h + * + * Look up firwall marks in /etc/fwmarks. This is intended to be + * analogous to /etc/hosts + * + * Authors: Horms + * + * Version: $Id: fwmark_lookup.h,v Exp $ + * + * Copyright (c) 2001 Horms + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Changes: + */ + +/* + * /etc/fwmarks + * + * The format for this file is + * + * fwnark name ... + * + * Blank lines are ignored, as is anything including and after a # (hash) + * on a line. If a \ precedes a new line then the lines will be + * concatenated. if a \ precedes any other character, including a # + * (hash) it will be treated as a literal. Anything inside single quotes + * (') will be treated as a litreal. Anything other than a (') inside + * double quotes (") will be treated as a litreal. Whitespace in names must + * be escaped or quoted. + * + * e.g. + * + * 1 jimmy james + * 2 john + * + * This associates the names jimmy ad james with fwmark 1 + * and the name john with fwmark 2 + * + */ + +#ifndef _FWMARK_LOOKUP_H +#define _FWMARK_LOOKUP_H + + +/* This should be set by a configure check */ +typedef unsigned int uint32; + +typedef uint32 fwm_t; + +#ifndef FWMARKS_FILE +#define FWMARKS_FILE "/etc/fwmarks" +#endif + + +/********************************************************************** + * setfwment + * Rewind the fwmarks file + * pre: FWMARKS_FILE is defined + * post: If fwmarks file is already open it is rewound to the begining + * else it is opened. + * return: none + **********************************************************************/ + +void setfwment(void); + + +/********************************************************************** + * endfwment + * Close the fwmarks file + * pre: none + * post: fwmarks file is closed if it was open. + * return: none + **********************************************************************/ + +void endfwment(void); + + +/********************************************************************** + * getfwment + * Read the next valid line from the fwmarks file + * pre: none + * return: hostent for line for fwmarks file if a valid line is found + * NULL if the end of the file is reached without finding a new + * line, or on error. + * + * Note: Values are stored in internally allocated memory which is not + * persistant across calls. If you wish to keep values you should + * copy them. Don not free the memory returned by this function. + **********************************************************************/ + + +struct hostent *getfwment(void); + + +/********************************************************************** + * getfwmbyfwm + * Find a the names for a firewall mark + * pre: fwm: firewall mark to find names of + * post: fwmarks file is serached for the first line corresponding + * to fwm + * return: hostent connresponding to fwm as per the fwmarks file. + * + * Note: Values are stored in internally allocated memory which is not + * persistant across calls. If you wish to keep values you should + * copy them. Don not free the memory returned by this function. + **********************************************************************/ + +struct hostent *getfwmbyfwm(fwm_t fwm); + + +/********************************************************************** + * getfwmbyname + * Find a the fwmark and aliases for a name + * pre: fwm: name to find the firewall mark and aliases of + * post: If name is the ASCII representation of a fwm + * A hostent with that as the name and fwm is returned. + * Else + * fwmarks file is serached for the first line corresponding + * to name + * return: hostent connresponding to name as per the fwmarks file. + * + * Note: Values are stored in internally allocated memory which is not + * persistant across calls. If you wish to keep values you should + * copy them. Don not free the memory returned by this function. + **********************************************************************/ + +struct hostent *getfwmbyname(const char *name); + +#endif /* _FWMARK_LOOKUP_H */ diff -ruN ipvs-0.9.5/ipvs/ipvsadm/header ipvs-0.9.5.new/ipvs/ipvsadm/header --- ipvs-0.9.5/ipvs/ipvsadm/header Thu Jan 1 12:00:00 1970 +++ ipvs-0.9.5.new/ipvs/ipvsadm/header Mon Oct 29 10:42:16 2001 @@ -0,0 +1,30 @@ +/* + * dynamic_array.c - Code to convert a stream input into a + * that can be parsed as argc and argv. + * + * Author: Horms + * + * Version: $Id: config_stream.c,v Exp $ + * + * Copyright (c) 2001 Horms + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Changes: + * Horms : scanf Glibc under Red Hat 7 does not appear + * to return EOF when input ends. Fall through + * code has been added to handle this case correctly + */ diff -ruN ipvs-0.9.5/ipvs/ipvsadm/ipvsadm.8 ipvs-0.9.5.new/ipvs/ipvsadm/ipvsadm.8 --- ipvs-0.9.5/ipvs/ipvsadm/ipvsadm.8 Wed Sep 19 03:42:54 2001 +++ ipvs-0.9.5.new/ipvs/ipvsadm/ipvsadm.8 Mon Oct 29 11:05:22 2001 @@ -4,16 +4,18 @@ .\" $Id: ipvsadm.8,v 1.8 2001/09/18 15:42:54 wensong Exp $ .\" .\" Authors: Mike Wangsmo -.\" Wensong Zhang +.\" Wensong Zhang +.\" Horms .\" .\" Changes: .\" Horms : Updated to reflect recent change of ipvsadm .\" : Style guidance taken from ipchains(8) .\" where appropriate. -.\" Wensong Zhang : Added a short note about the defense strategies +.\" Wensong Zhang : Added a short note about the defence strategies .\" Horms : Tidy up some of the description and the .\" grammar in the -f and sysctl sections .\" Wensong Zhang : -s option description taken from ipchains(8) +.\" Horms : documented /etc/fwmarks support .\" .\" This program is free software; you can redistribute it and/or modify .\" it under the terms of the GNU General Public License as published by @@ -30,7 +32,7 @@ .\" Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. .\" .\" -.TH IPVSADM 8 "18th September 2001" "LVS Administration" "Linux Administrator's Guide" +.TH IPVSADM 8 "29th October 2001" "LVS Administration" "Linux Administrator's Guide" .UC 4 .SH NAME ipvsadm \- Linux Virtual Server administration @@ -69,7 +71,7 @@ nodes. The active node of the cluster redirects service requests to a collection of server hosts that will actually perform the services. Supported features include two protocols (TCP and UDP), -three packet-forwarding methods (NAT, tunneling, and direct routing), +three packet-forwarding methods (NAT, tunnelling, and direct routing), and six load balancing algorithms (round robin, weighted round robin, least-connection, weighted least-connection, locality-based least-connection, and locality-based least-connection with @@ -149,9 +151,9 @@ the current timeout value of the corresponding entry is preserved. .TP .B --start-daemon \fIstate\fP -Start the connection synchronization daemon. The \fIstate\fP is to +Start the connection synchronisation daemon. The \fIstate\fP is to indicate that the daemon is started as master or backup. The -connection synchronization daemon is implemented inside the Linux +connection synchronisation daemon is implemented inside the Linux kernel. The master daemon running on the primary load balancer multicasts changes of connections periodically, and the backup daemon running the backup load balancers receives multicast message and @@ -161,7 +163,7 @@ can continue to access the service. .TP .B --stop-daemon -Stop the connection synchronization daemon. +Stop the connection synchronisation daemon. .TP \fB-h, --help\fR Display a description of the command syntax. @@ -187,8 +189,8 @@ virtual service instead of an address, port and protocol (UDP or TCP). The marking of packets with a firewall-mark is configured using the -m|--mark option to \fBiptables\fR(8). It can be used to build a -virtual service assoicated with the same real servers, covering -multiple IP addresss, port and protocol tripplets. +virtual service associated with the same real servers, covering +multiple IP addresses, port and protocol triplets. .sp Using firewall-mark virtual services provides a convenient method of grouping together different IP addresses, ports and protocols into a @@ -270,10 +272,10 @@ service name of port. In the case of the masquerading method, the host address is usually an RFC 1918 private IP address, and the port can be different from that of the associated service. With the -tunneling and direct routing methods, \fIport\fP must be equal to that +tunnelling and direct routing methods, \fIport\fP must be equal to that of the service address. For normal services, the port specified in the service address will be used if \fIport\fP is not specified. For -fwmark services, \fIport\fP may be ommitted, in which case the +fwmark services, \fIport\fP may be omitted, in which case the destination port on the real server will be the destination port of the request sent to the virtual service. .TP @@ -281,7 +283,7 @@ .sp \fB-g, --gatewaying\fR Use gatewaying (direct routing). This is the default. .sp -\fB-i, --ipip\fR Use ipip encapsulation (tunneling). +\fB-i, --ipip\fR Use ipip encapsulation (tunnelling). .sp \fB-m, --masquerading\fR Use masquerading (network access translation, or NAT). .sp @@ -405,13 +407,14 @@ modprobe ip_vs_ftp .fi .SH NOTES -The Linux Virtual Server implements three defense strategies against +.SS DENIAL OF SERVICE DEFENCE STRATEGIES +The Linux Virtual Server implements three defence strategies against some types of denial of service (DoS) attacks. The Linux Director creates an entry for each connection in order to keep its state, and each entry occupies 128 bytes effective memory. LVS's vulnerability to a DoS attack lies in the potential to increase the number entries as much as possible until the linux director runs out of memory. The -three defense strategies against the attack are: Randomly drop some +three defence strategies against the attack are: Randomly drop some entries in the table. Drop 1/rate packets before forwarding them. And use secure tcp state transition table and short timeouts. The strategies are controlled by sysctl variables and corresponding @@ -422,7 +425,7 @@ /proc/sys/net/ipv4/vs/secure_tcp .PP Valid values for each variable are 0 through to 3. The default value -is 0, which disables the respective defense strategy. 1 and 2 are +is 0, which disables the respective defence strategy. 1 and 2 are automatic modes - when there is no enough available memory, the respective strategy will be enabled and the variable is automatically set to 2, otherwise the strategy is disabled and the variable is set @@ -433,6 +436,36 @@ .sp /proc/sys/net/ipv4/vs/amemthresh /proc/sys/net/ipv4/vs/timeout_* +.SS NAMING FIREWALL MARKS +ipvsadm understands names for firwall marks. These are assigned +by adding entries to /etc/fwmarks which is intended to +be analogous to /etc/hosts. +.PP +The format of the file is "fwmark name ...". +Blank lines are ignored, as is anything including and after a # (hash) on a +line. If a \\ precedes a new line then the lines will be concatenated. if a +\\ precedes any other character, including a # (hash) it will be treated as +a literal. Anything inside single quotes (') will be treated as a literal. +Anything other than a (') inside double quotes (") will be treated as a +literal. Whitespace in names must be escaped or quoted. +.sp +.nf +e.g. +# /etc/fwmarks +1 a-name +2 another-name yet-another-name +.fi +.PP +This associates a-name with fwmark 1 and associates another-name +and yet-another-name with fwmark 2. +In this way names may be used instead of numeric values when +defining fwmark virtual services +.sp +.nf +e.g. +ipvsadm -A -f a-name +ipvsadm -a -f a-name -r 127.0.0.1 +.fi .SH FILES .I /proc/net/ip_masq/vs .br @@ -469,6 +502,8 @@ .I /proc/sys/net/ipv4/vs/timeout_timewait .br .I /proc/sys/net/ipv4/vs/timeout_udp +.br +.I /etc/fwmarks .SH SEE ALSO \fBiptables\fP(8), \fBinsmod\fP(8), \fBmodprobe\fP(8) .SH AUTHORS @@ -477,5 +512,5 @@ Peter Kese man page - Mike Wangsmo Wensong Zhang - Horms + Horms .fi diff -ruN ipvs-0.9.5/ipvs/ipvsadm/ipvsadm.c ipvs-0.9.5.new/ipvs/ipvsadm/ipvsadm.c --- ipvs-0.9.5/ipvs/ipvsadm/ipvsadm.c Sat Oct 20 04:05:17 2001 +++ ipvs-0.9.5.new/ipvs/ipvsadm/ipvsadm.c Mon Oct 29 10:49:39 2001 @@ -52,6 +52,7 @@ * Horms : added -v option * Wensong Zhang : rewrite most code of parsing options and * processing options. + * Horms : added /etc/fwmarks support * * * ippfvsadm - Port Fowarding & Virtual Server ADMinistration program @@ -122,6 +123,7 @@ #endif #include "config_stream.h" +#include "fwmark_lookup.h" #include "libipvs/libipvs.h" #define IPVSADM_VERSION_NO "v" VERSION @@ -241,13 +243,15 @@ int str_is_digit(const char *str); int string_to_number(const char *s, int min, int max); int host_to_addr(const char *name, struct in_addr *addr); +int name_to_fwm(const char *name, fwm_t *fwm); char * addr_to_host(struct in_addr *addr); char * addr_to_anyname(struct in_addr *addr); int service_to_port(const char *name, unsigned short proto); -char * port_to_service(int port, unsigned short proto); -char * port_to_anyname(int port, unsigned short proto); -char * addrport_to_anyname(struct in_addr *addr, int port, +char * port_to_service(unsigned int port, unsigned short proto); +char * port_to_anyname(unsigned int port, unsigned short proto); +char * addrport_to_anyname(struct in_addr *addr, unsigned int port, unsigned short proto, unsigned int format); +char * fwmark_to_anyname(fwm_t fwm, unsigned int format); int parse_service(char *buf, u_int16_t proto, u_int32_t *addr, u_int16_t *port); int parse_netmask(char *buf, u_int32_t *addr); @@ -932,20 +936,26 @@ /* - * Parse IP fwmark from the argument. + * Parse fwmark from the argument. */ unsigned int parse_fwmark(char *buf) { unsigned long l; + unsigned int i; char *end; errno = 0; l = strtol(buf, &end, 10); - if (*end != '\0' || end == buf || - errno == ERANGE || l <= 0 || l > UINT_MAX) - fail(2, "invalid fwmark value `%s' specified", buf); + if (*end == '\0' && end != buf && + errno != ERANGE && l > 0 && l < UINT_MAX) { + return(l); + } + else if(name_to_fwm(buf, &i) > -1) { + return(ntohl(i)); + } - return l; + fail(2, "invalid fwmark value `%s' specified", buf); + return 0; } @@ -1401,19 +1411,22 @@ { struct ip_vs_get_dests *d; char svc_name[64]; + char *vname; int i; if (!(d = ipvs_get_dests(svc))) exit(1); if (svc->fwmark) { + if(!(vname = fwmark_to_anyname(svc->fwmark, format))) + fail(2, "fwmark_to_anyname"); if (format & FMT_RULE) - sprintf(svc_name, "-f %d", svc->fwmark); + sprintf(svc_name, "-f %s", vname); else - sprintf(svc_name, "FWM %d", svc->fwmark); + sprintf(svc_name, "FWM %s", vname); + free(vname); } else { struct in_addr vaddr; - char *vname; vaddr.s_addr = svc->addr; if (!(vname = addrport_to_anyname(&vaddr, ntohs(svc->port), @@ -1597,6 +1610,20 @@ } +int name_to_fwm(const char *name, fwm_t *fwm) +{ + struct hostent *hostent; + + if ((hostent = getfwmbyname(name)) == NULL) { + return -1; + } + + /* warning: we just handle h_addr_list[0] here */ + *fwm = (fwm_t) hostent->h_addr_list[0]; + return 0; +} + + char * addr_to_host(struct in_addr *addr) { struct hostent *host; @@ -1635,7 +1662,7 @@ } -char * port_to_service(int port, unsigned short proto) +char * port_to_service(unsigned int port, unsigned short proto) { struct servent *service; @@ -1650,7 +1677,7 @@ } -char * port_to_anyname(int port, unsigned short proto) +char * port_to_anyname(unsigned int port, unsigned short proto) { char *name; static char buf[10]; @@ -1658,13 +1685,13 @@ if ((name = port_to_service(port, proto)) != NULL) return name; else { - sprintf(buf, "%d", port); + sprintf(buf, "%u", port); return buf; } } -char * addrport_to_anyname(struct in_addr *addr, int port, +char * addrport_to_anyname(struct in_addr *addr, unsigned int port, unsigned short proto, unsigned int format) { char *buf; @@ -1678,6 +1705,28 @@ } else { snprintf(buf, 60, "%s:%s", addr_to_anyname(addr), port_to_anyname(port, proto)); + } + + return buf; +} + + +char * fwmark_to_anyname(fwm_t fwm, unsigned int format) +{ + char *buf; + struct hostent *h; + + if (!(buf=malloc(60))) + return NULL; + + if (format & FMT_NUMERIC) { + snprintf(buf, 60, "%u", fwm); + } else { + if((h = getfwmbyfwm(fwm)) == NULL) { + free(buf); + return NULL; + } + snprintf(buf, 60, "%s", h->h_name); } return buf;