Example #1
0
/*
 * Partition an mbuf chain in two pieces, returning the tail --
 * all but the first len0 bytes.  In case of failure, it returns NULL and
 * attempts to restore the chain to its original state.
 */
struct mbuf *
m_split(struct mbuf *m0, int len0, int wait)
{
	struct mbuf *m, *n;
	unsigned len = len0, remain, olen;

	for (m = m0; m && len > m->m_len; m = m->m_next)
		len -= m->m_len;
	if (m == NULL)
		return (NULL);
	remain = m->m_len - len;
	if (m0->m_flags & M_PKTHDR) {
		MGETHDR(n, wait, m0->m_type);
		if (n == NULL)
			return (NULL);
		if (m_dup_pkthdr(n, m0, wait)) {
			m_freem(n);
			return (NULL);
		}
		n->m_pkthdr.len -= len0;
		olen = m0->m_pkthdr.len;
		m0->m_pkthdr.len = len0;
		if (m->m_flags & M_EXT)
			goto extpacket;
		if (remain > MHLEN) {
			/* m can't be the lead packet */
			MH_ALIGN(n, 0);
			n->m_next = m_split(m, len, wait);
			if (n->m_next == NULL) {
				(void) m_free(n);
				m0->m_pkthdr.len = olen;
				return (NULL);
			} else
				return (n);
		} else
			MH_ALIGN(n, remain);
	} else if (remain == 0) {
		n = m->m_next;
		m->m_next = NULL;
		return (n);
	} else {
		MGET(n, wait, m->m_type);
		if (n == NULL)
			return (NULL);
		M_ALIGN(n, remain);
	}
extpacket:
	if (m->m_flags & M_EXT) {
		n->m_ext = m->m_ext;
		MCLADDREFERENCE(m, n);
		n->m_data = m->m_data + len;
	} else {
		memcpy(mtod(n, caddr_t), mtod(m, caddr_t) + len, remain);
	}
	n->m_len = remain;
	m->m_len = len;
	n->m_next = m->m_next;
	m->m_next = NULL;
	return (n);
}
Example #2
0
static int		analyse(char *line, t_env *e, int i)
{
	char		**str_p;
	char		**str;
	int			nb;

	if (line)
	{
		str = m_split(line);
		str_p = ft_strsplit(line, ' ');
	}
	if (i == 0)
	{
		nb = ft_atoi(line);
		if (nb < 0)
			return (-1);
		e->worms = nb;
		return (1);
	}
	else if (line && ft_strcmp(line, "##start") == 0 && e->start == 0)
		return (e->start = 1);
	else if (line && ft_strcmp(line, "##end") == 0 && e->end == 0)
		return (e->end = 1);
	else if (line && line[0] == '#' && (ft_strcmp(line, "##start") != 0
			|| ft_strcmp(line, "##end") != 0))
		return (free_tab(&str, &str_p, 1));
	return (analyse2(line, str, str_p, e));
}
Example #3
0
errno_t
mbuf_split(mbuf_t src, size_t offset,
					mbuf_how_t how, mbuf_t *new_mbuf)
{
	/* Must set *new_mbuf to NULL in failure case */
	*new_mbuf = m_split(src, offset, how);

	return (*new_mbuf == NULL ? ENOMEM : 0);
}
Example #4
0
static int
smb_t2_placedata(struct mbuf *mtop, u_int16_t offset, u_int16_t count,
	struct mdchain *mdp)
{
	struct mbuf *m, *m0;
	int len;

	m0 = m_split(mtop, offset, M_WAIT);
	len = m_length(m0, &m);
	m->m_len -= len - count;
	if (mdp->md_top == NULL) {
		md_initm(mdp, m0);
	} else
		m_cat(mdp->md_top, m0);
	return 0;
}
Example #5
0
File: sk_rule.c Project: Safe3/silk
static int parse_key_value_pair(char* pair, char* key, char* value)
{
	if(pair == NULL || key == NULL || value == NULL)
		return -1;

	char** toks;
	int num_toks;
	int i;

	toks = m_split(pair, ":", PARSERULE_SIZE, &num_toks, 0);
	if(toks[0] == NULL || toks[1] == NULL)
	{
		m_split_free(&toks, num_toks);
		return -1;
	}
	else
	{
		char* p_start, *p_end;

		char tmp[2][PARSERULE_SIZE]={{0}, {0}};

		for(i=0; i<2; i++)
		{
			p_start = toks[i];
			p_end = toks[i]+strlen(toks[i])-1;

			if(*p_start=='"')
				p_start++;
			if(*p_end=='"')
				*p_end = 0x00;

			strcpy(tmp[i], p_start);
		}

		strcpy(key, tmp[0]);
		strcpy(value, tmp[1]);

		m_split_free(&toks, num_toks);
	}

	return 0;
}
Example #6
0
static int
smb_t2_placedata(struct mbuf *mtop, u_int16_t offset, u_int16_t count,
                 struct mdchain *mdp)
{
    struct mbuf *m, *m0;
    int len;

    m0 = m_split(mtop, offset, M_WAIT);
    if (m0 == NULL)
        return EBADRPC;
    for(len = 0, m = m0; m->m_next; m = m->m_next)
        len += m->m_len;
    len += m->m_len;
    m->m_len -= len - count;
    if (mdp->md_top == NULL) {
        md_initm(mdp, m0);
    } else
        m_cat(mdp->md_top, m0);
    return 0;
}
Example #7
0
static bool_t
svc_vc_recv(SVCXPRT *xprt, struct rpc_msg *msg,
    struct sockaddr **addrp, struct mbuf **mp)
{
	struct cf_conn *cd = (struct cf_conn *) xprt->xp_p1;
	struct uio uio;
	struct mbuf *m;
	XDR xdrs;
	int error, rcvflag;

	/*
	 * Serialise access to the socket and our own record parsing
	 * state.
	 */
	sx_xlock(&xprt->xp_lock);

	for (;;) {
		/*
		 * If we have an mbuf chain in cd->mpending, try to parse a
		 * record from it, leaving the result in cd->mreq. If we don't
		 * have a complete record, leave the partial result in
		 * cd->mreq and try to read more from the socket.
		 */
		if (cd->mpending) {
			/*
			 * If cd->resid is non-zero, we have part of the
			 * record already, otherwise we are expecting a record
			 * marker.
			 */
			if (!cd->resid) {
				/*
				 * See if there is enough data buffered to
				 * make up a record marker. Make sure we can
				 * handle the case where the record marker is
				 * split across more than one mbuf.
				 */
				size_t n = 0;
				uint32_t header;

				m = cd->mpending;
				while (n < sizeof(uint32_t) && m) {
					n += m->m_len;
					m = m->m_next;
				}
				if (n < sizeof(uint32_t))
					goto readmore;
				if (cd->mpending->m_len < sizeof(uint32_t))
					cd->mpending = m_pullup(cd->mpending,
					    sizeof(uint32_t));
				memcpy(&header, mtod(cd->mpending, uint32_t *),
				    sizeof(header));
				header = ntohl(header);
				cd->eor = (header & 0x80000000) != 0;
				cd->resid = header & 0x7fffffff;
				m_adj(cd->mpending, sizeof(uint32_t));
			}

			/*
			 * Start pulling off mbufs from cd->mpending
			 * until we either have a complete record or
			 * we run out of data. We use m_split to pull
			 * data - it will pull as much as possible and
			 * split the last mbuf if necessary.
			 */
			while (cd->mpending && cd->resid) {
				m = cd->mpending;
				if (cd->mpending->m_next
				    || cd->mpending->m_len > cd->resid)
					cd->mpending = m_split(cd->mpending,
					    cd->resid, M_WAIT);
				else
					cd->mpending = NULL;
				if (cd->mreq)
					m_last(cd->mreq)->m_next = m;
				else
					cd->mreq = m;
				while (m) {
					cd->resid -= m->m_len;
					m = m->m_next;
				}
			}

			/*
			 * If cd->resid is zero now, we have managed to
			 * receive a record fragment from the stream. Check
			 * for the end-of-record mark to see if we need more.
			 */
			if (cd->resid == 0) {
				if (!cd->eor)
					continue;

				/*
				 * Success - we have a complete record in
				 * cd->mreq.
				 */
				xdrmbuf_create(&xdrs, cd->mreq, XDR_DECODE);
				cd->mreq = NULL;
				sx_xunlock(&xprt->xp_lock);

				if (! xdr_callmsg(&xdrs, msg)) {
					XDR_DESTROY(&xdrs);
					return (FALSE);
				}

				*addrp = NULL;
				*mp = xdrmbuf_getall(&xdrs);
				XDR_DESTROY(&xdrs);

				return (TRUE);
			}
		}

	readmore:
		/*
		 * The socket upcall calls xprt_active() which will eventually
		 * cause the server to call us here. We attempt to
		 * read as much as possible from the socket and put
		 * the result in cd->mpending. If the read fails,
		 * we have drained both cd->mpending and the socket so
		 * we can call xprt_inactive().
		 */
		uio.uio_resid = 1000000000;
		uio.uio_td = curthread;
		m = NULL;
		rcvflag = MSG_DONTWAIT;
		CURVNET_SET(xprt->xp_socket->so_vnet);
		error = soreceive(xprt->xp_socket, NULL, &uio, &m, NULL,
		    &rcvflag);
		CURVNET_RESTORE();

		if (error == EWOULDBLOCK) {
			/*
			 * We must re-test for readability after
			 * taking the lock to protect us in the case
			 * where a new packet arrives on the socket
			 * after our call to soreceive fails with
			 * EWOULDBLOCK. The pool lock protects us from
			 * racing the upcall after our soreadable()
			 * call returns false.
			 */
			mtx_lock(&xprt->xp_pool->sp_lock);
			if (!soreadable(xprt->xp_socket))
				xprt_inactive_locked(xprt);
			mtx_unlock(&xprt->xp_pool->sp_lock);
			sx_xunlock(&xprt->xp_lock);
			return (FALSE);
		}

		if (error) {
			SOCKBUF_LOCK(&xprt->xp_socket->so_rcv);
			if (xprt->xp_upcallset) {
				xprt->xp_upcallset = 0;
				soupcall_clear(xprt->xp_socket, SO_RCV);
			}
			SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv);
			xprt_inactive(xprt);
			cd->strm_stat = XPRT_DIED;
			sx_xunlock(&xprt->xp_lock);
			return (FALSE);
		}

		if (!m) {
			/*
			 * EOF - the other end has closed the socket.
			 */
			xprt_inactive(xprt);
			cd->strm_stat = XPRT_DIED;
			sx_xunlock(&xprt->xp_lock);
			return (FALSE);
		}

		if (cd->mpending)
			m_last(cd->mpending)->m_next = m;
		else
			cd->mpending = m;
	}
Example #8
0
/*
 * Partition an mbuf chain in two pieces, returning the tail --
 * all but the first len0 bytes.  In case of failure, it returns NULL and
 * attempts to restore the chain to its original state.
 *
 * Note that the resulting mbufs might be read-only, because the new
 * mbuf can end up sharing an mbuf cluster with the original mbuf if
 * the "breaking point" happens to lie within a cluster mbuf. Use the
 * M_WRITABLE() macro to check for this case.
 */
struct mbuf *
m_split(struct mbuf *m0, int len0, int wait)
{
	struct mbuf *m, *n;
	u_int len = len0, remain;

	MBUF_CHECKSLEEP(wait);
	for (m = m0; m && len > m->m_len; m = m->m_next)
		len -= m->m_len;
	if (m == NULL)
		return (NULL);
	remain = m->m_len - len;
	if (m0->m_flags & M_PKTHDR && remain == 0) {
		n = m_gethdr(wait, m0->m_type);
		if (n == NULL)
			return (NULL);
		n->m_next = m->m_next;
		m->m_next = NULL;
		n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif;
		n->m_pkthdr.len = m0->m_pkthdr.len - len0;
		m0->m_pkthdr.len = len0;
		return (n);
	} else if (m0->m_flags & M_PKTHDR) {
		n = m_gethdr(wait, m0->m_type);
		if (n == NULL)
			return (NULL);
		n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif;
		n->m_pkthdr.len = m0->m_pkthdr.len - len0;
		m0->m_pkthdr.len = len0;
		if (m->m_flags & M_EXT)
			goto extpacket;
		if (remain > MHLEN) {
			/* m can't be the lead packet */
			M_ALIGN(n, 0);
			n->m_next = m_split(m, len, wait);
			if (n->m_next == NULL) {
				(void) m_free(n);
				return (NULL);
			} else {
				n->m_len = 0;
				return (n);
			}
		} else
			M_ALIGN(n, remain);
	} else if (remain == 0) {
		n = m->m_next;
		m->m_next = NULL;
		return (n);
	} else {
		n = m_get(wait, m->m_type);
		if (n == NULL)
			return (NULL);
		M_ALIGN(n, remain);
	}
extpacket:
	if (m->m_flags & M_EXT) {
		n->m_data = m->m_data + len;
		mb_dupcl(n, m);
	} else {
		bcopy(mtod(m, caddr_t) + len, mtod(n, caddr_t), remain);
	}
	n->m_len = remain;
	m->m_len = len;
	n->m_next = m->m_next;
	m->m_next = NULL;
	return (n);
}
Example #9
0
int
ng_l2cap_lp_send(ng_l2cap_con_p con, u_int16_t dcid, struct mbuf *m0)
{
	ng_l2cap_p		 l2cap = con->l2cap;
	ng_l2cap_hdr_t		*l2cap_hdr = NULL;
        ng_hci_acldata_pkt_t	*acl_hdr = NULL;
        struct mbuf		*m_last = NULL, *m = NULL;
        int			 len, flag = NG_HCI_PACKET_START;

	KASSERT((con->tx_pkt == NULL),
("%s: %s - another packet pending?!\n", __func__, NG_NODE_NAME(l2cap->node)));
	KASSERT((l2cap->pkt_size > 0),
("%s: %s - invalid l2cap->pkt_size?!\n", __func__, NG_NODE_NAME(l2cap->node)));

	/* Prepend mbuf with L2CAP header */
	m0 = ng_l2cap_prepend(m0, sizeof(*l2cap_hdr));
	if (m0 == NULL) {
		NG_L2CAP_ALERT(
"%s: %s - ng_l2cap_prepend(%zd) failed\n",
			__func__, NG_NODE_NAME(l2cap->node),
			sizeof(*l2cap_hdr));

		goto fail;
	}

	l2cap_hdr = mtod(m0, ng_l2cap_hdr_t *);
	l2cap_hdr->length = htole16(m0->m_pkthdr.len - sizeof(*l2cap_hdr));
	l2cap_hdr->dcid = htole16(dcid);

	/*
	 * Segment single L2CAP packet according to the HCI layer MTU. Convert 
	 * each segment into ACL data packet and prepend it with ACL data packet
	 * header. Link all segments together via m_nextpkt link. 
 	 *
	 * XXX BC (Broadcast flag) will always be 0 (zero).
	 */

	while (m0 != NULL) {
		/* Check length of the packet against HCI MTU */
		len = m0->m_pkthdr.len;
		if (len > l2cap->pkt_size) {
			m = m_split(m0, l2cap->pkt_size, M_DONTWAIT);
			if (m == NULL) {
				NG_L2CAP_ALERT(
"%s: %s - m_split(%d) failed\n",	__func__, NG_NODE_NAME(l2cap->node),
					l2cap->pkt_size);
				goto fail;
			}

			len = l2cap->pkt_size;
		}

		/* Convert packet fragment into ACL data packet */
		m0 = ng_l2cap_prepend(m0, sizeof(*acl_hdr));
		if (m0 == NULL) {
			NG_L2CAP_ALERT(
"%s: %s - ng_l2cap_prepend(%zd) failed\n",
				__func__, NG_NODE_NAME(l2cap->node),
				sizeof(*acl_hdr));
			goto fail;
		}

		acl_hdr = mtod(m0, ng_hci_acldata_pkt_t *);
		acl_hdr->type = NG_HCI_ACL_DATA_PKT;
		acl_hdr->length = htole16(len);
		acl_hdr->con_handle = htole16(NG_HCI_MK_CON_HANDLE(
					con->con_handle, flag, 0));

		/* Add fragment to the chain */
		m0->m_nextpkt = NULL;

		if (con->tx_pkt == NULL)
			con->tx_pkt = m_last = m0;
		else {
			m_last->m_nextpkt = m0;
			m_last = m0;
		}

		NG_L2CAP_INFO(
"%s: %s - attaching ACL packet, con_handle=%d, PB=%#x, length=%d\n",
			__func__, NG_NODE_NAME(l2cap->node), con->con_handle,
			flag, len);

		m0 = m;
		m = NULL;
		flag = NG_HCI_PACKET_FRAGMENT;
	}

	return (0);
fail:
	NG_FREE_M(m0);
	NG_FREE_M(m);

	while (con->tx_pkt != NULL) {
		m = con->tx_pkt->m_nextpkt;
		m_freem(con->tx_pkt);
		con->tx_pkt = m;
	}

	return (ENOBUFS);
} /* ng_l2cap_lp_send */
Example #10
0
/*
 * If we have an mbuf chain in cd->mpending, try to parse a record from it,
 * leaving the result in cd->mreq. If we don't have a complete record, leave
 * the partial result in cd->mreq and try to read more from the socket.
 */
static int
svc_vc_process_pending(SVCXPRT *xprt)
{
	struct cf_conn *cd = (struct cf_conn *) xprt->xp_p1;
	struct socket *so = xprt->xp_socket;
	struct mbuf *m;

	/*
	 * If cd->resid is non-zero, we have part of the
	 * record already, otherwise we are expecting a record
	 * marker.
	 */
	if (!cd->resid && cd->mpending) {
		/*
		 * See if there is enough data buffered to
		 * make up a record marker. Make sure we can
		 * handle the case where the record marker is
		 * split across more than one mbuf.
		 */
		size_t n = 0;
		uint32_t header;

		m = cd->mpending;
		while (n < sizeof(uint32_t) && m) {
			n += m->m_len;
			m = m->m_next;
		}
		if (n < sizeof(uint32_t)) {
			so->so_rcv.sb_lowat = sizeof(uint32_t) - n;
			return (FALSE);
		}
		m_copydata(cd->mpending, 0, sizeof(header),
		    (char *)&header);
		header = ntohl(header);
		cd->eor = (header & 0x80000000) != 0;
		cd->resid = header & 0x7fffffff;
		m_adj(cd->mpending, sizeof(uint32_t));
	}

	/*
	 * Start pulling off mbufs from cd->mpending
	 * until we either have a complete record or
	 * we run out of data. We use m_split to pull
	 * data - it will pull as much as possible and
	 * split the last mbuf if necessary.
	 */
	while (cd->mpending && cd->resid) {
		m = cd->mpending;
		if (cd->mpending->m_next
		    || cd->mpending->m_len > cd->resid)
			cd->mpending = m_split(cd->mpending,
			    cd->resid, M_WAITOK);
		else
			cd->mpending = NULL;
		if (cd->mreq)
			m_last(cd->mreq)->m_next = m;
		else
			cd->mreq = m;
		while (m) {
			cd->resid -= m->m_len;
			m = m->m_next;
		}
	}

	/*
	 * Block receive upcalls if we have more data pending,
	 * otherwise report our need.
	 */
	if (cd->mpending)
		so->so_rcv.sb_lowat = INT_MAX;
	else
		so->so_rcv.sb_lowat =
		    imax(1, imin(cd->resid, so->so_rcv.sb_hiwat / 2));
	return (TRUE);
}
Example #11
0
bool_t
xdr_rpc_gss_unwrap_data(struct mbuf **resultsp,
                        gss_ctx_id_t ctx, gss_qop_t qop,
                        rpc_gss_service_t svc, u_int seq)
{
    struct mbuf	*results, *message, *mic;
    uint32_t	len, cklen;
    OM_uint32	maj_stat, min_stat;
    u_int		seq_num, conf_state, qop_state;

    results = *resultsp;
    *resultsp = NULL;

    message = NULL;
    if (svc == rpc_gss_svc_integrity) {
        /*
         * Extract the seq+message part. Remember that there
         * may be extra RPC padding in the checksum. The
         * message part is RPC encoded already so no
         * padding.
         */
        len = get_uint32(&results);
        message = results;
        results = m_split(results, len, M_WAITOK);
        if (!results) {
            m_freem(message);
            return (FALSE);
        }

        /*
         * Extract the MIC and make it contiguous.
         */
        cklen = get_uint32(&results);
        if (!results) {
            m_freem(message);
            return (FALSE);
        }
        KASSERT(cklen <= MHLEN, ("unexpected large GSS-API checksum"));
        mic = results;
        if (cklen > mic->m_len) {
            mic = m_pullup(mic, cklen);
            if (!mic) {
                m_freem(message);
                return (FALSE);
            }
        }
        if (cklen != RNDUP(cklen))
            m_trim(mic, cklen);

        /* Verify checksum and QOP. */
        maj_stat = gss_verify_mic_mbuf(&min_stat, ctx,
                                       message, mic, &qop_state);
        m_freem(mic);

        if (maj_stat != GSS_S_COMPLETE || qop_state != qop) {
            m_freem(message);
            rpc_gss_log_status("gss_verify_mic", NULL,
                               maj_stat, min_stat);
            return (FALSE);
        }
    } else if (svc == rpc_gss_svc_privacy) {
        /* Decode databody_priv. */
        len = get_uint32(&results);
        if (!results)
            return (FALSE);

        /* Decrypt databody. */
        message = results;
        if (len != RNDUP(len))
            m_trim(message, len);
        maj_stat = gss_unwrap_mbuf(&min_stat, ctx, &message,
                                   &conf_state, &qop_state);

        /* Verify encryption and QOP. */
        if (maj_stat != GSS_S_COMPLETE) {
            rpc_gss_log_status("gss_unwrap", NULL,
                               maj_stat, min_stat);
            return (FALSE);
        }
        if (qop_state != qop || conf_state != TRUE) {
            m_freem(results);
            return (FALSE);
        }
    }

    /* Decode rpc_gss_data_t (sequence number + arguments). */
    seq_num = get_uint32(&message);
    if (!message)
        return (FALSE);

    /* Verify sequence number. */
    if (seq_num != seq) {
        rpc_gss_log_debug("wrong sequence number in databody");
        m_freem(message);
        return (FALSE);
    }

    *resultsp = message;
    return (TRUE);
}
Example #12
0
File: sk_rule.c Project: Safe3/silk
int parse_rule_content(char* rule)
{
	if(rule == NULL)
		return -1;

	char* index = rule;
	char** toks;
	int i;	// j;
	int num_toks;
//	int ruletype;
	int level;

	rule_node_t rule_node[10];	//每一行内容可能包含多个content
	int rule_num = 0;
	memset(&rule_node, 0, sizeof(rule_node_t)*10);

	while(*index == ' ' || *index =='\t')
		index++;
	for(i=0; i<strlen(index); i++)
	{
		if(*(index+i) == '\n')
		{
			*(index+i) = 0x00;
			break;
		}
	}

	toks = m_split(index, ";", PARSERULE_SIZE, &num_toks, 0);
	for(i=0; i<num_toks; i++)
	{
		char key[PARSERULE_SIZE]={0};
		char value[PARSERULE_SIZE]={0};
		char* idx;

		idx = toks[i];
		while(*idx == ' ' || *idx == '\t')
			idx++;
		if(*idx == '\n' || *idx == 0x00)	//是否是最后一个元素,即换行符
			break;

		if(parse_key_value_pair(idx, key, value) < 0)
		{
			save_err_log("profile %s, line:%d, this line is not in the expected format", file_name, file_line);
			exit(1);
		}

		if(!strcmp(key, "classtype"))
		{
			strcpy(rule_node[0].type, value);
		}
		else if(!strcmp(key, "level"))
		{
			level = rule_level(value);
			if(level < 0)
			{
				m_split_free(&toks, num_toks);
				return -1;
			}
			rule_node[0].level = level;
		}
		else if(!strcmp(key, "msg"))
		{
			strcpy(rule_node[0].msg, value);
		}
		else if(!strcmp(key, "content") || !strcmp(key, "uricontent"))
		{
			if(parse_pattern(value, rule_node[rule_num].content, &rule_node[rule_num].content_len)<0)
			{
				save_err_log("profile %s, line:%d, this line is not in the expected format", file_name, file_line);
				m_split_free(&toks, num_toks);
				return -1;
			}
			rule_num++;
		}
	}

	for(i=0; i<rule_num; i++)
	{
		rule_node[i].nocase = NOCASE;
		rule_node[i].id = rule_id++;
		strcpy(rule_node[i].file_name, file_name);
		rule_node[i].file_line = file_line;

		if(i != 0)
		{
			strcpy(rule_node[i].type, rule_node[0].type);
			rule_node[i].level = rule_node[0].level;
			strcpy(rule_node[i].msg, rule_node[0].msg);
		}
	}

	m_split_free(&toks, num_toks);

	if(rule_node[0].content_len > 0 && rule_num >= 1)
	{
		rule_node_t* cur_rule_node = &rule_node[0];
		if(rule_num == 1)
		{
			fpdetect_add_rule(cur_rule_node);
		}
		else
		{
			int j=1;
			for(j=1; j<rule_num; j++)
			{
				cur_rule_node = &rule_node[j];

				if(cur_rule_node->content_len > 0)
					fpdetect_add_rule(cur_rule_node);
			}
		}
	}
	return 0;
}