Exemple #1
0
static int shutdown(struct socket *sock, int how)
{
	struct sock *sk = sock->sk;
	struct tipc_port *tport = tipc_sk_port(sk);
	struct sk_buff *buf;
	int res;

	if (how != SHUT_RDWR)
		return -EINVAL;

	lock_sock(sk);

	switch (sock->state) {
	case SS_CONNECTING:
	case SS_CONNECTED:

		/* Disconnect and send a 'FIN+' or 'FIN-' message to peer */
restart:
		buf = __skb_dequeue(&sk->sk_receive_queue);
		if (buf) {
			atomic_dec(&tipc_queue_size);
			if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf))) {
				buf_discard(buf);
				goto restart;
			}
			tipc_disconnect(tport->ref);
			tipc_reject_msg(buf, TIPC_CONN_SHUTDOWN);
		} else {
			tipc_shutdown(tport->ref);
		}

		sock->state = SS_DISCONNECTING;

		/* fall through */

	case SS_DISCONNECTING:

		/* Discard any unreceived messages; wake up sleeping tasks */

		discard_rx_queue(sk);
		if (waitqueue_active(sk_sleep(sk)))
			wake_up_interruptible(sk_sleep(sk));
		res = 0;
		break;

	default:
		res = -ENOTCONN;
	}

	release_sock(sk);
	return res;
}
static int release(struct socket *sock)
{
	struct tipc_sock *tsock = tipc_sk(sock->sk);
	struct sock *sk = sock->sk;
	int res = TIPC_OK;
	struct sk_buff *buf;

        dbg("sock_delete: %x\n",tsock);
	if (!tsock)
		return 0;
	down_interruptible(&tsock->sem);
	if (!sock->sk) {
		up(&tsock->sem);
		return 0;
	}
	
	/* Reject unreceived messages, unless no longer connected */

	while (sock->state != SS_DISCONNECTING) {
		sock_lock(tsock);
		buf = skb_dequeue(&sk->sk_receive_queue);
		if (!buf)
			tsock->p->usr_handle = 0;
		sock_unlock(tsock);
		if (!buf)
			break;
		if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf)))
			buf_discard(buf);
		else
			tipc_reject_msg(buf, TIPC_ERR_NO_PORT);
		atomic_dec(&tipc_queue_size);
	}

	/* Delete TIPC port */

	res = tipc_deleteport(tsock->p->ref);
	sock->sk = NULL;

	/* Discard any remaining messages */

	while ((buf = skb_dequeue(&sk->sk_receive_queue))) {
		buf_discard(buf);
		atomic_dec(&tipc_queue_size);
	}

	up(&tsock->sem);

	sock_put(sk);

        atomic_dec(&tipc_user_count);
	return res;
}
Exemple #3
0
static int anc_data_recv(struct msghdr *m, struct tipc_msg *msg,
				struct tipc_port *tport)
{
	u32 anc_data[3];
	u32 err;
	u32 dest_type;
	int has_name;
	int res;

	if (likely(m->msg_controllen == 0))
		return 0;

	/* Optionally capture errored message object(s) */

	err = msg ? msg_errcode(msg) : 0;
	if (unlikely(err)) {
		anc_data[0] = err;
		anc_data[1] = msg_data_sz(msg);
		res = put_cmsg(m, SOL_TIPC, TIPC_ERRINFO, 8, anc_data);
		if (res)
			return res;
		if (anc_data[1]) {
			res = put_cmsg(m, SOL_TIPC, TIPC_RETDATA, anc_data[1],
				       msg_data(msg));
			if (res)
				return res;
		}
	}

	/* Optionally capture message destination object */

	dest_type = msg ? msg_type(msg) : TIPC_DIRECT_MSG;
	switch (dest_type) {
	case TIPC_NAMED_MSG:
		has_name = 1;
		anc_data[0] = msg_nametype(msg);
		anc_data[1] = msg_namelower(msg);
		anc_data[2] = msg_namelower(msg);
		break;
	case TIPC_MCAST_MSG:
		has_name = 1;
		anc_data[0] = msg_nametype(msg);
		anc_data[1] = msg_namelower(msg);
		anc_data[2] = msg_nameupper(msg);
		break;
	case TIPC_CONN_MSG:
		has_name = (tport
Exemple #4
0
k8s_dispatcher::msg_data k8s_dispatcher::get_msg_data(const Json::Value& root)
{
	msg_data data;
	Json::Value evtype = root["type"];
	if(!evtype.isNull())
	{
		const std::string& et = evtype.asString();
		if(!et.empty())
		{
			if(et[0] == 'A') { data.m_reason = COMPONENT_ADDED;    }
			else if(et[0] == 'M') { data.m_reason = COMPONENT_MODIFIED; }
			else if(et[0] == 'D') { data.m_reason = COMPONENT_DELETED;  }
			else if(et[0] == 'E') { data.m_reason = COMPONENT_ERROR;    }
		}
		else
		{
			return msg_data();
		}
	}
	Json::Value object = root["object"];
	if(!object.isNull() && object.isObject())
	{
		Json::Value meta = object["metadata"];
		if(!meta.isNull() && meta.isObject())
		{
			Json::Value name = meta["name"];
			if(!name.isNull())
			{
				data.m_name = std::move(name.asString());
			}
			Json::Value uid = meta["uid"];
			if(!uid.isNull())
			{
				data.m_uid = std::move(uid.asString());
			}
			Json::Value nspace = meta["namespace"];
			if(!nspace.isNull())
			{
				data.m_namespace = std::move(nspace.asString());
			}
		}
	}
	return data;
}
Exemple #5
0
int
ACE_TMAIN (int, ACE_TCHAR *[])
{
  long pid = long (ACE_OS::getpid ());

  ACE_Typed_SV_Message_Queue<Message_Data> msgque (key_t (SRV_KEY));

  Message_Data msg_data (pid,
                         ACE_OS::cuserid (static_cast<char *> (0)),
                         "did you get this?");

  ACE_Typed_SV_Message<Message_Data> send_msg (msg_data,
					       SRV_ID,
					       msg_data.length ()),
					       recv_msg (pid);

  if (msgque.send (send_msg) < 0)
    ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
                       ACE_TEXT ("msgque.send")), 1);

  if (msgque.recv (recv_msg) < 0)
    ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
                       ACE_TEXT ("msgque.recv")), 1);

  Message_Data &recv_msg_data = recv_msg.data ();

  ACE_DEBUG ((LM_DEBUG,
              ACE_TEXT ("a message of length %d")
              ACE_TEXT (" received from server %d")
              ACE_TEXT (" (user %C): %C\n"),
              recv_msg_data.length (),
              recv_msg_data.pid (),
              recv_msg_data.user (),
              recv_msg_data.text ()));

  return 0;
}
Exemple #6
0
static int recv_msg(struct kiocb *iocb, struct socket *sock,
		    struct msghdr *m, size_t buf_len, int flags)
{
	struct tipc_sock *tsock = tipc_sk(sock->sk);
	struct sk_buff *buf;
	struct tipc_msg *msg;
	unsigned int q_len;
	unsigned int sz;
	u32 err;
	int res;

	/* Currently doesn't support receiving into multiple iovec entries */

	if (m->msg_iovlen != 1)
		return -EOPNOTSUPP;

	/* Catch invalid receive attempts */

	if (unlikely(!buf_len))
		return -EINVAL;

	if (sock->type == SOCK_SEQPACKET) {
		if (unlikely(sock->state == SS_UNCONNECTED))
			return -ENOTCONN;
		if (unlikely((sock->state == SS_DISCONNECTING) &&
			     (skb_queue_len(&sock->sk->sk_receive_queue) == 0)))
			return -ENOTCONN;
	}

	/* Look for a message in receive queue; wait if necessary */

	if (unlikely(down_interruptible(&tsock->sem)))
		return -ERESTARTSYS;

restart:
	if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) &&
		     (flags & MSG_DONTWAIT))) {
		res = -EWOULDBLOCK;
		goto exit;
	}

	if ((res = wait_event_interruptible(
		*sock->sk->sk_sleep,
		((q_len = skb_queue_len(&sock->sk->sk_receive_queue)) ||
		 (sock->state == SS_DISCONNECTING))) )) {
		goto exit;
	}

	/* Catch attempt to receive on an already terminated connection */
	/* [THIS CHECK MAY OVERLAP WITH AN EARLIER CHECK] */

	if (!q_len) {
		res = -ENOTCONN;
		goto exit;
	}

	/* Get access to first message in receive queue */

	buf = skb_peek(&sock->sk->sk_receive_queue);
	msg = buf_msg(buf);
	sz = msg_data_sz(msg);
	err = msg_errcode(msg);

	/* Complete connection setup for an implied connect */

	if (unlikely(sock->state == SS_CONNECTING)) {
		if ((res = auto_connect(sock, tsock, msg)))
			goto exit;
	}

	/* Discard an empty non-errored message & try again */

	if ((!sz) && (!err)) {
		advance_queue(tsock);
		goto restart;
	}

	/* Capture sender's address (optional) */

	set_orig_addr(m, msg);

	/* Capture ancillary data (optional) */

	if ((res = anc_data_recv(m, msg, tsock->p)))
		goto exit;

	/* Capture message data (if valid) & compute return value (always) */

	if (!err) {
		if (unlikely(buf_len < sz)) {
			sz = buf_len;
			m->msg_flags |= MSG_TRUNC;
		}
		if (unlikely(copy_to_user(m->msg_iov->iov_base, msg_data(msg),
					  sz))) {
			res = -EFAULT;
			goto exit;
		}
		res = sz;
	} else {
		if ((sock->state == SS_READY) ||
		    ((err == TIPC_CONN_SHUTDOWN) || m->msg_control))
			res = 0;
		else
			res = -ECONNRESET;
	}

	/* Consume received message (optional) */

	if (likely(!(flags & MSG_PEEK))) {
		if (unlikely(++tsock->p->conn_unacked >= TIPC_FLOW_CONTROL_WIN))
			tipc_acknowledge(tsock->p->ref, tsock->p->conn_unacked);
		advance_queue(tsock);
	}
exit:
	up(&tsock->sem);
	return res;
}
Exemple #7
0
static int shutdown(struct socket *sock, int how)
{
	struct tipc_sock* tsock = tipc_sk(sock->sk);
	struct sk_buff *buf;
	int res;

	/* Could return -EINVAL for an invalid "how", but why bother? */

	if (down_interruptible(&tsock->sem))
		return -ERESTARTSYS;

	sock_lock(tsock);

	switch (sock->state) {
	case SS_CONNECTED:

		/* Send 'FIN+' or 'FIN-' message to peer */

		sock_unlock(tsock);
restart:
		if ((buf = skb_dequeue(&sock->sk->sk_receive_queue))) {
			atomic_dec(&tipc_queue_size);
			if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf))) {
				buf_discard(buf);
				goto restart;
			}
			tipc_reject_msg(buf, TIPC_CONN_SHUTDOWN);
		}
		else {
			tipc_shutdown(tsock->p->ref);
		}
		sock_lock(tsock);

		/* fall through */

	case SS_DISCONNECTING:

		/* Discard any unreceived messages */

		while ((buf = skb_dequeue(&sock->sk->sk_receive_queue))) {
			atomic_dec(&tipc_queue_size);
			buf_discard(buf);
		}
		tsock->p->conn_unacked = 0;

		/* fall through */

	case SS_CONNECTING:
		sock->state = SS_DISCONNECTING;
		res = 0;
		break;

	default:
		res = -ENOTCONN;
	}

	sock_unlock(tsock);

	up(&tsock->sem);
	return res;
}
Exemple #8
0
static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf)
{
	struct tipc_msg *msg = buf_msg(buf);
	struct tipc_sock *tsock = (struct tipc_sock *)tport->usr_handle;
	struct socket *sock;
	u32 recv_q_len;

	/* Reject message if socket is closing */

	if (!tsock)
		return TIPC_ERR_NO_PORT;

	/* Reject message if it is wrong sort of message for socket */

	/*
	 * WOULD IT BE BETTER TO JUST DISCARD THESE MESSAGES INSTEAD?
	 * "NO PORT" ISN'T REALLY THE RIGHT ERROR CODE, AND THERE MAY
	 * BE SECURITY IMPLICATIONS INHERENT IN REJECTING INVALID TRAFFIC
	 */
	sock = tsock->sk.sk_socket;
	if (sock->state == SS_READY) {
		if (msg_connected(msg)) {
			msg_dbg(msg, "dispatch filter 1\n");
			return TIPC_ERR_NO_PORT;
		}
	} else {
		if (msg_mcast(msg)) {
			msg_dbg(msg, "dispatch filter 2\n");
			return TIPC_ERR_NO_PORT;
		}
		if (sock->state == SS_CONNECTED) {
			if (!msg_connected(msg)) {
				msg_dbg(msg, "dispatch filter 3\n");
				return TIPC_ERR_NO_PORT;
			}
		}
		else if (sock->state == SS_CONNECTING) {
			if (!msg_connected(msg) && (msg_errcode(msg) == 0)) {
				msg_dbg(msg, "dispatch filter 4\n");
				return TIPC_ERR_NO_PORT;
			}
		}
		else if (sock->state == SS_LISTENING) {
			if (msg_connected(msg) || msg_errcode(msg)) {
				msg_dbg(msg, "dispatch filter 5\n");
				return TIPC_ERR_NO_PORT;
			}
		}
		else if (sock->state == SS_DISCONNECTING) {
			msg_dbg(msg, "dispatch filter 6\n");
			return TIPC_ERR_NO_PORT;
		}
		else /* (sock->state == SS_UNCONNECTED) */ {
			if (msg_connected(msg) || msg_errcode(msg)) {
				msg_dbg(msg, "dispatch filter 7\n");
				return TIPC_ERR_NO_PORT;
			}
		}
	}

	/* Reject message if there isn't room to queue it */

	if (unlikely((u32)atomic_read(&tipc_queue_size) >
		     OVERLOAD_LIMIT_BASE)) {
		if (queue_overloaded(atomic_read(&tipc_queue_size),
				     OVERLOAD_LIMIT_BASE, msg))
			return TIPC_ERR_OVERLOAD;
	}
	recv_q_len = skb_queue_len(&tsock->sk.sk_receive_queue);
	if (unlikely(recv_q_len > (OVERLOAD_LIMIT_BASE / 2))) {
		if (queue_overloaded(recv_q_len,
				     OVERLOAD_LIMIT_BASE / 2, msg))
			return TIPC_ERR_OVERLOAD;
	}

	/* Initiate connection termination for an incoming 'FIN' */

	if (unlikely(msg_errcode(msg) && (sock->state == SS_CONNECTED))) {
		sock->state = SS_DISCONNECTING;
		/* Note: Use signal since port lock is already taken! */
		tipc_k_signal((Handler)async_disconnect, tport->ref);
	}

	/* Enqueue message (finally!) */

	msg_dbg(msg,"<DISP<: ");
	TIPC_SKB_CB(buf)->handle = msg_data(msg);
	atomic_inc(&tipc_queue_size);
	skb_queue_tail(&sock->sk->sk_receive_queue, buf);

	if (waitqueue_active(sock->sk->sk_sleep))
		wake_up_interruptible(sock->sk->sk_sleep);
	return TIPC_OK;
}
Exemple #9
0
static int recv_msg(struct kiocb *iocb, struct socket *sock,
		    struct msghdr *m, size_t buf_len, int flags)
{
	struct sock *sk = sock->sk;
	struct tipc_port *tport = tipc_sk_port(sk);
	struct sk_buff *buf;
	struct tipc_msg *msg;
	unsigned int sz;
	u32 err;
	int res;

	/* Catch invalid receive requests */

	if (m->msg_iovlen != 1)
		return -EOPNOTSUPP;   /* Don't do multiple iovec entries yet */

	if (unlikely(!buf_len))
		return -EINVAL;

	lock_sock(sk);

	if (unlikely(sock->state == SS_UNCONNECTED)) {
		res = -ENOTCONN;
		goto exit;
	}

restart:

	/* Look for a message in receive queue; wait if necessary */

	while (skb_queue_empty(&sk->sk_receive_queue)) {
		if (sock->state == SS_DISCONNECTING) {
			res = -ENOTCONN;
			goto exit;
		}
		if (flags & MSG_DONTWAIT) {
			res = -EWOULDBLOCK;
			goto exit;
		}
		release_sock(sk);
		res = wait_event_interruptible(*sk_sleep(sk),
			(!skb_queue_empty(&sk->sk_receive_queue) ||
			 (sock->state == SS_DISCONNECTING)));
		lock_sock(sk);
		if (res)
			goto exit;
	}

	/* Look at first message in receive queue */

	buf = skb_peek(&sk->sk_receive_queue);
	msg = buf_msg(buf);
	sz = msg_data_sz(msg);
	err = msg_errcode(msg);

	/* Complete connection setup for an implied connect */

	if (unlikely(sock->state == SS_CONNECTING)) {
		res = auto_connect(sock, msg);
		if (res)
			goto exit;
	}

	/* Discard an empty non-errored message & try again */

	if ((!sz) && (!err)) {
		advance_rx_queue(sk);
		goto restart;
	}

	/* Capture sender's address (optional) */

	set_orig_addr(m, msg);

	/* Capture ancillary data (optional) */

	res = anc_data_recv(m, msg, tport);
	if (res)
		goto exit;

	/* Capture message data (if valid) & compute return value (always) */

	if (!err) {
		if (unlikely(buf_len < sz)) {
			sz = buf_len;
			m->msg_flags |= MSG_TRUNC;
		}
		if (unlikely(copy_to_user(m->msg_iov->iov_base, msg_data(msg),
					  sz))) {
			res = -EFAULT;
			goto exit;
		}
		res = sz;
	} else {
		if ((sock->state == SS_READY) ||
		    ((err == TIPC_CONN_SHUTDOWN) || m->msg_control))
			res = 0;
		else
			res = -ECONNRESET;
	}

	/* Consume received message (optional) */

	if (likely(!(flags & MSG_PEEK))) {
		if ((sock->state != SS_READY) &&
		    (++tport->conn_unacked >= TIPC_FLOW_CONTROL_WIN))
			tipc_acknowledge(tport->ref, tport->conn_unacked);
		advance_rx_queue(sk);
	}
exit:
	release_sock(sk);
	return res;
}
Exemple #10
0
static int release(struct socket *sock)
{
	struct sock *sk = sock->sk;
	struct tipc_port *tport;
	struct sk_buff *buf;
	int res;

	/*
	 * Exit if socket isn't fully initialized (occurs when a failed accept()
	 * releases a pre-allocated child socket that was never used)
	 */

	if (sk == NULL)
		return 0;

	tport = tipc_sk_port(sk);
	lock_sock(sk);

	/*
	 * Reject all unreceived messages, except on an active connection
	 * (which disconnects locally & sends a 'FIN+' to peer)
	 */

	while (sock->state != SS_DISCONNECTING) {
		buf = __skb_dequeue(&sk->sk_receive_queue);
		if (buf == NULL)
			break;
		atomic_dec(&tipc_queue_size);
		if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf)))
			buf_discard(buf);
		else {
			if ((sock->state == SS_CONNECTING) ||
			    (sock->state == SS_CONNECTED)) {
				sock->state = SS_DISCONNECTING;
				tipc_disconnect(tport->ref);
			}
			tipc_reject_msg(buf, TIPC_ERR_NO_PORT);
		}
	}

	/*
	 * Delete TIPC port; this ensures no more messages are queued
	 * (also disconnects an active connection & sends a 'FIN-' to peer)
	 */

	res = tipc_deleteport(tport->ref);

	/* Discard any remaining (connection-based) messages in receive queue */

	discard_rx_queue(sk);

	/* Reject any messages that accumulated in backlog queue */

	sock->state = SS_DISCONNECTING;
	release_sock(sk);

	sock_put(sk);
	sock->sk = NULL;

	atomic_dec(&tipc_user_count);
	return res;
}
Exemple #11
0
static char *message_text(activealerts_t *alert, recip_t *recip)
{
    static strbuffer_t *buf = NULL;
    char *eoln, *bom, *p;
    char info[4096];

    MEMDEFINE(info);

    if (!buf) buf = newstrbuffer(0);
    else clearstrbuffer(buf);

    if (alert->state == A_NOTIFY) {
        sprintf(info, "%s:%s INFO\n", alert->hostname, alert->testname);
        addtobuffer(buf, info);
        addtobuffer(buf, alert->pagemessage);
        MEMUNDEFINE(info);
        return STRBUF(buf);
    }

    switch (recip->format) {
    case ALERTFORM_TEXT:
    case ALERTFORM_PLAIN:
        bom = msg_data(alert->pagemessage);
        eoln = strchr(bom, '\n');
        if (eoln) *eoln = '\0';

        /* If there's a "<-- flags:.... -->" then remove it from the message */
        if ((p = strstr(bom, "<!--")) != NULL) {
            /* Add the part of line 1 before the flags ... */
            *p = '\0';
            addtobuffer(buf, bom);
            *p = '<';

            /* And the part of line 1 after the flags ... */
            p = strstr(p, "-->");
            if (p) addtobuffer(buf, p+3);

            /* And if there is more than line 1, add it as well */
            if (eoln) {
                *eoln = '\n';
                addtobuffer(buf, eoln);
            }
        }
        else {
            if (eoln) *eoln = '\n';
            addtobuffer(buf, bom);
        }

        addtobuffer(buf, "\n");

        if (recip->format == ALERTFORM_TEXT) {
            sprintf(info, "See %s%s\n",
                    xgetenv("XYMONWEBHOST"),
                    hostsvcurl(alert->hostname, alert->testname, 0));
            addtobuffer(buf, info);
        }

        MEMUNDEFINE(info);
        return STRBUF(buf);

    case ALERTFORM_SMS:
        /*
         * Send a report containing a brief alert
         * and any lines that begin with a "&COLOR"
         */
        switch (alert->state) {
        case A_PAGING:
        case A_ACKED:
            sprintf(info, "%s:%s %s [%d]",
                    alert->hostname, alert->testname,
                    colorname(alert->color), alert->cookie);
            break;

        case A_RECOVERED:
            sprintf(info, "%s:%s RECOVERED",
                    alert->hostname, alert->testname);
            break;

        case A_DISABLED:
            sprintf(info, "%s:%s DISABLED",
                    alert->hostname, alert->testname);
            break;

        case A_NOTIFY:
            sprintf(info, "%s:%s NOTICE",
                    alert->hostname, alert->testname);
            break;

        case A_NORECIP:
        case A_DEAD:
            break;
        }

        addtobuffer(buf, info);
        bom = msg_data(alert->pagemessage);
        eoln = strchr(bom, '\n');
        if (eoln) {
            bom = eoln;
            while ((bom = strstr(bom, "\n&")) != NULL) {
                eoln = strchr(bom+1, '\n');
                if (eoln) *eoln = '\0';
                if ((strncmp(bom+1, "&red", 4) == 0) || (strncmp(bom+1, "&yellow", 7) == 0))
                    addtobuffer(buf, bom);
                if (eoln) *eoln = '\n';
                bom = (eoln ? eoln+1 : "");
            }
        }
        MEMUNDEFINE(info);
        return STRBUF(buf);

    case ALERTFORM_SCRIPT:
        sprintf(info, "%s:%s %s [%d]\n",
                alert->hostname, alert->testname, colorname(alert->color), alert->cookie);
        addtobuffer(buf, info);
        addtobuffer(buf, msg_data(alert->pagemessage));
        addtobuffer(buf, "\n");
        sprintf(info, "See %s%s\n",
                xgetenv("XYMONWEBHOST"),
                hostsvcurl(alert->hostname, alert->testname, 0));
        addtobuffer(buf, info);
        MEMUNDEFINE(info);
        return STRBUF(buf);

    case ALERTFORM_PAGER:
    case ALERTFORM_NONE:
        MEMUNDEFINE(info);
        return "";
    }

    MEMUNDEFINE(info);
    return alert->pagemessage;
}
Exemple #12
0
int main(int argc, char *argv[])
{
	time_t starttime = time(NULL);
	char *histdir = NULL;
	char *histlogdir = NULL;
	char *msg;
	int argi, seq;
	int save_allevents = 1;
	int save_hostevents = 1;
	int save_statusevents = 1;
	int save_histlogs = 1;
	FILE *alleventsfd = NULL;
	int running = 1;
	struct sigaction sa;
	char newcol2[3];
	char oldcol2[3];

	MEMDEFINE(newcol2);
	MEMDEFINE(oldcol2);

	/* Dont save the error buffer */
	save_errbuf = 0;

	if (xgetenv("BBALLHISTLOG")) save_allevents = (strcmp(xgetenv("BBALLHISTLOG"), "TRUE") == 0);
	if (xgetenv("BBHOSTHISTLOG")) save_hostevents = (strcmp(xgetenv("BBHOSTHISTLOG"), "TRUE") == 0);
	if (xgetenv("SAVESTATUSLOG")) save_histlogs = (strcmp(xgetenv("SAVESTATUSLOG"), "TRUE") == 0);

	for (argi = 1; (argi < argc); argi++) {
		if (argnmatch(argv[argi], "--histdir=")) {
			histdir = strchr(argv[argi], '=')+1;
		}
		else if (argnmatch(argv[argi], "--histlogdir=")) {
			histlogdir = strchr(argv[argi], '=')+1;
		}
		else if (argnmatch(argv[argi], "--debug")) {
			debug = 1;
		}
	}

	if (xgetenv("BBHIST") && (histdir == NULL)) {
		histdir = strdup(xgetenv("BBHIST"));
	}
	if (histdir == NULL) {
		errprintf("No history directory given, aborting\n");
		return 1;
	}

	if (save_histlogs && (histlogdir == NULL) && xgetenv("BBHISTLOGS")) {
		histlogdir = strdup(xgetenv("BBHISTLOGS"));
	}
	if (save_histlogs && (histlogdir == NULL)) {
		errprintf("No history-log directory given, aborting\n");
		return 1;
	}

	if (save_allevents) {
		char alleventsfn[PATH_MAX];

		MEMDEFINE(alleventsfn);

		sprintf(alleventsfn, "%s/allevents", histdir);
		alleventsfd = fopen(alleventsfn, "a");
		if (alleventsfd == NULL) {
			errprintf("Cannot open the all-events file '%s'\n", alleventsfn);
		}
		setvbuf(alleventsfd, (char *)NULL, _IOLBF, 0);

		MEMUNDEFINE(alleventsfn);
	}

	/* For picking up lost children */
	setup_signalhandler("hobbitd_history");
	memset(&sa, 0, sizeof(sa));
	sa.sa_handler = sig_handler;
	sigaction(SIGCHLD, &sa, NULL);
	signal(SIGPIPE, SIG_DFL);

	while (running) {
		char *metadata[20] = { NULL, };
		int metacount;
		char *p;
		char *statusdata = "";
		char *hostname, *hostnamecommas, *testname, *dismsg;
		time_t tstamp, lastchg, disabletime, clienttstamp;
		int tstamp_i, lastchg_i;
		int newcolor, oldcolor;
		int downtimeactive;
		struct tm tstamptm;
		int trend;
		int childstat;

		/* Pickup any finished child processes to avoid zombies */
		while (wait3(&childstat, WNOHANG, NULL) > 0) ;

		msg = get_hobbitd_message(C_STACHG, "hobbitd_history", &seq, NULL);
		if (msg == NULL) {
			running = 0;
			continue;
		}

		p = strchr(msg, '\n'); 
		if (p) {
			*p = '\0'; 
			statusdata = msg_data(p+1);
		}
		metacount = 0;
		memset(&metadata, 0, sizeof(metadata));
		p = gettok(msg, "|");
		while (p && (metacount < 20)) {
			metadata[metacount++] = p;
			p = gettok(NULL, "|");
		}

		if ((metacount > 9) && (strncmp(metadata[0], "@@stachg", 8) == 0)) {
			/* @@stachg#seq|timestamp|sender|origin|hostname|testname|expiretime|color|prevcolor|changetime|disabletime|disablemsg|downtimeactive|clienttstamp */
			sscanf(metadata[1], "%d.%*d", &tstamp_i); tstamp = tstamp_i;
			hostname = metadata[4];
			testname = metadata[5];
			newcolor = parse_color(metadata[7]);
			oldcolor = parse_color(metadata[8]);
			lastchg  = atoi(metadata[9]);
			disabletime = atoi(metadata[10]);
			dismsg   = metadata[11];
			downtimeactive = (atoi(metadata[12]) > 0);
			clienttstamp = atoi(metadata[13]);

			if (newcolor == -1) {
				errprintf("Bad message: newcolor is unknown '%s'\n", metadata[7]);
				continue;
			}

			p = hostnamecommas = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = ',';

			if (save_statusevents) {
				char statuslogfn[PATH_MAX];
				int logexists;
				FILE *statuslogfd;
				char oldcol[100];
				char timestamp[40];
				struct stat st;

				MEMDEFINE(statuslogfn);
				MEMDEFINE(oldcol);
				MEMDEFINE(timestamp);

				sprintf(statuslogfn, "%s/%s.%s", histdir, hostnamecommas, testname);
				stat(statuslogfn, &st);
				statuslogfd = fopen(statuslogfn, "r+");
				logexists = (statuslogfd != NULL);
				*oldcol = '\0';

				if (logexists) {
					/*
					 * There is a fair chance hobbitd has not been
					 * running all the time while this system was monitored.
					 * So get the time of the latest status change from the file,
					 * instead of relying on the "lastchange" value we get
					 * from hobbitd. This is also needed when migrating from 
					 * standard bbd to hobbitd.
					 */
					off_t pos = -1;
					char l[1024];
					int gotit;

					MEMDEFINE(l);

					fseeko(statuslogfd, 0, SEEK_END);
					if (ftello(statuslogfd) > 512) {
						/* Go back 512 from EOF, and skip to start of a line */
						fseeko(statuslogfd, -512, SEEK_END);
						gotit = (fgets(l, sizeof(l)-1, statuslogfd) == NULL);
					}
					else {
						/* Read from beginning of file */
						fseeko(statuslogfd, 0, SEEK_SET);
						gotit = 0;
					}


					while (!gotit) {
						off_t tmppos = ftello(statuslogfd);
						time_t dur;
						int dur_i;

						if (fgets(l, sizeof(l)-1, statuslogfd)) {
							/* Sun Oct 10 06:49:42 2004 red   1097383782 602 */

							if ((strlen(l) > 24) && 
							    (sscanf(l+24, " %s %d %d", oldcol, &lastchg_i, &dur_i) == 2) &&
							    (parse_color(oldcol) != -1)) {
								/* 
								 * Record the start location of the line
								 */
								pos = tmppos;
								lastchg = lastchg_i;
								dur = dur_i;
							}
						}
						else {
							gotit = 1;
						}
					}

					if (pos == -1) {
						/* 
						 * Couldnt find anything in the log.
						 * Take lastchg from the timestamp of the logfile,
						 * and just append the data.
						 */
						lastchg = st.st_mtime;
						fseeko(statuslogfd, 0, SEEK_END);
					}
					else {
						/*
						 * lastchg was updated above.
						 * Seek to where the last line starts.
						 */
						fseeko(statuslogfd, pos, SEEK_SET);
					}

					MEMUNDEFINE(l);
				}
				else {
					/*
					 * Logfile does not exist.
					 */
					lastchg = tstamp;
					statuslogfd = fopen(statuslogfn, "a");
					if (statuslogfd == NULL) {
						errprintf("Cannot open status historyfile '%s' : %s\n", 
							statuslogfn, strerror(errno));
					}
				}

				if (strcmp(oldcol, colorname(newcolor)) == 0) {
					/* We wont update history unless the color did change. */
					if ((time(NULL) - starttime) > 300) {
						errprintf("Will not update %s - color unchanged (%s)\n", 
							  statuslogfn, oldcol);
					}

					if (hostnamecommas) xfree(hostnamecommas);
					if (statuslogfd) fclose(statuslogfd);

					MEMUNDEFINE(statuslogfn);
					MEMUNDEFINE(oldcol);
					MEMUNDEFINE(timestamp);

					continue;
				}

				if (statuslogfd) {
					if (logexists) {
						struct tm oldtm;

						/* Re-print the old record, now with the final duration */
						memcpy(&oldtm, localtime(&lastchg), sizeof(oldtm));
						strftime(timestamp, sizeof(timestamp), "%a %b %e %H:%M:%S %Y", &oldtm);
						fprintf(statuslogfd, "%s %s %d %d\n", 
							timestamp, oldcol, (int)lastchg, (int)(tstamp - lastchg));
					}

					/* And the new record. */
					memcpy(&tstamptm, localtime(&tstamp), sizeof(tstamptm));
					strftime(timestamp, sizeof(timestamp), "%a %b %e %H:%M:%S %Y", &tstamptm);
					fprintf(statuslogfd, "%s %s %d", timestamp, colorname(newcolor), (int)tstamp);

					fclose(statuslogfd);
				}

				MEMUNDEFINE(statuslogfn);
				MEMUNDEFINE(oldcol);
				MEMUNDEFINE(timestamp);
			}

			if (save_histlogs) {
				char *hostdash;
				char fname[PATH_MAX];
				FILE *histlogfd;

				MEMDEFINE(fname);

				p = hostdash = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = '_';
				sprintf(fname, "%s/%s", histlogdir, hostdash);
				mkdir(fname, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
				p = fname + sprintf(fname, "%s/%s/%s", histlogdir, hostdash, testname);
				mkdir(fname, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
				p += sprintf(p, "/%s", histlogtime(tstamp));

				histlogfd = fopen(fname, "w");
				if (histlogfd) {
					/*
					 * When a host gets disabled or goes purple, the status
					 * message data is not changed - so it will include a
					 * wrong color as the first word of the message.
					 * Therefore we need to fixup this so it matches the
					 * newcolor value.
					 */
					int txtcolor = parse_color(statusdata);
					char *origstatus = statusdata;

					if (txtcolor != -1) {
						fprintf(histlogfd, "%s", colorname(newcolor));
						statusdata += strlen(colorname(txtcolor));
					}

					if (dismsg && *dismsg) nldecode(dismsg);
					if (disabletime > 0) {
						fprintf(histlogfd, " Disabled until %s\n%s\n\n", 
							ctime(&disabletime), (dismsg ? dismsg : ""));
						fprintf(histlogfd, "Status message when disabled follows:\n\n");
						statusdata = origstatus;
					}
					else if (dismsg && *dismsg) {
						fprintf(histlogfd, " Planned downtime: %s\n\n", dismsg);
						fprintf(histlogfd, "Original status message follows:\n\n");
						statusdata = origstatus;
					}

					fwrite(statusdata, strlen(statusdata), 1, histlogfd);
					fprintf(histlogfd, "Status unchanged in 0.00 minutes\n");
					fprintf(histlogfd, "Message received from %s\n", metadata[2]);
					if (clienttstamp) fprintf(histlogfd, "Client data ID %d\n", (int) clienttstamp);
					fclose(histlogfd);
				}
				else {
					errprintf("Cannot create histlog file '%s' : %s\n", fname, strerror(errno));
				}
				xfree(hostdash);

				MEMUNDEFINE(fname);
			}

			strncpy(oldcol2, ((oldcolor >= 0) ? colorname(oldcolor) : "-"), 2);
			strncpy(newcol2, colorname(newcolor), 2);
			newcol2[2] = oldcol2[2] = '\0';

			if (oldcolor == -1)           trend = -1;	/* we dont know how bad it was */
			else if (newcolor > oldcolor) trend = 2;	/* It's getting worse */
			else if (newcolor < oldcolor) trend = 1;	/* It's getting better */
			else                          trend = 0;	/* Shouldn't happen ... */

			if (save_hostevents) {
				char hostlogfn[PATH_MAX];
				FILE *hostlogfd;

				MEMDEFINE(hostlogfn);

				sprintf(hostlogfn, "%s/%s", histdir, hostname);
				hostlogfd = fopen(hostlogfn, "a");
				if (hostlogfd) {
					fprintf(hostlogfd, "%s %d %d %d %s %s %d\n",
						testname, (int)tstamp, (int)lastchg, (int)(tstamp - lastchg),
						newcol2, oldcol2, trend);
					fclose(hostlogfd);
				}
				else {
					errprintf("Cannot open host logfile '%s' : %s\n", hostlogfn, strerror(errno));
				}

				MEMUNDEFINE(hostlogfn);
			}

			if (save_allevents) {
				fprintf(alleventsfd, "%s %s %d %d %d %s %s %d\n",
					hostname, testname, (int)tstamp, (int)lastchg, (int)(tstamp - lastchg),
					newcol2, oldcol2, trend);
				fflush(alleventsfd);
			}

			xfree(hostnamecommas);
		}
		else if ((metacount > 3) && ((strncmp(metadata[0], "@@drophost", 10) == 0))) {
			/* @@drophost|timestamp|sender|hostname */

			hostname = metadata[3];

			if (save_histlogs) {
				char *hostdash;
				char testdir[PATH_MAX];

				MEMDEFINE(testdir);

				/* Remove all directories below the host-specific histlog dir */
				p = hostdash = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = '_';
				sprintf(testdir, "%s/%s", histlogdir, hostdash);
				dropdirectory(testdir, 1);
				xfree(hostdash);

				MEMUNDEFINE(testdir);
			}

			if (save_hostevents) {
				char hostlogfn[PATH_MAX];
				struct stat st;

				MEMDEFINE(hostlogfn);

				sprintf(hostlogfn, "%s/%s", histdir, hostname);
				if ((stat(hostlogfn, &st) == 0) && S_ISREG(st.st_mode)) {
					unlink(hostlogfn);
				}

				MEMUNDEFINE(hostlogfn);
			}

			if (save_statusevents) {
				DIR *dirfd;
				struct dirent *de;
				char *hostlead;
				char statuslogfn[PATH_MAX];
				struct stat st;

				MEMDEFINE(statuslogfn);

				/* Remove bbvar/hist/host,name.* */
				p = hostnamecommas = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = ',';
				hostlead = malloc(strlen(hostname) + 2);
				strcpy(hostlead, hostnamecommas); strcat(hostlead, ".");

				dirfd = opendir(histdir);
				if (dirfd) {
					while ((de = readdir(dirfd)) != NULL) {
						if (strncmp(de->d_name, hostlead, strlen(hostlead)) == 0) {
							sprintf(statuslogfn, "%s/%s", histdir, de->d_name);
							if ((stat(statuslogfn, &st) == 0) && S_ISREG(st.st_mode)) {
								unlink(statuslogfn);
							}
						}
					}
					closedir(dirfd);
				}

				xfree(hostlead);
				xfree(hostnamecommas);

				MEMUNDEFINE(statuslogfn);
			}
		}
		else if ((metacount > 4) && ((strncmp(metadata[0], "@@droptest", 10) == 0))) {
			/* @@droptest|timestamp|sender|hostname|testname */

			hostname = metadata[3];
			testname = metadata[4];

			if (save_histlogs) {
				char *hostdash;
				char testdir[PATH_MAX];

				MEMDEFINE(testdir);

				p = hostdash = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = '_';
				sprintf(testdir, "%s/%s/%s", histlogdir, hostdash, testname);
				dropdirectory(testdir, 1);
				xfree(hostdash);

				MEMUNDEFINE(testdir);
			}

			if (save_statusevents) {
				char *hostnamecommas;
				char statuslogfn[PATH_MAX];
				struct stat st;

				MEMDEFINE(statuslogfn);

				p = hostnamecommas = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = ',';
				sprintf(statuslogfn, "%s/%s.%s", histdir, hostnamecommas, testname);
				if ((stat(statuslogfn, &st) == 0) && S_ISREG(st.st_mode)) unlink(statuslogfn);
				xfree(hostnamecommas);

				MEMUNDEFINE(statuslogfn);
			}
		}
		else if ((metacount > 4) && ((strncmp(metadata[0], "@@renamehost", 12) == 0))) {
			/* @@renamehost|timestamp|sender|hostname|newhostname */
			char *newhostname;

			hostname = metadata[3];
			newhostname = metadata[4];

			if (save_histlogs) {
				char *hostdash;
				char *newhostdash;
				char olddir[PATH_MAX];
				char newdir[PATH_MAX];

				MEMDEFINE(olddir); MEMDEFINE(newdir);

				p = hostdash = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = '_';
				p = newhostdash = strdup(newhostname); while ((p = strchr(p, '.')) != NULL) *p = '_';
				sprintf(olddir, "%s/%s", histlogdir, hostdash);
				sprintf(newdir, "%s/%s", histlogdir, newhostdash);
				rename(olddir, newdir);
				xfree(newhostdash);
				xfree(hostdash);

				MEMUNDEFINE(newdir); MEMUNDEFINE(olddir);
			}

			if (save_hostevents) {
				char hostlogfn[PATH_MAX];
				char newhostlogfn[PATH_MAX];

				MEMDEFINE(hostlogfn); MEMDEFINE(newhostlogfn);

				sprintf(hostlogfn, "%s/%s", histdir, hostname);
				sprintf(newhostlogfn, "%s/%s", histdir, newhostname);
				rename(hostlogfn, newhostlogfn);

				MEMUNDEFINE(hostlogfn); MEMUNDEFINE(newhostlogfn);
			}

			if (save_statusevents) {
				DIR *dirfd;
				struct dirent *de;
				char *hostlead;
				char *newhostnamecommas;
				char statuslogfn[PATH_MAX];
				char newlogfn[PATH_MAX];

				MEMDEFINE(statuslogfn); MEMDEFINE(newlogfn);

				p = hostnamecommas = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = ',';
				hostlead = malloc(strlen(hostname) + 2);
				strcpy(hostlead, hostnamecommas); strcat(hostlead, ".");

				p = newhostnamecommas = strdup(newhostname); while ((p = strchr(p, '.')) != NULL) *p = ',';


				dirfd = opendir(histdir);
				if (dirfd) {
					while ((de = readdir(dirfd)) != NULL) {
						if (strncmp(de->d_name, hostlead, strlen(hostlead)) == 0) {
							char *testname = strchr(de->d_name, '.');
							sprintf(statuslogfn, "%s/%s", histdir, de->d_name);
							sprintf(newlogfn, "%s/%s%s", histdir, newhostnamecommas, testname);
							rename(statuslogfn, newlogfn);
						}
					}
					closedir(dirfd);
				}

				xfree(newhostnamecommas);
				xfree(hostlead);
				xfree(hostnamecommas);

				MEMUNDEFINE(statuslogfn); MEMUNDEFINE(newlogfn);
			}
		}
		else if ((metacount > 5) && (strncmp(metadata[0], "@@renametest", 12) == 0)) {
			/* @@renametest|timestamp|sender|hostname|oldtestname|newtestname */
			char *newtestname;

			hostname = metadata[3];
			testname = metadata[4];
			newtestname = metadata[5];

			if (save_histlogs) {
				char *hostdash;
				char olddir[PATH_MAX];
				char newdir[PATH_MAX];

				MEMDEFINE(olddir); MEMDEFINE(newdir);

				p = hostdash = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = '_';
				sprintf(olddir, "%s/%s/%s", histlogdir, hostdash, testname);
				sprintf(newdir, "%s/%s/%s", histlogdir, hostdash, newtestname);
				rename(olddir, newdir);
				xfree(hostdash);

				MEMUNDEFINE(newdir); MEMUNDEFINE(olddir);
			}

			if (save_statusevents) {
				char *hostnamecommas;
				char statuslogfn[PATH_MAX];
				char newstatuslogfn[PATH_MAX];

				MEMDEFINE(statuslogfn); MEMDEFINE(newstatuslogfn);

				p = hostnamecommas = strdup(hostname); while ((p = strchr(p, '.')) != NULL) *p = ',';
				sprintf(statuslogfn, "%s/%s.%s", histdir, hostnamecommas, testname);
				sprintf(newstatuslogfn, "%s/%s.%s", histdir, hostnamecommas, newtestname);
				rename(statuslogfn, newstatuslogfn);
				xfree(hostnamecommas);

				MEMUNDEFINE(newstatuslogfn); MEMUNDEFINE(statuslogfn);
			}
		}
		else if (strncmp(metadata[0], "@@shutdown", 10) == 0) {
			running = 0;
		}
		else if (strncmp(metadata[0], "@@logrotate", 11) == 0) {
			char *fn = xgetenv("HOBBITCHANNEL_LOGFILENAME");
			if (fn && strlen(fn)) {
				freopen(fn, "a", stdout);
				freopen(fn, "a", stderr);
			}
			continue;
		}
	}

	MEMUNDEFINE(newcol2);
	MEMUNDEFINE(oldcol2);

	fclose(alleventsfd);
	return 0;
}
Exemple #13
0
static int ioc_send(ENGINE * server, int size)
{
    ENGINE_USER * usr = (ENGINE_USER *)server->usr;
    msg_data(usr, server->receive_buffer, size);
    return 0;
}
Exemple #14
0
void tipc_msg_print(struct print_buf *buf, struct tipc_msg *msg, const char *str)
{
	u32 usr = msg_user(msg);
	tipc_printf(buf, str);

	switch (usr) {
	case MSG_BUNDLER:
		tipc_printf(buf, "BNDL::");
		tipc_printf(buf, "MSGS(%u):", msg_msgcnt(msg));
		break;
	case BCAST_PROTOCOL:
		tipc_printf(buf, "BCASTP::");
		break;
	case MSG_FRAGMENTER:
		tipc_printf(buf, "FRAGM::");
		switch (msg_type(msg)) {
		case FIRST_FRAGMENT:
			tipc_printf(buf, "FIRST:");
			break;
		case FRAGMENT:
			tipc_printf(buf, "BODY:");
			break;
		case LAST_FRAGMENT:
			tipc_printf(buf, "LAST:");
			break;
		default:
			tipc_printf(buf, "UNKNOWN:%x",msg_type(msg));

		}
		tipc_printf(buf, "NO(%u/%u):",msg_long_msgno(msg),
			    msg_fragm_no(msg));
		break;
	case TIPC_LOW_IMPORTANCE:
	case TIPC_MEDIUM_IMPORTANCE:
	case TIPC_HIGH_IMPORTANCE:
	case TIPC_CRITICAL_IMPORTANCE:
		tipc_printf(buf, "DAT%u:", msg_user(msg));
		if (msg_short(msg)) {
			tipc_printf(buf, "CON:");
			break;
		}
		switch (msg_type(msg)) {
		case TIPC_CONN_MSG:
			tipc_printf(buf, "CON:");
			break;
		case TIPC_MCAST_MSG:
			tipc_printf(buf, "MCST:");
			break;
		case TIPC_NAMED_MSG:
			tipc_printf(buf, "NAM:");
			break;
		case TIPC_DIRECT_MSG:
			tipc_printf(buf, "DIR:");
			break;
		default:
			tipc_printf(buf, "UNKNOWN TYPE %u",msg_type(msg));
		}
		if (msg_routed(msg) && !msg_non_seq(msg))
			tipc_printf(buf, "ROUT:");
		if (msg_reroute_cnt(msg))
			tipc_printf(buf, "REROUTED(%u):",
				    msg_reroute_cnt(msg));
		break;
	case NAME_DISTRIBUTOR:
		tipc_printf(buf, "NMD::");
		switch (msg_type(msg)) {
		case PUBLICATION:
			tipc_printf(buf, "PUBL(%u):", (msg_size(msg) - msg_hdr_sz(msg)) / 20);	/* Items */
			break;
		case WITHDRAWAL:
			tipc_printf(buf, "WDRW:");
			break;
		default:
			tipc_printf(buf, "UNKNOWN:%x",msg_type(msg));
		}
		if (msg_routed(msg))
			tipc_printf(buf, "ROUT:");
		if (msg_reroute_cnt(msg))
			tipc_printf(buf, "REROUTED(%u):",
				    msg_reroute_cnt(msg));
		break;
	case CONN_MANAGER:
		tipc_printf(buf, "CONN_MNG:");
		switch (msg_type(msg)) {
		case CONN_PROBE:
			tipc_printf(buf, "PROBE:");
			break;
		case CONN_PROBE_REPLY:
			tipc_printf(buf, "PROBE_REPLY:");
			break;
		case CONN_ACK:
			tipc_printf(buf, "CONN_ACK:");
			tipc_printf(buf, "ACK(%u):",msg_msgcnt(msg));
			break;
		default:
			tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg));
		}
		if (msg_routed(msg))
			tipc_printf(buf, "ROUT:");
		if (msg_reroute_cnt(msg))
			tipc_printf(buf, "REROUTED(%u):",msg_reroute_cnt(msg));
		break;
	case LINK_PROTOCOL:
		tipc_printf(buf, "PROT:TIM(%u):",msg_timestamp(msg));
		switch (msg_type(msg)) {
		case STATE_MSG:
			tipc_printf(buf, "STATE:");
			tipc_printf(buf, "%s:",msg_probe(msg) ? "PRB" :"");
			tipc_printf(buf, "NXS(%u):",msg_next_sent(msg));
			tipc_printf(buf, "GAP(%u):",msg_seq_gap(msg));
			tipc_printf(buf, "LSTBC(%u):",msg_last_bcast(msg));
			break;
		case RESET_MSG:
			tipc_printf(buf, "RESET:");
			if (msg_size(msg) != msg_hdr_sz(msg))
				tipc_printf(buf, "BEAR:%s:",msg_data(msg));
			break;
		case ACTIVATE_MSG:
			tipc_printf(buf, "ACTIVATE:");
			break;
		default:
			tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg));
		}
		tipc_printf(buf, "PLANE(%c):",msg_net_plane(msg));
		tipc_printf(buf, "SESS(%u):",msg_session(msg));
		break;
	case CHANGEOVER_PROTOCOL:
		tipc_printf(buf, "TUNL:");
		switch (msg_type(msg)) {
		case DUPLICATE_MSG:
			tipc_printf(buf, "DUPL:");
			break;
		case ORIGINAL_MSG:
			tipc_printf(buf, "ORIG:");
			tipc_printf(buf, "EXP(%u)",msg_msgcnt(msg));
			break;
		default:
			tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg));
		}
		break;
	case ROUTE_DISTRIBUTOR:
		tipc_printf(buf, "ROUTING_MNG:");
		switch (msg_type(msg)) {
		case EXT_ROUTING_TABLE:
			tipc_printf(buf, "EXT_TBL:");
			tipc_printf(buf, "TO:%x:",msg_remote_node(msg));
			break;
		case LOCAL_ROUTING_TABLE:
			tipc_printf(buf, "LOCAL_TBL:");
			tipc_printf(buf, "TO:%x:",msg_remote_node(msg));
			break;
		case SLAVE_ROUTING_TABLE:
			tipc_printf(buf, "DP_TBL:");
			tipc_printf(buf, "TO:%x:",msg_remote_node(msg));
			break;
		case ROUTE_ADDITION:
			tipc_printf(buf, "ADD:");
			tipc_printf(buf, "TO:%x:",msg_remote_node(msg));
			break;
		case ROUTE_REMOVAL:
			tipc_printf(buf, "REMOVE:");
			tipc_printf(buf, "TO:%x:",msg_remote_node(msg));
			break;
		default:
			tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg));
		}
		break;
	case LINK_CONFIG:
		tipc_printf(buf, "CFG:");
		switch (msg_type(msg)) {
		case DSC_REQ_MSG:
			tipc_printf(buf, "DSC_REQ:");
			break;
		case DSC_RESP_MSG:
			tipc_printf(buf, "DSC_RESP:");
			break;
		default:
			tipc_printf(buf, "UNKNOWN TYPE:%x:",msg_type(msg));
			break;
		}
		break;
	default:
		tipc_printf(buf, "UNKNOWN USER:"******"NO_NAME:");
			break;
		case TIPC_ERR_NO_PORT:
			tipc_printf(buf, "NO_PORT:");
			break;
		case TIPC_ERR_NO_NODE:
			tipc_printf(buf, "NO_PROC:");
			break;
		case TIPC_ERR_OVERLOAD:
			tipc_printf(buf, "OVERLOAD:");
			break;
		case TIPC_CONN_SHUTDOWN:
			tipc_printf(buf, "SHUTDOWN:");
			break;
		default:
			tipc_printf(buf, "UNKNOWN ERROR(%x):",
				    msg_errcode(msg));
		}
	default:{}
	}

	tipc_printf(buf, "HZ(%u):", msg_hdr_sz(msg));
	tipc_printf(buf, "SZ(%u):", msg_size(msg));
	tipc_printf(buf, "SQNO(%u):", msg_seqno(msg));

	if (msg_non_seq(msg))
		tipc_printf(buf, "NOSEQ:");
	else {
		tipc_printf(buf, "ACK(%u):", msg_ack(msg));
	}
	tipc_printf(buf, "BACK(%u):", msg_bcast_ack(msg));
	tipc_printf(buf, "PRND(%x)", msg_prevnode(msg));

	if (msg_isdata(msg)) {
		if (msg_named(msg)) {
			tipc_printf(buf, "NTYP(%u):", msg_nametype(msg));
			tipc_printf(buf, "NINST(%u)", msg_nameinst(msg));
		}
	}

	if ((usr != LINK_PROTOCOL) && (usr != LINK_CONFIG) &&
	    (usr != MSG_BUNDLER)) {
		if (!msg_short(msg)) {
			tipc_printf(buf, ":ORIG(%x:%u):",
				    msg_orignode(msg), msg_origport(msg));
			tipc_printf(buf, ":DEST(%x:%u):",
				    msg_destnode(msg), msg_destport(msg));
		} else {
			tipc_printf(buf, ":OPRT(%u):", msg_origport(msg));
			tipc_printf(buf, ":DPRT(%u):", msg_destport(msg));
		}
		if (msg_routed(msg) && !msg_non_seq(msg))
			tipc_printf(buf, ":TSEQN(%u)", msg_transp_seqno(msg));
	}
	if (msg_user(msg) == NAME_DISTRIBUTOR) {
		tipc_printf(buf, ":ONOD(%x):", msg_orignode(msg));
		tipc_printf(buf, ":DNOD(%x):", msg_destnode(msg));
		if (msg_routed(msg)) {
			tipc_printf(buf, ":CSEQN(%u)", msg_transp_seqno(msg));
		}
	}

	if (msg_user(msg) ==  LINK_CONFIG) {
		u32* raw = (u32*)msg;
		struct tipc_media_addr* orig = (struct tipc_media_addr*)&raw[5];
		tipc_printf(buf, ":REQL(%u):", msg_req_links(msg));
		tipc_printf(buf, ":DDOM(%x):", msg_dest_domain(msg));
		tipc_printf(buf, ":NETID(%u):", msg_bc_netid(msg));
		tipc_media_addr_printf(buf, orig);
	}
	if (msg_user(msg) == BCAST_PROTOCOL) {
		tipc_printf(buf, "BCNACK:AFTER(%u):", msg_bcgap_after(msg));
		tipc_printf(buf, "TO(%u):", msg_bcgap_to(msg));
	}
	tipc_printf(buf, "\n");
	if ((usr == CHANGEOVER_PROTOCOL) && (msg_msgcnt(msg))) {
		tipc_msg_print(buf,msg_get_wrapped(msg),"      /");
	}
	if ((usr == MSG_FRAGMENTER) && (msg_type(msg) == FIRST_FRAGMENT)) {
		tipc_msg_print(buf,msg_get_wrapped(msg),"      /");
	}
}
Exemple #15
0
static u32 filter_rcv(struct sock *sk, struct sk_buff *buf)
{
	struct socket *sock = sk->sk_socket;
	struct tipc_msg *msg = buf_msg(buf);
	u32 recv_q_len;

	/* Reject message if it is wrong sort of message for socket */

	/*
	 * WOULD IT BE BETTER TO JUST DISCARD THESE MESSAGES INSTEAD?
	 * "NO PORT" ISN'T REALLY THE RIGHT ERROR CODE, AND THERE MAY
	 * BE SECURITY IMPLICATIONS INHERENT IN REJECTING INVALID TRAFFIC
	 */

	if (sock->state == SS_READY) {
		if (msg_connected(msg)) {
			msg_dbg(msg, "dispatch filter 1\n");
			return TIPC_ERR_NO_PORT;
		}
	} else {
		if (msg_mcast(msg)) {
			msg_dbg(msg, "dispatch filter 2\n");
			return TIPC_ERR_NO_PORT;
		}
		if (sock->state == SS_CONNECTED) {
			if (!msg_connected(msg)) {
				msg_dbg(msg, "dispatch filter 3\n");
				return TIPC_ERR_NO_PORT;
			}
		}
		else if (sock->state == SS_CONNECTING) {
			if (!msg_connected(msg) && (msg_errcode(msg) == 0)) {
				msg_dbg(msg, "dispatch filter 4\n");
				return TIPC_ERR_NO_PORT;
			}
		}
		else if (sock->state == SS_LISTENING) {
			if (msg_connected(msg) || msg_errcode(msg)) {
				msg_dbg(msg, "dispatch filter 5\n");
				return TIPC_ERR_NO_PORT;
			}
		}
		else if (sock->state == SS_DISCONNECTING) {
			msg_dbg(msg, "dispatch filter 6\n");
			return TIPC_ERR_NO_PORT;
		}
		else /* (sock->state == SS_UNCONNECTED) */ {
			if (msg_connected(msg) || msg_errcode(msg)) {
				msg_dbg(msg, "dispatch filter 7\n");
				return TIPC_ERR_NO_PORT;
			}
		}
	}

	/* Reject message if there isn't room to queue it */

	recv_q_len = (u32)atomic_read(&tipc_queue_size);
	if (unlikely(recv_q_len >= OVERLOAD_LIMIT_BASE)) {
		if (rx_queue_full(msg, recv_q_len, OVERLOAD_LIMIT_BASE))
			return TIPC_ERR_OVERLOAD;
	}
	recv_q_len = skb_queue_len(&sk->sk_receive_queue);
	if (unlikely(recv_q_len >= (OVERLOAD_LIMIT_BASE / 2))) {
		if (rx_queue_full(msg, recv_q_len, OVERLOAD_LIMIT_BASE / 2))
			return TIPC_ERR_OVERLOAD;
	}

	/* Enqueue message (finally!) */

	msg_dbg(msg, "<DISP<: ");
	TIPC_SKB_CB(buf)->handle = msg_data(msg);
	atomic_inc(&tipc_queue_size);
	__skb_queue_tail(&sk->sk_receive_queue, buf);

	/* Initiate connection termination for an incoming 'FIN' */

	if (unlikely(msg_errcode(msg) && (sock->state == SS_CONNECTED))) {
		sock->state = SS_DISCONNECTING;
		tipc_disconnect_port(tipc_sk_port(sk));
	}

	if (waitqueue_active(sk_sleep(sk)))
		wake_up_interruptible(sk_sleep(sk));
	return TIPC_OK;
}
Exemple #16
0
void tipc_msg_dbg(struct print_buf *buf, struct tipc_msg *msg, const char *str)
{
	u32 usr = msg_user(msg);
	tipc_printf(buf, KERN_DEBUG);
	tipc_printf(buf, str);

	switch (usr) {
	case MSG_BUNDLER:
		tipc_printf(buf, "BNDL::");
		tipc_printf(buf, "MSGS(%u):", msg_msgcnt(msg));
		break;
	case BCAST_PROTOCOL:
		tipc_printf(buf, "BCASTP::");
		break;
	case MSG_FRAGMENTER:
		tipc_printf(buf, "FRAGM::");
		switch (msg_type(msg)) {
		case FIRST_FRAGMENT:
			tipc_printf(buf, "FIRST:");
			break;
		case FRAGMENT:
			tipc_printf(buf, "BODY:");
			break;
		case LAST_FRAGMENT:
			tipc_printf(buf, "LAST:");
			break;
		default:
			tipc_printf(buf, "UNKNOWN:%x", msg_type(msg));

		}
		tipc_printf(buf, "NO(%u/%u):", msg_long_msgno(msg),
			    msg_fragm_no(msg));
		break;
	case TIPC_LOW_IMPORTANCE:
	case TIPC_MEDIUM_IMPORTANCE:
	case TIPC_HIGH_IMPORTANCE:
	case TIPC_CRITICAL_IMPORTANCE:
		tipc_printf(buf, "DAT%u:", msg_user(msg));
		if (msg_short(msg)) {
			tipc_printf(buf, "CON:");
			break;
		}
		switch (msg_type(msg)) {
		case TIPC_CONN_MSG:
			tipc_printf(buf, "CON:");
			break;
		case TIPC_MCAST_MSG:
			tipc_printf(buf, "MCST:");
			break;
		case TIPC_NAMED_MSG:
			tipc_printf(buf, "NAM:");
			break;
		case TIPC_DIRECT_MSG:
			tipc_printf(buf, "DIR:");
			break;
		default:
			tipc_printf(buf, "UNKNOWN TYPE %u", msg_type(msg));
		}
		if (msg_reroute_cnt(msg))
			tipc_printf(buf, "REROUTED(%u):",
				    msg_reroute_cnt(msg));
		break;
	case NAME_DISTRIBUTOR:
		tipc_printf(buf, "NMD::");
		switch (msg_type(msg)) {
		case PUBLICATION:
			tipc_printf(buf, "PUBL(%u):", (msg_size(msg) - msg_hdr_sz(msg)) / 20);	/* Items */
			break;
		case WITHDRAWAL:
			tipc_printf(buf, "WDRW:");
			break;
		default:
			tipc_printf(buf, "UNKNOWN:%x", msg_type(msg));
		}
		if (msg_reroute_cnt(msg))
			tipc_printf(buf, "REROUTED(%u):",
				    msg_reroute_cnt(msg));
		break;
	case CONN_MANAGER:
		tipc_printf(buf, "CONN_MNG:");
		switch (msg_type(msg)) {
		case CONN_PROBE:
			tipc_printf(buf, "PROBE:");
			break;
		case CONN_PROBE_REPLY:
			tipc_printf(buf, "PROBE_REPLY:");
			break;
		case CONN_ACK:
			tipc_printf(buf, "CONN_ACK:");
			tipc_printf(buf, "ACK(%u):", msg_msgcnt(msg));
			break;
		default:
			tipc_printf(buf, "UNKNOWN TYPE:%x", msg_type(msg));
		}
		if (msg_reroute_cnt(msg))
			tipc_printf(buf, "REROUTED(%u):", msg_reroute_cnt(msg));
		break;
	case LINK_PROTOCOL:
		switch (msg_type(msg)) {
		case STATE_MSG:
			tipc_printf(buf, "STATE:");
			tipc_printf(buf, "%s:", msg_probe(msg) ? "PRB" : "");
			tipc_printf(buf, "NXS(%u):", msg_next_sent(msg));
			tipc_printf(buf, "GAP(%u):", msg_seq_gap(msg));
			tipc_printf(buf, "LSTBC(%u):", msg_last_bcast(msg));
			break;
		case RESET_MSG:
			tipc_printf(buf, "RESET:");
			if (msg_size(msg) != msg_hdr_sz(msg))
				tipc_printf(buf, "BEAR:%s:", msg_data(msg));
			break;
		case ACTIVATE_MSG:
			tipc_printf(buf, "ACTIVATE:");
			break;
		default:
			tipc_printf(buf, "UNKNOWN TYPE:%x", msg_type(msg));
		}
		tipc_printf(buf, "PLANE(%c):", msg_net_plane(msg));
		tipc_printf(buf, "SESS(%u):", msg_session(msg));
		break;
	case CHANGEOVER_PROTOCOL:
		tipc_printf(buf, "TUNL:");
		switch (msg_type(msg)) {
		case DUPLICATE_MSG:
			tipc_printf(buf, "DUPL:");
			break;
		case ORIGINAL_MSG:
			tipc_printf(buf, "ORIG:");
			tipc_printf(buf, "EXP(%u)", msg_msgcnt(msg));
			break;
		default:
			tipc_printf(buf, "UNKNOWN TYPE:%x", msg_type(msg));
		}
		break;
	case LINK_CONFIG:
		tipc_printf(buf, "CFG:");
		switch (msg_type(msg)) {
		case DSC_REQ_MSG:
			tipc_printf(buf, "DSC_REQ:");
			break;
		case DSC_RESP_MSG:
			tipc_printf(buf, "DSC_RESP:");
			break;
		default:
			tipc_printf(buf, "UNKNOWN TYPE:%x:", msg_type(msg));
			break;
		}
		break;
	default:
		tipc_printf(buf, "UNKNOWN USER:"******"NO_NAME:");
			break;
		case TIPC_ERR_NO_PORT:
			tipc_printf(buf, "NO_PORT:");
			break;
		case TIPC_ERR_NO_NODE:
			tipc_printf(buf, "NO_PROC:");
			break;
		case TIPC_ERR_OVERLOAD:
			tipc_printf(buf, "OVERLOAD:");
			break;
		case TIPC_CONN_SHUTDOWN:
			tipc_printf(buf, "SHUTDOWN:");
			break;
		default:
			tipc_printf(buf, "UNKNOWN ERROR(%x):",
				    msg_errcode(msg));
		}
	default:
		break;
	}

	tipc_printf(buf, "HZ(%u):", msg_hdr_sz(msg
Exemple #17
0
int main(int argc, char *argv[])
{
	char *filedir = NULL;
	char *htmldir = NULL;
	char *htmlextension = "html";
	char *onlytests = NULL;
	char *msg;
	enum role_t role = ROLE_STATUS;
	enum msgchannels_t chnid = C_STATUS;
	int argi;
	int seq;
	int running = 1;

	/* Dont save the error buffer */
	save_errbuf = 0;

	for (argi = 1; (argi < argc); argi++) {
		if (strcmp(argv[argi], "--status") == 0) {
			role = ROLE_STATUS;
			chnid = C_STATUS;
			if (!filedir) filedir = xgetenv("XYMONRAWSTATUSDIR");
		}
		else if (strcmp(argv[argi], "--html") == 0) {
			role = ROLE_STATUS;
			chnid = C_STATUS;
			if (!htmldir) htmldir = xgetenv("XYMONHTMLSTATUSDIR");
		}
		else if (strcmp(argv[argi], "--data") == 0) {
			role = ROLE_DATA;
			chnid = C_DATA;
			if (!filedir) filedir = xgetenv("XYMONDATADIR");
		}
		else if (strcmp(argv[argi], "--notes") == 0) {
			role = ROLE_NOTES;
			chnid = C_NOTES;
			if (!filedir) filedir = xgetenv("XYMONNOTESDIR");
		}
		else if (strcmp(argv[argi], "--enadis") == 0) {
			role = ROLE_ENADIS;
			chnid = C_ENADIS;
			if (!filedir) filedir = xgetenv("XYMONDISABLEDDIR");
		}
		else if (strcmp(argv[argi], "--debug") == 0) {
			debug = 1;
		}
		else if (argnmatch(argv[argi], "--dir=")) {
			filedir = strchr(argv[argi], '=')+1;
		}
		else if (argnmatch(argv[argi], "--htmldir=")) {
			htmldir = strchr(argv[argi], '=')+1;
		}
		else if (argnmatch(argv[argi], "--htmlext=")) {
			htmlextension = strchr(argv[argi], '=')+1;
		}
		else if (argnmatch(argv[argi], "--only=")) {
			char *p = strchr(argv[argi], '=') + 1;
			onlytests = (char *)malloc(3 + strlen(p));
			sprintf(onlytests, ",%s,", p);
		}
		else if (argnmatch(argv[argi], "--multigraphs=")) {
			char *p = strchr(argv[argi], '=');
			multigraphs = (char *)malloc(strlen(p+1) + 3);
			sprintf(multigraphs, ",%s,", p+1);
		}
		else if (argnmatch(argv[argi], "--locator=")) {
			char *p = strchr(argv[argi], '=');
			locator_init(p+1);
			locatorbased = 1;
		}
	}

	if (filedir == NULL) {
		errprintf("No directory given, aborting\n");
		return 1;
	}

	/* For picking up lost children */
	setup_signalhandler("xymond_filestore");
	signal(SIGPIPE, SIG_DFL);

	if (onlytests) dbgprintf("Storing tests '%s' only\n", onlytests);
	else dbgprintf("Storing all tests\n");

	while (running) {
		char *metadata[20] = { NULL, };
		char *statusdata = "";
		char *p;
		int metacount;
		char *hostname, *testname;
		time_t expiretime = 0;
		char logfn[PATH_MAX];

		MEMDEFINE(logfn);

		msg = get_xymond_message(chnid, "filestore", &seq, NULL);
		if (msg == NULL) {
			running = 0;
			MEMUNDEFINE(logfn);
			continue;
		}

		p = strchr(msg, '\n'); 
		if (p) {
			*p = '\0'; 
			statusdata = p+1;
		}

		metacount = 0;
		memset(&metadata, 0, sizeof(metadata));
		p = gettok(msg, "|");
		while (p && (metacount < 20)) {
			metadata[metacount++] = p;
			p = gettok(NULL, "|");
		}

		if ((role == ROLE_STATUS) && (metacount >= 14) && (strncmp(metadata[0], "@@status", 8) == 0)) {
			/* @@status|timestamp|sender|origin|hostname|testname|expiretime|color|testflags|prevcolor|changetime|ackexpiretime|ackmessage|disableexpiretime|disablemessage|clientmsgtstamp|flapping */
			int ltime, flapping = 0;
			time_t logtime = 0, timesincechange = 0, acktime = 0, disabletime = 0;

			hostname = metadata[4];
			testname = metadata[5];
			if (!wantedtest(onlytests, testname)) {
				dbgprintf("Status dropped - not wanted\n");
				MEMUNDEFINE(logfn);
				continue;
			}

			sprintf(logfn, "%s/%s.%s", filedir, commafy(hostname), testname);
			expiretime = atoi(metadata[6]);
			statusdata = msg_data(statusdata);
			sscanf(metadata[1], "%d.%*d", &ltime); logtime = ltime;
			timesincechange = logtime - atoi(metadata[10]);
			update_file(logfn, "w", statusdata, expiretime, metadata[2], timesincechange, seq);
			if (htmldir) {
				char *ackmsg = NULL;
				char *dismsg = NULL;
				char htmllogfn[PATH_MAX];

				MEMDEFINE(htmllogfn);

				if (metadata[11]) acktime = atoi(metadata[11]);
				if (metadata[12] && strlen(metadata[12])) ackmsg = metadata[12];
				if (ackmsg) nldecode(ackmsg);

				if (metadata[13]) disabletime = atoi(metadata[13]);
				if (metadata[14] && strlen(metadata[14]) && (disabletime > 0)) dismsg = metadata[14];
				if (dismsg) nldecode(dismsg);

				flapping = (metadata[16] ? (*metadata[16] == '1') : 0);

				sprintf(htmllogfn, "%s/%s.%s.%s", htmldir, hostname, testname, htmlextension);
				update_htmlfile(htmllogfn, statusdata, hostname, testname, parse_color(metadata[7]), flapping,
						     metadata[2], metadata[8], logtime, timesincechange, 
						     acktime, ackmsg,
						     disabletime, dismsg);

				MEMUNDEFINE(htmllogfn);
			}
		}
		else if ((role == ROLE_DATA) && (metacount > 5) && (strncmp(metadata[0], "@@data", 6) == 0)) {
			/* @@data|timestamp|sender|hostname|testname */
			p = hostname = metadata[4]; while ((p = strchr(p, '.')) != NULL) *p = ',';
			testname = metadata[5];
			if (!wantedtest(onlytests, testname)) {
				dbgprintf("data dropped - not wanted\n");
				MEMUNDEFINE(logfn);
				continue;
			}

			statusdata = msg_data(statusdata); if (*statusdata == '\n') statusdata++;
			sprintf(logfn, "%s/%s.%s", filedir, hostname, testname);
			expiretime = 0;
			update_file(logfn, "a", statusdata, expiretime, NULL, -1, seq);
		}
		else if ((role == ROLE_NOTES) && (metacount > 3) && (strncmp(metadata[0], "@@notes", 7) == 0)) {
			/* @@notes|timestamp|sender|hostname */
			hostname = metadata[3];
			statusdata = msg_data(statusdata); if (*statusdata == '\n') statusdata++;
			sprintf(logfn, "%s/%s", basename(filedir), hostname);
			expiretime = 0;
			update_file(logfn, "w", statusdata, expiretime, NULL, -1, seq);
		}
		else if ((role == ROLE_ENADIS) && (metacount > 5) && (strncmp(metadata[0], "@@enadis", 8) == 0)) {
			/* @@enadis|timestamp|sender|hostname|testname|expiretime */
			p = hostname = metadata[3]; while ((p = strchr(p, '.')) != NULL) *p = ',';
			testname = metadata[4];
			expiretime = atoi(metadata[5]);
			sprintf(logfn, "%s/%s.%s", filedir, hostname, testname);
			update_enable(logfn, expiretime);
		}
		else if (((role == ROLE_STATUS) || (role == ROLE_DATA) || (role == ROLE_ENADIS)) && (metacount > 3) && (strncmp(metadata[0], "@@drophost", 10) == 0)) {
			/* @@drophost|timestamp|sender|hostname */
			DIR *dirfd;
			struct dirent *de;
			char *hostlead;

			p = hostname = metadata[3]; while ((p = strchr(p, '.')) != NULL) *p = ',';
			hostlead = malloc(strlen(hostname) + 2);
			strcpy(hostlead, hostname); strcat(hostlead, ".");

			dirfd = opendir(filedir);
			if (dirfd) {
				while ( (de = readdir(dirfd)) != NULL) {
					if (strncmp(de->d_name, hostlead, strlen(hostlead)) == 0) {
						sprintf(logfn, "%s/%s", filedir, de->d_name);
						unlink(logfn);
					}
				}
				closedir(dirfd);
			}

			xfree(hostlead);
		}
		else if (((role == ROLE_STATUS) || (role == ROLE_DATA) || (role == ROLE_ENADIS)) && (metacount > 4) && (strncmp(metadata[0], "@@droptest", 10) == 0)) {
			/* @@droptest|timestamp|sender|hostname|testname */
			p = hostname = metadata[3]; while ((p = strchr(p, '.')) != NULL) *p = ',';
			testname = metadata[4];
			sprintf(logfn, "%s/%s.%s", filedir, hostname, testname);
			unlink(logfn);
		}
		else if (((role == ROLE_STATUS) || (role == ROLE_DATA) || (role == ROLE_ENADIS)) && (metacount > 4) && (strncmp(metadata[0], "@@renamehost", 12) == 0)) {
			/* @@renamehost|timestamp|sender|hostname|newhostname */
			DIR *dirfd;
			struct dirent *de;
			char *hostlead;
			char *newhostname;
			char newlogfn[PATH_MAX];

			MEMDEFINE(newlogfn);

			p = hostname = metadata[3]; while ((p = strchr(p, '.')) != NULL) *p = ',';
			hostlead = malloc(strlen(hostname) + 2);
			strcpy(hostlead, hostname); strcat(hostlead, ".");
			p = newhostname = metadata[4]; while ((p = strchr(p, '.')) != NULL) *p = ',';

			dirfd = opendir(filedir);
			if (dirfd) {
				while ( (de = readdir(dirfd)) != NULL) {
					if (strncmp(de->d_name, hostlead, strlen(hostlead)) == 0) {
						char *testname = strchr(de->d_name, '.');
						sprintf(logfn, "%s/%s", filedir, de->d_name);
						sprintf(newlogfn, "%s/%s%s", filedir, newhostname, testname);
						rename(logfn, newlogfn);
					}
				}
				closedir(dirfd);
			}
			xfree(hostlead);

			MEMUNDEFINE(newlogfn);
		}
		else if (((role == ROLE_STATUS) || (role == ROLE_DATA) || (role == ROLE_ENADIS)) && (metacount > 5) && (strncmp(metadata[0], "@@renametest", 12) == 0)) {
			/* @@renametest|timestamp|sender|hostname|oldtestname|newtestname */
			char *newtestname;
			char newfn[PATH_MAX];

			MEMDEFINE(newfn);

			p = hostname = metadata[3]; while ((p = strchr(p, '.')) != NULL) *p = ',';
			testname = metadata[4];
			newtestname = metadata[5];
			sprintf(logfn, "%s/%s.%s", filedir, hostname, testname);
			sprintf(newfn, "%s/%s.%s", filedir, hostname, newtestname);
			rename(logfn, newfn);

			MEMUNDEFINE(newfn);
		}
		else if (strncmp(metadata[0], "@@shutdown", 10) == 0) {
			running = 0;
		}
		else if (strncmp(metadata[0], "@@logrotate", 11) == 0) {
			char *fn = xgetenv("XYMONCHANNEL_LOGFILENAME");
			if (fn && strlen(fn)) {
				freopen(fn, "a", stdout);
				freopen(fn, "a", stderr);
			}
			continue;
		}
		else if (strncmp(metadata[0], "@@idle", 6) == 0) {
			/* Ignored */
		}
		else {
			errprintf("Dropping message type %s, metacount=%d\n", metadata[0], metacount);
		}

		MEMUNDEFINE(logfn);
	}

	return 0;
}