Пример #1
0
/*
 * Implements the <IfVersion> container
 */
static const char *start_ifversion(cmd_parms *cmd, void *mconfig,
                                   const char *arg1, const char *arg2,
                                   const char *arg3)
{
    const char *endp;
    int reverse = 0, done = 0, match = 0, compare;
    const char *p, *error;
    char c;

    /* supplying one argument is possible, we assume an equality check then */
    if (!arg2) {
        arg2 = arg1;
        arg1 = "=";
    }

    /* surrounding quotes without operator */
    if (!arg3 && *arg2 == '>' && !arg2[1]) {
        arg3 = ">";
        arg2 = arg1;
        arg1 = "=";
    }

    /* the third argument makes version surrounding quotes plus operator
     * possible.
     */
    endp = arg2 + strlen(arg2);
    if (   endp == arg2
        || (!(arg3 && *arg3 == '>' && !arg3[1]) && *--endp != '>')) {
        return apr_pstrcat(cmd->pool, cmd->cmd->name,
                           "> directive missing closing '>'", NULL);
    }

    p = arg1;
    if (*p == '!') {
        reverse = 1;
        if (p[1]) {
            ++p;
        }
    }

    c = *p++;
    if (!*p || (*p == '=' && !p[1] && c != '~')) {
        if (!httpd_version.major) {
            ap_get_server_revision(&httpd_version);
        }

        done = 1;
        switch (c) {
        case '=':
            /* normal comparison */
            if (*arg2 != '/') {
                compare = compare_version(apr_pstrmemdup(cmd->pool, arg2,
                                                         endp-arg2),
                                          &error);
                if (error) {
                    return error;
                }

                match = !compare;
                break;
            }

            /* regexp otherwise */
            if (endp == ++arg2 || *--endp != '/') {
                return "Missing delimiting / of regular expression.";
            }

        case '~':
            /* regular expression */
            match = match_version(cmd->pool, apr_pstrmemdup(cmd->pool, arg2,
                                                            endp-arg2),
                                  &error);
            if (error) {
                return error;
            }
            break;

        case '<':
            compare = compare_version(apr_pstrmemdup(cmd->pool, arg2,
                                                     endp-arg2),
                                      &error);
            if (error) {
                return error;
            }

            match = ((-1 == compare) || (*p && !compare));
            break;

        case '>':
            compare = compare_version(apr_pstrmemdup(cmd->pool, arg2,
                                                     endp-arg2),
                                      &error);
            if (error) {
                return error;
            }

            match = ((1 == compare) || (*p && !compare));
            break;

        default:
            done = 0;
            break;
        }
    }

    if (!done) {
        return apr_pstrcat(cmd->pool, "unrecognized operator '", arg1, "'",
                           NULL);
    }

    if ((!reverse && match) || (reverse && !match)) {
        ap_directive_t *parent = NULL;
        ap_directive_t *current = NULL;
        const char *retval;

        retval = ap_build_cont_config(cmd->pool, cmd->temp_pool, cmd,
                                      &current, &parent, "<IfVersion");
        *(ap_directive_t **)mconfig = current;
        return retval;
    }

    *(ap_directive_t **)mconfig = NULL;
    return ap_soak_end_container(cmd, "<IfVersion");
}
Пример #2
0
int main(int argc, char **argv)
{
	struct nl_sock *nsd;
	int family = NET_MAT_DFLT_FAMILY;
	struct sockaddr_nl dest_addr;
	unsigned char *buf;
	int rc = EXIT_SUCCESS;
	int err, opt;
	const char *backend = NULL;
	struct switch_args sw_args;
	struct sigaction sig_act;
	int verbose = 0;
	int opt_index = 0;
	static struct option long_options[] = {
		{ "version", no_argument, NULL, 0 },
		{ 0, 0, 0, 0}
	};

	memset(&sw_args, 0, sizeof(sw_args));

	while ((opt = getopt_long(argc, argv, "b:f:vhls", long_options,
	                          &opt_index)) != -1) {
		switch (opt) {
		case 0:
			if (!strcmp(long_options[opt_index].name, "version")) {
				printf("Match Version: %s\n", match_version());
				exit(0);
			}
			break;
		case 'b':
			backend = optarg;
			break;
		case 'f':
			family = atoi(optarg);
			break;
		case 'h':
			matchd_usage();
			exit(-1);
		case 'l':
			match_backend_list_all();
			exit(0);
		case 's':
			sw_args.single_vlan = true;
			break;
		case 'v':
			++verbose;
			break;
		default:
			matchd_usage();
			exit(-1);
		}
	}

	if (verbose > 1)
		mat_setlogmask(MAT_LOG_UPTO(MAT_LOG_DEBUG));
	else if (verbose > 0)
		mat_setlogmask(MAT_LOG_UPTO(MAT_LOG_INFO));
	else
		mat_setlogmask(MAT_LOG_UPTO(MAT_LOG_ERR));

	nsd = nl_socket_alloc();
	nl_socket_set_local_port(nsd, (uint32_t)getpid());
	nl_connect(nsd, NETLINK_GENERIC);

	if (backend == NULL)
		backend = DEFAULT_BACKEND_NAME;

	rc = matchd_init(nsd, family, backend, &sw_args);
	if (rc) {
		MAT_LOG(ERR, "Error: cannot init matchd\n");
		exit(-1);
	}

	err = matchd_create_pid();
	if (err) {
		MAT_LOG(ERR, "matchd create pid failed\n");
		exit(-1);
	}

	sig_act.sa_handler = matchd_int_handler;
	sigaction(SIGINT, &sig_act, NULL);
	sigaction(SIGTERM, &sig_act, NULL);

	while (1) {
		MAT_LOG(DEBUG, "Waiting for message\n");
		rc = nl_recv(nsd, &dest_addr, &buf, NULL);
		if(rc <= 0) {
			printf("%s:receive error on netlink socket:%d\n",
				__func__, errno);
			rc = EXIT_FAILURE;
			break;
		}
		/*printf("%s:recvfrom received %d bytes from pid %d\n",
			__func__, rc, dest_addr.nl_pid); */

		err = matchd_rx_process((struct nlmsghdr *)buf);
		if (err < 0)
			MAT_LOG(ERR, "%s: Warning: parsing error\n",
					__func__);

		free(buf);
	}
	
	matchd_uninit();

	nl_close(nsd);
	nl_socket_free(nsd);
	return rc;
}
Пример #3
0
/* Usage: <IfVersion [!]op version-string|regex> */
MODRET start_ifversion(cmd_rec *cmd) {
  unsigned int ifversion_ctx_count = 1;
  int compared, matched = FALSE, negated = FALSE;
  char buf[PR_TUNABLE_BUFFER_SIZE], *config_line = NULL;
  char *error = NULL, *version_str = NULL, *op_str = NULL;
  size_t op_len;

  if (cmd->argc-1 == 0 ||
      cmd->argc-1 > 2) {
    CONF_ERROR(cmd, "wrong number of parameters");
  }

  if (cmd->argc-1 == 2) {
    op_str = cmd->argv[1];

    if (*op_str == '!' &&
        strlen(op_str) > 1) {
      negated = TRUE;
      op_str++;
    }

    op_len = strlen(op_str);
    version_str = cmd->argv[2];

  } else {
    /* Assume that if only a version-string was supplied, the operator
     * is intended to be the equality operator.
     */
    op_str = "=";
    op_len = 1;
    version_str = cmd->argv[1];
  }

  switch (*op_str) {
    case '=':
      if (*version_str != '/') {
        /* Normal equality comparison */
        compared = compare_version(cmd->tmp_pool, version_str, &error);
        if (error != NULL) {
          CONF_ERROR(cmd, error);
        }

        matched = (compared == 0);
        break;
      }

      /* Otherwise, it's a regular expression */
      if (version_str[strlen(version_str)-1] != '/') {
        CONF_ERROR(cmd, "Missing terminating '/' of regular expression");
      }

      /* Fall through to the next case in order to handle/evaluate the
       * regular expression.  Be sure to remove the bracketing '/' characters
       * for the regex compilation.
       */
      version_str[strlen(version_str)-1] = '\0';
      version_str++;

    case '~': 
      /* Regular expression */
      matched = match_version(cmd->tmp_pool, version_str, &error);
      if (error != NULL) {
        CONF_ERROR(cmd, error);
      }

      break;

    case '<':
      compared = compare_version(cmd->tmp_pool, version_str, &error);
      if (error != NULL) {
        CONF_ERROR(cmd, error);
      }

      if (compared == -1 ||
          (op_len == 2 && compared == 0)) {
        matched = TRUE;
      }

      break;

    case '>':
      compared = compare_version(cmd->tmp_pool, version_str, &error);
      if (error != NULL) {
        CONF_ERROR(cmd, error);
      }

      if (compared == 1 ||
          (op_len == 2 && compared == 0)) {
        matched = TRUE;
      }

      break;

    default:
      CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "unknown comparison operator '",
        op_str, "'", NULL));
  } 

  if ((matched && !negated) ||
      (!matched && negated)) {
    pr_log_debug(DEBUG3, "%s: using '%s %s' section at line %u",
      cmd->argv[0], cmd->argv[1], cmd->argv[2], pr_parser_get_lineno());
      return PR_HANDLED(cmd);
  }

  pr_log_debug(DEBUG3, "%s: skipping '%s %s' section at line %u",
    cmd->argv[0], cmd->argv[1], cmd->argv[2], pr_parser_get_lineno());

  while (ifversion_ctx_count > 0 &&
         (config_line = pr_parser_read_line(buf, sizeof(buf))) != NULL) {
    pr_signals_handle();

    if (strncasecmp(config_line, "<IfVersion", 10) == 0) {
      ifversion_ctx_count++;
    }

    if (strcasecmp(config_line, "</IfVersion>") == 0) {
      ifversion_ctx_count--;
    }
  }

  /* If there are still unclosed <IfVersion> sections, signal an error.
   */
  if (ifversion_ctx_count > 0) {
    CONF_ERROR(cmd, "unclosed <IfVersion> section");
  }

  return PR_HANDLED(cmd);
}