/*- * Copyright (c) 2004 Andrey Simonenko * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "config.h" #ifndef lint static const char rcsid[] ATTR_UNUSED = "@(#)$Id: ipactl.c,v 1.3.2.5 2007/05/11 16:29:59 simon Exp $"; #endif /* !lint */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pathnames.h" #include "ipa_mod.h" #include "ipactl.h" #ifndef PF_LOCAL # ifdef PF_UNIX # define PF_LOCAL PF_UNIX # else # ifdef AF_LOCAL # define PF_LOCAL AF_LOCAL # else # ifdef AF_UNIX # define PF_LOCAL AF_UNIX # else # error cannot define PF_LOCAL # endif # endif # endif #endif #define IPACTL_NAME "ipactl" #ifndef IPACTL_ANSWER_MAX # define IPACTL_ANSWER_MAX (100 * 1024) #endif /* * All strto_uintxx() functions get strings with positive decimal * integers, so it is not necessary to check '-' in the first character * of a string inside strto_uintxx() functions (remember, that strtoul() * and strtoull() work with negative values). */ static const char *envprogname; static int wait_answer = 1; /* 0, if -n. */ static u_int ctl_timeout = 0; /* -w */ static const char *ctl_socket_path = IPA_CTL_SOCKET; /* -s */ static const char *rule_name = NULL; /* -r */ #ifdef WITH_LIMITS # define OPTSTRING_LIMITS "l:" static const char *limit_name = NULL; /* -l */ #else # define OPTSTRING_LIMITS "" #endif #ifdef WITH_THRESHOLDS # define OPTSTRING_THRESHOLDS "t:" static const char *threshold_name = NULL; /* -t */ #else # define OPTSTRING_THRESHOLDS "" #endif #define OPTSTRING ":hnvr:s:w:" OPTSTRING_LIMITS OPTSTRING_THRESHOLDS static int sockfd; /* Socket descriptor. */ static struct ctl_cmd_query cmd_query; static struct ctl_cmd_answer cmd_answer; static struct ctl_cmd_answer_status cmd_answer_status; #ifdef WITH_ANY_LIMITS static struct ctl_cmd_answer_set cmd_answer_set; #endif static void *cmd_answer_aux = NULL; /* Auxiliary answer. */ static int cmd_answer_aux_exp = 0; /* Non-zero if auxiliary answer is expected. */ static size_t cmd_answer_aux_size; /* Auxiliary answer size. */ #define CTL_REQ_RULE 0x01 #ifdef WITH_LIMITS # define CTL_REQ_LIMIT 0x02 #endif struct ctl_cmd { const char *name; /* Name of option. */ u_int nargs; /* Number of arguments. */ int req; /* ORed CTL_REQ_xxx or -1. */ u_int cmd; /* Command code. */ int (*parse)(int argc, char *argv[]); /* Parser. */ int (*check)(void); /* Check returned result. */ }; static sigjmp_buf env_alrm; /* Used if -w option is used. */ #define PAT_TIME "^([[:digit:]]+[smh])+$" #define PAT_BYTES "^([[:digit:]]+[BKMGT])+$" #define SECONDS_IN_MINUTE (60) #define SECONDS_IN_HOUR (60 * SECONDS_IN_MINUTE) #define SECONDS_IN_DAY (24 * SECONDS_IN_HOUR) #define KBYTE (UINT64_C(1024)) #define MBYTE (UINT64_C(1024) * KBYTE) #define GBYTE (UINT64_C(1024) * MBYTE) #define TBYTE (UINT64_C(1024) * GBYTE) /* For reporting errors from regcomp(3) function. */ #define RE_ERRBUF_SIZ 100 static int re_errcode; static char re_errbuf[RE_ERRBUF_SIZ]; static void logmsg(const char *, ...) ATTR_FORMAT(printf, 1, 2); static void logmsgx(const char *, ...) ATTR_FORMAT(printf, 1, 2); static void vlogmsg(const char *, va_list) ATTR_FORMAT(printf, 1, 0); static void vlogmsgx(const char *, va_list) ATTR_FORMAT(printf, 1, 0); static void exit_errx(const char *, ...) ATTR_NORETURN ATTR_FORMAT(printf, 1, 2); static void vlogmsg(const char *format, va_list ap) { int errno_save = errno; fflush(stdout); fprintf(stderr, "%s: ", envprogname); vfprintf(stderr, format, ap); if (errno_save != 0) fprintf(stderr, ": %s", strerror(errno_save)); fprintf(stderr, "\n"); } static void vlogmsgx(const char *format, va_list ap) { fflush(stdout); fprintf(stderr, "%s: ", envprogname); vfprintf(stderr, format, ap); fprintf(stderr, "\n"); } /* * Output the program name, a message and an error message. */ static void logmsg(const char *format, ...) { va_list ap; va_start(ap, format); vlogmsg(format, ap); va_end(ap); } /* * Output the program name and a message. */ static void logmsgx(const char *format, ...) { va_list ap; va_start(ap, format); vlogmsgx(format, ap); va_end(ap); } /* * Output the program name, a message and exit. */ static void exit_errx(const char *format, ...) { va_list ap; va_start(ap, format); vlogmsgx(format, ap); va_end(ap); exit(1); } /* * Convert string to u_int. * Assume that sizeof(u_long) >= sizeof(u_int). */ static int strto_u_int(u_int *result, const char *nptr) { char *endptr; u_long val_ul; if (isdigit(*nptr) == 0) goto failed; errno = 0; val_ul = strtoul(nptr, &endptr, 10); if (errno != 0) { logmsg("strtoul"); return -1; } if (val_ul > UINT_MAX) { logmsgx("too big value for u_int"); return -1; } if (nptr == endptr) goto failed; *result = (u_int)val_ul; return 0; failed: logmsgx("wrong positive decimal number"); return -1; } /* * Output version number (-v and -h switches). */ static void show_version(void) { printf(IPACTL_NAME ", version " PACKAGE_VERSION "\nSupports: rules" #ifdef WITH_LIMITS ", limits" #endif #ifdef WITH_THRESHOLDS ", thresholds" #endif #ifdef CTL_CHECK_CREDS "; sending messages credentials is enabled" #else "; sending messages credentials is disabled" #endif ".\n"); } /* * Output the help message (-h switch). */ static void usage(void) { show_version(); printf("\ Usage: %s [-hnv] [-s ] [-w