Exemplo n.º 1
0
static int process_elements(struct conn *conn, uint8_t * rawmsg, int len,
			    struct sockaddr *from)
{
	struct cw_action_in as, *af, *afm;

	int offset = cw_get_hdr_msg_offset(rawmsg);

	uint8_t *msg_ptr = rawmsg + offset;

	int elems_len = cw_get_msg_elems_len(msg_ptr);

	int payloadlen = len - offset;


	/* pre-check message */
	if (payloadlen - 8 != elems_len) {

		if (conn->strict_hdr) {
			cw_dbg(DBG_MSG_ERR,
			       "Discarding message from %s, msgelems len=%d, payload len=%d, (Strict CAPWAP) ",
			       sock_addr2str(&conn->addr), elems_len, payloadlen - 8);
			errno = EAGAIN;
			return -1;
		}


		if (elems_len < payloadlen - 8) {
			cw_dbg(DBG_RFC,
			       "Packet from from %s has %d bytes of extra data, ignoring.",
			       sock_addr2str(&conn->addr), payloadlen - 8 - elems_len);
			elems_len = len - 8;
		}

		if (elems_len > payloadlen - 8) {

			cw_dbg(DBG_RFC,
			       "Packet from from %s has msgelems len of %d bytes, but has only %d bytes of data, truncating.",
			       sock_addr2str(&conn->addr), elems_len, payloadlen - 8);
			elems_len = payloadlen - 8;
		}
	}



	if (!conn->detected) {
		//struct mod_ac *mod;
		struct cw_actiondef *ad = load_mods(conn, rawmsg, len, elems_len, from);
		if (!ad) {
			cw_log(LOG_ERR, "Error");
			errno = EAGAIN;
			return -1;
		}
		conn->actions = ad;
		conn->detected = 1;

	}



	/* prepare struct for search operation */
	as.capwap_state = conn->capwap_state;
	as.msg_id = cw_get_msg_id(msg_ptr);
	as.vendor_id = 0;
	as.elem_id = 0;
	as.proto = 0;


	/* Search for state/message combination */
	afm = cw_actionlist_in_get(conn->actions->in, &as);

	if (!afm) {
		/* Throw away unexpected response messages */
		if (!(as.msg_id & 1)) {
			cw_dbg(DBG_MSG_ERR,
			       "Message type %d (%s) unexpected/illegal in %s State, discarding.",
			       as.msg_id, cw_strmsg(as.msg_id),
			       cw_strstate(conn->capwap_state));
			errno = EAGAIN;
			return -1;
		}

		/* Request message not found in current state, check if we know 
		   anything else about this message type */
		const char *str = cw_strheap_get(conn->actions->strmsg, as.msg_id);
		int result_code = 0;
		if (str) {
			/* Message found, but it was in wrong state */
			cw_dbg(DBG_MSG_ERR,
			       "Message type %d (%s) not allowed in %s State.", as.msg_id,
			       cw_strmsg(as.msg_id), cw_strstate(as.capwap_state));
			result_code = CW_RESULT_MSG_INVALID_IN_CURRENT_STATE;
		} else {
			/* Message is unknown */
			cw_dbg(DBG_MSG_ERR, "Message type %d (%s) unknown.",
			       as.msg_id, cw_strmsg(as.msg_id),
			       cw_strstate(as.capwap_state));
			result_code = CW_RESULT_MSG_UNRECOGNIZED;

		}
		cw_send_error_response(conn, rawmsg, result_code);
		errno = EAGAIN;
		return -1;
	}

	
	if (conn->msg_start){
		conn->msg_start(conn, afm, rawmsg, len, from);
	}

	/* Execute start processor for message */
	if (afm->start) {
		afm->start(conn, afm, rawmsg, len, from);
	}

	uint8_t *elems_ptr = cw_get_msg_elems_ptr(msg_ptr);
	uint8_t *elem;

	/* Create an avltree to catch the found mandatory elements */
	conn->mand = stravltree_create();

	int unrecognized = 0;

	/* iterate through message elements */
	cw_foreach_elem(elem, elems_ptr, elems_len) {

		as.elem_id = cw_get_elem_id(elem);
		int elem_len = cw_get_elem_len(elem);


		af = cw_actionlist_in_get(conn->actions->in, &as);

		if (!af) {
			unrecognized++;
			cw_dbg(DBG_ELEM_ERR,
			       "Element %d (%s) not allowed in msg of type %d (%s), ignoring.",
			       as.elem_id, cw_strelemp(conn->actions, as.elem_id),
			       as.msg_id, cw_strmsg(as.msg_id));
			continue;
		}

		if (!check_len(conn, af, cw_get_elem_data(elem), elem_len, from)) {
			continue;
		}
		cw_dbg_elem(DBG_ELEM, conn, as.msg_id, as.elem_id, cw_get_elem_data(elem),
			    elem_len);



		int afrc = 1;
		if (af->start) {
			afrc =
			    af->start(conn, af, cw_get_elem_data(elem), elem_len, from);

		}

		if (af->mand && afrc) {
			/* add found mandatory message element 
			   to mand list */
			stravltree_add(conn->mand, af->item_id);
		}

		if(conn->elem_end){
			afrc = conn->elem_end(conn,af,afrc,cw_get_elem_data(elem), elem_len,from);
		}

	}
Exemplo n.º 2
0
static int
parse_config_file(const char *path)
{
    int err;
    long int int_val;
    const char *string_val;
    int string_val_len;
    config_t config;
    config_setting_t *setting;
    memset(&g_config, 0, sizeof(struct config_s));
    err = 0;
    config_init(&config);
    fprintf(stderr, "read config: %s\n", path);
    if (config_read_file(&config,
                         path) == CONFIG_FALSE) {
        fprintf(stderr, "config_read_file(): %s - %d - %s\n", path, config_error_line(&config), config_error_text(&config));
        err = 1;
        goto error;
    }

    setting = config_lookup(&config, "server");
    if (setting != NULL) {
        if (!config_setting_lookup_int(setting,
                                       "listen_port",
                                       &int_val)) {
            fprintf(stderr, "ERROR ... no listen port in config file %s\n",
                    path);
            err = 1;
            goto error;
        }
        if (int_val > 65535) {
            fprintf(stderr, "ERROR ... port has to be smaller 65535\n");
            err = 1;
            goto error;
        }
        g_config.listen_port = (int)int_val;
        if (!config_setting_lookup_string(setting,
                                          "accept_ip",
                                          &string_val)) {
            fprintf(stderr, "ERROR ... no accept_ip in config file %s\n",
                    path);
            err = 1;
            goto error;
        }
        string_val_len = strlen(string_val);
        /* check if supplied argument is max of 16 */
        if (string_val_len > IP_V4_LEN - 1) {
            fprintf(stderr, "ERROR ... accept_ip too long\n");
            err = 1;
            goto error;
        }
        memset(g_config.accept_ip_v4, 0, IP_V4_LEN);
        memcpy(g_config.accept_ip_v4, string_val, string_val_len);
        if (!config_setting_lookup_int(setting,
                                       "read_package_size",
                                       &int_val)) {
            int_val = MAX_BUF_SIZE;
        }
        if (int_val > MAX_BUF_SIZE) {
            fprintf(stderr, "WARNING ... read_package_size given bigger than MAX_BUF_SIZE (%d)\n", MAX_BUF_SIZE);
            int_val = MAX_BUF_SIZE;
        } else if (int_val < 100) {
            fprintf(stderr, "WARNING ... read_package_size to small.\n");
            int_val = 100;
        }

        g_config.read_package_size = int_val;

        if (!config_setting_lookup_int(setting,
                                       "backlog",
                                       &int_val)) {
            int_val = 128;
        }

        g_config.backlog = int_val;

        if (!config_setting_lookup_string(setting,
                                          "base_path",
                                          &string_val)) {
            fprintf(stderr, "ERROR ... no base path specified\n");
            err = 1;
            goto error;
        }
        g_config.base_path = strdup(string_val);
    }


    fprintf(stderr, "listen_port: %d\n", g_config.listen_port);
    fprintf(stderr, "accept_ip: %s\n", g_config.accept_ip_v4);
    fprintf(stderr, "read_package_size: %d\n", g_config.read_package_size);
    fprintf(stderr, "backlog: %d\n", g_config.backlog);
    fprintf(stderr, "base_path: %s\n", g_config.base_path);

    err = load_mods(&config, setting);

error:
    config_destroy(&config);
    return err;
}