?? ipvsadm.c
字號:
ce.dest.weight = 1; /* Set direct routing as default forwarding method */ ce.dest.conn_flags = IP_VS_CONN_F_DROUTE; /* Set the default persistent granularity to /32 mask */ ce.svc.netmask = ((u_int32_t) 0xffffffff); if (parse_options(argc, argv, &ce, &options, &format)) return -1; generic_opt_check(ce.cmd, options); if (ce.cmd == CMD_ADD || ce.cmd == CMD_EDIT) { /* Make sure that port zero service is persistent */ if (!ce.svc.fwmark && !ce.svc.port && (ce.svc.flags != IP_VS_SVC_F_PERSISTENT)) fail(2, "Zero port specified " "for non-persistent service"); /* Set the default scheduling algorithm if not specified */ if (strlen(ce.svc.sched_name) == 0) strcpy(ce.svc.sched_name, DEF_SCHED); } if (ce.cmd == CMD_STARTDAEMON && strlen(ce.daemon.mcast_ifn) == 0) strcpy(ce.daemon.mcast_ifn, DEF_MCAST_IFN); if (ce.cmd == CMD_ADDDEST || ce.cmd == CMD_EDITDEST) { /* * The destination port must be equal to the service port * if the IP_VS_CONN_F_TUNNEL or IP_VS_CONN_F_DROUTE is set. * Don't worry about this if fwmark is used. */ if (!ce.svc.fwmark && (ce.dest.conn_flags == IP_VS_CONN_F_TUNNEL || ce.dest.conn_flags == IP_VS_CONN_F_DROUTE)) ce.dest.port = ce.svc.port; } switch (ce.cmd) { case CMD_LIST: if ((options & OPT_CONNECTION || options & OPT_TIMEOUT || options & OPT_DAEMON) && (options & OPT_STATS || options & OPT_PERSISTENTCONN || options & OPT_RATE || options & OPT_THRESHOLDS)) fail(2, "options conflicts in the list command"); if (options & OPT_CONNECTION) list_conn(format); else if (options & OPT_SERVICE) list_service(&ce.svc, format); else if (options & OPT_TIMEOUT) list_timeout(); else if (options & OPT_DAEMON) list_daemon(); else list_all(format); return 0; case CMD_RESTORE: return restore_table(argc, argv, reading_stdin); case CMD_SAVE: format |= FMT_RULE; list_all(format); return 0; case CMD_FLUSH: result = ipvs_flush(); break; case CMD_ADD: result = ipvs_add_service(&ce.svc); break; case CMD_EDIT: result = ipvs_update_service(&ce.svc); break; case CMD_DEL: result = ipvs_del_service(&ce.svc); break; case CMD_ZERO: result = ipvs_zero_service(&ce.svc); break; case CMD_ADDDEST: result = ipvs_add_dest(&ce.svc, &ce.dest); break; case CMD_EDITDEST: result = ipvs_update_dest(&ce.svc, &ce.dest); break; case CMD_DELDEST: result = ipvs_del_dest(&ce.svc, &ce.dest); break; case CMD_TIMEOUT: result = ipvs_set_timeout(&ce.timeout); break; case CMD_STARTDAEMON: result = ipvs_start_daemon(&ce.daemon); break; case CMD_STOPDAEMON: result = ipvs_stop_daemon(&ce.daemon); } if (result) fprintf(stderr, "%s\n", ipvs_strerror(errno)); return result;}static int string_to_number(const char *s, int min, int max){ long number; char *end; errno = 0; number = strtol(s, &end, 10); if (*end == '\0' && end != s) { /* We parsed a number, let's see if we want this. */ if (errno != ERANGE && min <= number && number <= max) return number; } return -1;}/* * Parse the timeout value. */static int parse_timeout(char *buf, int min, int max){ int i; /* it is just for parsing timeout of persistent service */ if (buf == NULL) return IPVS_SVC_PERSISTENT_TIMEOUT; if ((i=string_to_number(buf, min, max)) == -1) fail(2, "invalid timeout value `%s' specified", buf); return i;}/* * Parse IP fwmark from the argument. */static unsigned int parse_fwmark(char *buf){ unsigned long l; 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); return l;}/* * Get netmask. * Return 0 if failed, * 1 if addr read */static int parse_netmask(char *buf, u_int32_t *addr){ struct in_addr inaddr; if(buf == NULL) return 0; if (inet_aton(buf, &inaddr) != 0) *addr = inaddr.s_addr; else if (host_to_addr(buf, &inaddr) != -1) *addr = inaddr.s_addr; else return 0; return 1;}/* * Get IP address and port from the argument. * Result is a logical or of * SERVICE_NONE: no service elements set/error * SERVICE_ADDR: addr set * SERVICE_PORT: port set */static intparse_service(char *buf, u_int16_t proto, u_int32_t *addr, u_int16_t *port){ char *portp; long portn; int result=SERVICE_NONE; struct in_addr inaddr; if(buf==NULL || str_is_digit(buf)) return SERVICE_NONE; portp = strchr(buf, ':'); if (portp != NULL) *portp = '\0'; if (inet_aton(buf, &inaddr) != 0) *addr = inaddr.s_addr; else if (host_to_addr(buf, &inaddr) != -1) *addr = inaddr.s_addr; else return SERVICE_NONE; result |= SERVICE_ADDR; if (portp != NULL){ result |= SERVICE_PORT; if ((portn=string_to_number(portp+1, 0, 65535)) != -1) *port = htons(portn); else if ((portn=service_to_port(portp+1, proto)) != -1) *port = htons(portn); else return SERVICE_NONE; } return result;}static voidgeneric_opt_check(int command, int options){ int i, j; int last = 0, count = 0; /* Check that commands are valid with options. */ i = command - CMD_NONE -1; for (j = 0; j < NUMBER_OF_OPT; j++) { if (!(options & (1<<j))) { if (commands_v_options[i][j] == '+') fail(2, "You need to supply the '%s' " "option for the '%s' command", optnames[j], cmdnames[i]); } else { if (commands_v_options[i][j] == 'x') fail(2, "Illegal '%s' option with " "the '%s' command", optnames[j], cmdnames[i]); if (commands_v_options[i][j] == '1') { count++; if (count == 1) { last = j; continue; } fail(2, "The option '%s' conflicts with the " "'%s' option in the '%s' command", optnames[j], optnames[last], cmdnames[i]); } } }}static inline const char *opt2name(int option){ const char **ptr; for (ptr = optnames; option > 1; option >>= 1, ptr++); return *ptr;}static voidset_command(int *cmd, const int newcmd){ if (*cmd != CMD_NONE) fail(2, "multiple commands specified"); *cmd = newcmd;}static voidset_option(unsigned int *options, unsigned int option){ if (*options & option) fail(2, "multiple '%s' options specified", opt2name(option)); *options |= option;}static void tryhelp_exit(const char *program, const int exit_status){ fprintf(stderr, "Try `%s -h' or '%s --help' for more information.\n", program, program); exit(exit_status);}static void usage_exit(const char *program, const int exit_status){ FILE *stream; if (exit_status != 0) stream = stderr; else stream = stdout; version(stream); fprintf(stream, "Usage:\n" " %s -A|E -t|u|f service-address [-s scheduler] [-p [timeout]] [-M netmask]\n" " %s -D -t|u|f service-address\n" " %s -C\n" " %s -R\n" " %s -S [-n]\n" " %s -a|e -t|u|f service-address -r server-address [options]\n" " %s -d -t|u|f service-address -r server-address\n" " %s -L|l [options]\n" " %s -Z [-t|u|f service-address]\n" " %s --set tcp tcpfin udp\n" " %s --start-daemon state [--mcast-interface interface] [--syncid sid]\n" " %s --stop-daemon state\n" " %s -h\n\n", program, program, program, program, program, program, program, program, program, program, program, program, program); fprintf(stream, "Commands:\n" "Either long or short options are allowed.\n" " --add-service -A add virtual service with options\n" " --edit-service -E edit virtual service with options\n" " --delete-service -D delete virtual service\n" " --clear -C clear the whole table\n" " --restore -R restore rules from stdin\n" " --save -S save rules to stdout\n" " --add-server -a add real server with options\n" " --edit-server -e edit real server with options\n" " --delete-server -d delete real server\n" " --list -L|-l list the table\n" " --zero -Z zero counters in a service or all services\n" " --set tcp tcpfin udp set connection timeout values\n" " --start-daemon start connection sync daemon\n" " --stop-daemon stop connection sync daemon\n" " --help -h display this help message\n\n" ); fprintf(stream, "Options:\n" " --tcp-service -t service-address service-address is host[:port]\n" " --udp-service -u service-address service-address is host[:port]\n" " --fwmark-service -f fwmark fwmark is an integer greater than zero\n" " --scheduler -s scheduler one of " SCHEDULERS ",\n" " the default scheduler is %s.\n" " --persistent -p [timeout] persistent service\n" " --netmask -M netmask persistent granularity mask\n" " --real-server -r server-address server-address is host (and port)\n" " --gatewaying -g gatewaying (direct routing) (default)\n" " --ipip -i ipip encapsulation (tunneling)\n" " --masquerading -m masquerading (NAT)\n" " --weight -w weight capacity of real server\n" " --u-threshold -x uthreshold upper threshold of connections\n" " --l-threshold -y lthreshold lower threshold of connections\n" " --mcast-interface interface multicast interface for connection sync\n" " --syncid sid syncid for connection sync (default=255)\n" " --connection -c output of current IPVS connections\n" " --timeout output of timeout (tcp tcpfin udp)\n" " --daemon output of daemon information\n" " --stats output of statistics information\n" " --rate output of rate information\n" " --exact expand numbers (display exact values)\n" " --thresholds output of thresholds information\n" " --persistent-conn output of persistent connection info\n" " --sort sorting output of service/server entries\n" " --numeric -n numeric output of addresses and ports\n", DEF_SCHED); exit(exit_status);}static void version_exit(const int exit_status){ FILE *stream; if (exit_status != 0) stream = stderr; else stream = stdout; version(stream); exit(exit_status);}static void version(FILE *stream){ fprintf(stream, "ipvsadm " IPVSADM_VERSION " (compiled with " IPVS_OPTION_PROCESSING " and IPVS v%d.%d.%d)\n", NVERSION(IP_VS_VERSION_CODE));}static void fail(int err, char *msg, ...){ va_list args; va_start(args, msg); vfprintf(stderr, msg, args); va_end(args); fprintf(stderr, "\n"); exit(err);}static int modprobe_ipvs(void){ char *argv[] = { "/sbin/modprobe", "--", "ip_vs", NULL }; int child; int status; int rc; if (!(child = fork())) { execv(argv[0], argv); exit(1); } rc = waitpid(child, &status, 0); if (!WIFEXITED(status) || WEXITSTATUS(status)) { return 1; } return 0;}static void check_ipvs_version(void){ /* verify the IPVS version */ if (ipvs_info.version < IPVS_VERSION(MINIMUM_IPVS_VERSION_MAJOR, MINIMUM_IPVS_VERSION_MINOR, MINIMUM_IPVS_VERSION_PATCH)) { fprintf(stderr, "Warning: IPVS version mismatch: \n" " Kernel compiled with IPVS version %d.%d.%d\n" " ipvsadm " IPVSADM_VERSION_NO " requires minimum IPVS version %d.%d.%d\n\n", NVERSION(ipvs_info.version), MINIMUM_IPVS_VERSION_MAJOR, MINIMUM_IPVS_VERSION_MINOR, MINIMUM_IPVS_VERSION_PATCH); }}static void print_conn(char *buf, unsigned int format){ char protocol[8]; unsigned short proto; struct in_addr caddr; unsigned short cport; struct in_addr vaddr; unsigned short vport; struct in_addr daddr; unsigned short dport; char state[16]; unsigned int expires;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -