?? ipvsadm.c
字號:
/* * ipvsadm - IP Virtual Server ADMinistration program * for IPVS NetFilter Module in kernel 2.4 * * Version: $Id: ipvsadm.c,v 1.27 2005/12/10 16:00:07 wensong Exp $ * * Authors: Wensong Zhang <wensong@linuxvirtualserver.org> * Peter Kese <peter.kese@ijs.si> * * This program is based on ippfvsadm. * * Changes: * Wensong Zhang : added the editting service & destination support * Wensong Zhang : added the feature to specify persistent port * Jacob Rief : found the bug that masquerading dest of * different vport and dport cannot be deleted. * Wensong Zhang : fixed it and changed some cosmetic things * Wensong Zhang : added the timeout setting for persistent service * Wensong Zhang : added specifying the dest weight zero * Wensong Zhang : fixed the -E and -e options * Wensong Zhang : added the long options * Wensong Zhang : added the hostname and portname input * Wensong Zhang : added the hostname and portname output * Lars Marowsky-Br閑 : added persistence granularity support * Julian Anastasov : fixed the (null) print for unknown services * Wensong Zhang : added the port_to_anyname function * Horms : added option to read commands from stdin * Horms : modified usage function so it prints to * : stdout if an exit value of 0 is used and * : stdout otherwise. Program is then terminated * : with the supplied exit value. * Horms : updated manpage and usage funtion so * : the reflect the options available * Wensong Zhang : added option to write rules to stdout * Horms : added ability to specify a fwmark * : instead of a server and port for * : a virtual service * Horms : tightened up checking of services * : in parse_service * Horms : ensure that a -r is passed when needed * Wensong Zhang : fixed the output of fwmark rules * Horms : added kernel version verification * Horms : Specifying command and option options * (e.g. -Ln or -At) in one short option * with popt problem fixed. * Wensong Zhang : split the process_options and make * two versions of parse_options. * Horms : attempting to save or restore when * compiled against getopt_long now results * in an informative error message rather * than the usage information * Horms : added -v option * Wensong Zhang : rewrite most code of parsing options and * processing options. * Alexandre Cassen : added ipvs_syncd SyncdID support to filter * incoming sync messages. * Guy Waugh & Ratz : added --exact option and spelling cleanup * * * ippfvsadm - Port Fowarding & Virtual Server ADMinistration program * * Copyright (c) 1998 Wensong Zhang * All rights reserved. * * Author: Wensong Zhang <wensong@iinchina.net> * * This ippfvsadm is derived from Steven Clarke's ipportfw program. * * portfw - Port Forwarding Table Editing v1.1 * * Copyright (c) 1997 Steven Clarke * All rights reserved. * * Author: Steven Clarke <steven@monmouth.demon.co.uk> * * 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. * */#undef __KERNEL__ /* Makefile lazyness ;) */#include <stdio.h>#include <stdlib.h>#include <getopt.h>#include <netdb.h>#include <string.h>#include <unistd.h>#include <errno.h>#include <ctype.h>#include <stdarg.h>#include <netinet/in.h>#include <sys/socket.h>#include <sys/types.h>#include <sys/param.h>#include <sys/wait.h> /* For waitpid */#include <arpa/inet.h>#include <net/if.h>#include <netinet/ip_icmp.h>#include <netinet/udp.h>#include <netinet/tcp.h>#ifdef HAVE_POPT#include "popt.h"#define IPVS_OPTION_PROCESSING "popt"#else#define IPVS_OPTION_PROCESSING "getopt_long"#endif#include "config_stream.h"#include "libipvs/libipvs.h"#define IPVSADM_VERSION_NO "v" VERSION#define IPVSADM_VERSION_DATE "2005/12/10"#define IPVSADM_VERSION IPVSADM_VERSION_NO " " IPVSADM_VERSION_DATE#define MAX_TIMEOUT (86400*31) /* 31 days */#define CMD_NONE 0#define CMD_ADD (CMD_NONE+1)#define CMD_EDIT (CMD_NONE+2)#define CMD_DEL (CMD_NONE+3)#define CMD_FLUSH (CMD_NONE+4)#define CMD_LIST (CMD_NONE+5)#define CMD_ADDDEST (CMD_NONE+6)#define CMD_DELDEST (CMD_NONE+7)#define CMD_EDITDEST (CMD_NONE+8)#define CMD_TIMEOUT (CMD_NONE+9)#define CMD_STARTDAEMON (CMD_NONE+10)#define CMD_STOPDAEMON (CMD_NONE+11)#define CMD_RESTORE (CMD_NONE+12)#define CMD_SAVE (CMD_NONE+13)#define CMD_ZERO (CMD_NONE+14)#define CMD_MAX CMD_ZERO#define NUMBER_OF_CMD (CMD_MAX - CMD_NONE)static const char* cmdnames[] = { "add-service", "edit-service", "delete-service", "flush", "list", "add-server", "delete-server", "edit-server", "set", "start-daemon", "stop-daemon", "restore", "save", "zero",};#define OPT_NONE 0x000000#define OPT_NUMERIC 0x000001#define OPT_CONNECTION 0x000002#define OPT_SERVICE 0x000004#define OPT_SCHEDULER 0x000008#define OPT_PERSISTENT 0x000010#define OPT_NETMASK 0x000020#define OPT_SERVER 0x000040#define OPT_FORWARD 0x000080#define OPT_WEIGHT 0x000100#define OPT_UTHRESHOLD 0x000200#define OPT_LTHRESHOLD 0x000400#define OPT_MCAST 0x000800#define OPT_TIMEOUT 0x001000#define OPT_DAEMON 0x002000#define OPT_STATS 0x004000#define OPT_RATE 0x008000#define OPT_THRESHOLDS 0x010000#define OPT_PERSISTENTCONN 0x020000#define OPT_SORT 0x040000#define OPT_SYNCID 0x080000#define OPT_EXACT 0x100000#define NUMBER_OF_OPT 21static const char* optnames[] = { "numeric", "connection", "service-address", "scheduler", "persistent", "netmask", "real-server", "forwarding-method", "weight", "u-threshold", "l-threshold", "mcast-interface", "timeout", "daemon", "stats", "rate", "thresholds", "persistent-conn", "sort", "syncid", "exact",};/* * Table of legal combinations of commands and options. * Key: * '+' compulsory * 'x' illegal * '1' exclusive (only one '1' option can be supplied) * ' ' optional */static const char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] ={ /* -n -c svc -s -p -M -r fwd -w -x -y -mc tot dmn -st -rt thr -pc srt sid -ex *//*ADD*/ {'x', 'x', '+', ' ', ' ', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},/*EDIT*/ {'x', 'x', '+', ' ', ' ', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},/*DEL*/ {'x', 'x', '+', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},/*FLUSH*/ {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},/*LIST*/ {' ', '1', '1', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', '1', '1', ' ', ' ', ' ', ' ', ' ', ' ', ' '},/*ADDSRV*/ {'x', 'x', '+', 'x', 'x', 'x', '+', ' ', ' ', ' ', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},/*DELSRV*/ {'x', 'x', '+', 'x', 'x', 'x', '+', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},/*EDITSRV*/ {'x', 'x', '+', 'x', 'x', 'x', '+', ' ', ' ', ' ', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},/*TIMEOUT*/ {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},/*STARTD*/ {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},/*STOPD*/ {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},/*RESTORE*/ {'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},/*SAVE*/ {' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},/*ZERO*/ {'x', 'x', ' ', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'},};/* printing format flags */#define FMT_NONE 0x0000#define FMT_NUMERIC 0x0001#define FMT_RULE 0x0002#define FMT_STATS 0x0004#define FMT_RATE 0x0008#define FMT_THRESHOLDS 0x0010#define FMT_PERSISTENTCONN 0x0020#define FMT_SORT 0x0040#define FMT_EXACT 0x0080#define SERVICE_NONE 0x0000#define SERVICE_ADDR 0x0001#define SERVICE_PORT 0x0002/* default scheduler */#define DEF_SCHED "wlc"/* default multicast interface name */#define DEF_MCAST_IFN "eth0"#define CONN_PROC_FILE "/proc/net/ip_vs_conn"struct ipvs_command_entry { int cmd; ipvs_service_t svc; ipvs_dest_t dest; ipvs_timeout_t timeout; ipvs_daemon_t daemon;};/* various parsing helpers & parsing functions */static int str_is_digit(const char *str);static int string_to_number(const char *s, int min, int max);static int host_to_addr(const char *name, struct in_addr *addr);static char * addr_to_host(struct in_addr *addr);static char * addr_to_anyname(struct in_addr *addr);static int service_to_port(const char *name, unsigned short proto);static char * port_to_service(unsigned short port, unsigned short proto);static char * port_to_anyname(unsigned short port, unsigned short proto);static char * addrport_to_anyname(struct in_addr *addr, unsigned short port, unsigned short proto, unsigned int format);static int parse_service(char *buf, u_int16_t proto, u_int32_t *addr, u_int16_t *port);static int parse_netmask(char *buf, u_int32_t *addr);static int parse_timeout(char *buf, int min, int max);static unsigned int parse_fwmark(char *buf);/* check the options based on the commands_v_options table */static void generic_opt_check(int command, int options);static void set_command(int *cmd, const int newcmd);static void set_option(unsigned int *options, unsigned int option);static void tryhelp_exit(const char *program, const int exit_status);static void usage_exit(const char *program, const int exit_status);static void version_exit(int exit_status);static void version(FILE *stream);static void fail(int err, char *msg, ...);/* various listing functions */static void list_conn(unsigned int format);static void list_service(ipvs_service_t *svc, unsigned int format);static void list_all(unsigned int format);static void list_timeout(void);static void list_daemon(void);static int modprobe_ipvs(void);static void check_ipvs_version(void);static int process_options(int argc, char **argv, int reading_stdin);int main(int argc, char **argv){ int result; if (ipvs_init()) { /* try to insmod the ip_vs module if ipvs_init failed */ if (modprobe_ipvs() || ipvs_init()) fail(2, "Can't initialize ipvs: %s\n" "Are you sure that IP Virtual Server is " "built in the kernel or as module?", ipvs_strerror(errno)); } /* warn the user if the IPVS version is out of date */ check_ipvs_version(); /* list the table if there is no other arguement */ if (argc == 1){ list_all(FMT_NONE); ipvs_close(); return 0; } /* process command line arguments */ result = process_options(argc, argv, 0); ipvs_close(); return result;}#ifdef HAVE_POPTstatic intparse_options(int argc, char **argv, struct ipvs_command_entry *ce, unsigned int *options, unsigned int *format){ int c, parse; poptContext context; char *optarg=NULL; struct poptOption options_table[] = { {"add-service", 'A', POPT_ARG_NONE, NULL, 'A'}, {"edit-service", 'E', POPT_ARG_NONE, NULL, 'E'}, {"delete-service", 'D', POPT_ARG_NONE, NULL, 'D'}, {"clear", 'C', POPT_ARG_NONE, NULL, 'C'}, {"list", 'L', POPT_ARG_NONE, NULL, 'L'}, {"list", 'l', POPT_ARG_NONE, NULL, 'l'}, {"zero", 'Z', POPT_ARG_NONE, NULL, 'Z'}, {"add-server", 'a', POPT_ARG_NONE, NULL, 'a'}, {"edit-server", 'e', POPT_ARG_NONE, NULL, 'e'}, {"delete-server", 'd', POPT_ARG_NONE, NULL, 'd'}, {"set", '\0', POPT_ARG_NONE, NULL, '4'}, {"help", 'h', POPT_ARG_NONE, NULL, 'h'}, {"version", 'v', POPT_ARG_NONE, NULL, 'v'}, {"restore", 'R', POPT_ARG_NONE, NULL, 'R'}, {"save", 'S', POPT_ARG_NONE, NULL, 'S'}, {"start-daemon", '\0', POPT_ARG_STRING, &optarg, '1'}, {"stop-daemon", '\0', POPT_ARG_STRING, &optarg, '2'}, {"tcp-service", 't', POPT_ARG_STRING, &optarg, 't'}, {"udp-service", 'u', POPT_ARG_STRING, &optarg, 'u'}, {"fwmark-service", 'f', POPT_ARG_STRING, &optarg, 'f'}, {"scheduler", 's', POPT_ARG_STRING, &optarg, 's'}, {"persistent", 'p', POPT_ARG_STRING|POPT_ARGFLAG_OPTIONAL, &optarg, 'p'}, {"netmask", 'M', POPT_ARG_STRING, &optarg, 'M'}, {"real-server", 'r', POPT_ARG_STRING, &optarg, 'r'}, {"masquerading", 'm', POPT_ARG_NONE, NULL, 'm'}, {"ipip", 'i', POPT_ARG_NONE, NULL, 'i'}, {"gatewaying", 'g', POPT_ARG_NONE, NULL, 'g'}, {"weight", 'w', POPT_ARG_STRING, &optarg, 'w'}, {"u-threshold", 'x', POPT_ARG_STRING, &optarg, 'x'}, {"l-threshold", 'y', POPT_ARG_STRING, &optarg, 'y'}, {"numeric", 'n', POPT_ARG_NONE, NULL, 'n'}, {"connection", 'c', POPT_ARG_NONE, NULL, 'c'}, {"mcast-interface", '\0', POPT_ARG_STRING, &optarg, '3'}, {"syncid", '\0', POPT_ARG_STRING, &optarg, 'I'}, {"timeout", '\0', POPT_ARG_NONE, NULL, '5'}, {"daemon", '\0', POPT_ARG_NONE, NULL, '6'}, {"stats", '\0', POPT_ARG_NONE, NULL, '7'}, {"rate", '\0', POPT_ARG_NONE, NULL, '8'}, {"thresholds", '\0', POPT_ARG_NONE, NULL, '9'}, {"persistent-conn", '\0', POPT_ARG_NONE, NULL, 'P'}, {"sort", '\0', POPT_ARG_NONE, NULL, '0'}, {"exact", 'X', POPT_ARG_NONE, NULL, 'X'}, {NULL, 0, 0, NULL, 0} }; context = poptGetContext("ipvsadm", argc, (const char **)argv, options_table, 0); if ((c = poptGetNextOpt(context)) < 0) tryhelp_exit(argv[0], -1); switch (c) { case 'A': set_command(&ce->cmd, CMD_ADD); break; case 'E': set_command(&ce->cmd, CMD_EDIT); break; case 'D': set_command(&ce->cmd, CMD_DEL); break; case 'a': set_command(&ce->cmd, CMD_ADDDEST); break; case 'e': set_command(&ce->cmd, CMD_EDITDEST); break; case 'd': set_command(&ce->cmd, CMD_DELDEST); break; case 'C': set_command(&ce->cmd, CMD_FLUSH); break; case 'L': case 'l': set_command(&ce->cmd, CMD_LIST); break; case 'Z': set_command(&ce->cmd, CMD_ZERO); break; case '4': set_command(&ce->cmd, CMD_TIMEOUT); break; case 'R': set_command(&ce->cmd, CMD_RESTORE); break; case 'S': set_command(&ce->cmd, CMD_SAVE); break; case '1': set_command(&ce->cmd, CMD_STARTDAEMON); if (!strcmp(optarg, "master")) ce->daemon.state = IP_VS_STATE_MASTER; else if (!strcmp(optarg, "backup")) ce->daemon.state = IP_VS_STATE_BACKUP; else fail(2, "illegal start-daemon parameter specified"); break; case '2': set_command(&ce->cmd, CMD_STOPDAEMON); if (!strcmp(optarg, "master")) ce->daemon.state = IP_VS_STATE_MASTER; else if (!strcmp(optarg, "backup")) ce->daemon.state = IP_VS_STATE_BACKUP; else fail(2, "illegal start_daemon specified"); break; case 'h': usage_exit(argv[0], 0); break; case 'v': version_exit(0); break; default: tryhelp_exit(argv[0], -1); } while ((c=poptGetNextOpt(context)) >= 0){ switch (c) { case 't': case 'u': set_option(options, OPT_SERVICE); ce->svc.protocol = (c=='t' ? IPPROTO_TCP : IPPROTO_UDP); parse = parse_service(optarg, ce->svc.protocol, &ce->svc.addr, &ce->svc.port); if (!(parse & SERVICE_ADDR)) fail(2, "illegal virtual server "
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -