krishnanadh / rpms / rasdaemon

Forked from rpms/rasdaemon a year ago
Clone
ac32bf
From c6ed1e1af9356cdce1eaa652061dd6e4eb32d283 Mon Sep 17 00:00:00 2001
ac32bf
From: Junliang Li <lijunliang.dna@gmail.com>
ac32bf
Date: Thu, 13 Feb 2014 10:39:53 +0800
ac32bf
Subject: [PATCH 23/32] add abrt suppport for rasdaemon
ac32bf
ac32bf
Adds abrt as another error mechanism for the rasdaemon.
ac32bf
This patch does:
ac32bf
ac32bf
1) read ras event (mc,mce and aer)
ac32bf
ac32bf
2) setup a abrt-server unix socket
ac32bf
ac32bf
3) write messages follow ABRT server protocol, set event
ac32bf
   info into backtrace zone.
ac32bf
ac32bf
4) commit report.
ac32bf
ac32bf
For now, it depends on ABRT to limit flood reports.
ac32bf
ac32bf
Signed-off-by: Junliang Li <lijunliang.dna@gmail.com>
ac32bf
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
ac32bf
---
ac32bf
 Makefile.am       |    5 +-
ac32bf
 configure.ac      |    9 +
ac32bf
 ras-aer-handler.c |    6 +
ac32bf
 ras-events.h      |    3 +
ac32bf
 ras-mc-handler.c  |    7 +
ac32bf
 ras-mce-handler.c |    6 +
ac32bf
 ras-report.c      |  429 +++++++++++++++++++++++++++++++++++++++++++++++++++++
ac32bf
 ras-report.h      |   39 +++++
ac32bf
 8 files changed, 503 insertions(+), 1 deletions(-)
ac32bf
 create mode 100644 ras-report.c
ac32bf
 create mode 100644 ras-report.h
ac32bf
ac32bf
diff --git a/Makefile.am b/Makefile.am
ac32bf
index 473ce98..c1668b4 100644
ac32bf
--- a/Makefile.am
ac32bf
+++ b/Makefile.am
ac32bf
@@ -17,10 +17,13 @@ if WITH_MCE
ac32bf
 			mce-intel-dunnington.c mce-intel-tulsa.c \
ac32bf
 			mce-intel-sb.c mce-intel-ivb.c
ac32bf
 endif
ac32bf
+if WITH_ABRT_REPORT
ac32bf
+   rasdaemon_SOURCES += ras-report.c
ac32bf
+endif
ac32bf
 rasdaemon_LDADD = -lpthread $(SQLITE3_LIBS) libtrace/libtrace.a
ac32bf
 
ac32bf
 include_HEADERS = config.h  ras-events.h  ras-logger.h  ras-mc-handler.h \
ac32bf
-		  ras-aer-handler.h ras-mce-handler.h ras-record.h bitfield.h
ac32bf
+		  ras-aer-handler.h ras-mce-handler.h ras-record.h bitfield.h ras-report.h
ac32bf
 
ac32bf
 # This rule can't be called with more than one Makefile job (like make -j8)
ac32bf
 # I can't figure out a way to fix that
ac32bf
diff --git a/configure.ac b/configure.ac
ac32bf
index 4fe6ef2..0ea962e 100644
ac32bf
--- a/configure.ac
ac32bf
+++ b/configure.ac
ac32bf
@@ -53,6 +53,15 @@ AS_IF([test "x$enable_mce" = "xyes"], [
ac32bf
 ])
ac32bf
 AM_CONDITIONAL([WITH_MCE], [test x$enable_mce = xyes])
ac32bf
 
ac32bf
+AC_ARG_ENABLE([abrt_report],
ac32bf
+    AS_HELP_STRING([--enable-abrt-report], [enable report event to ABRT (currently experimental)]))
ac32bf
+
ac32bf
+AS_IF([test "x$enable_abrt_report" = "xyes"], [
ac32bf
+  AC_DEFINE(HAVE_ABRT_REPORT,1,"have report event to ABRT")
ac32bf
+  AC_SUBST([WITH_ABRT_REPORT])
ac32bf
+])
ac32bf
+AM_CONDITIONAL([WITH_ABRT_REPORT], [test x$enable_abrt_report = xyes])
ac32bf
+
ac32bf
 test "$sysconfdir" = '${prefix}/etc' && sysconfdir=/etc
ac32bf
 
ac32bf
 CFLAGS="$CFLAGS -Wall -Wmissing-prototypes -Wstrict-prototypes"
ac32bf
diff --git a/ras-aer-handler.c b/ras-aer-handler.c
ac32bf
index e5abaca..50526af 100644
ac32bf
--- a/ras-aer-handler.c
ac32bf
+++ b/ras-aer-handler.c
ac32bf
@@ -24,6 +24,7 @@
ac32bf
 #include "ras-record.h"
ac32bf
 #include "ras-logger.h"
ac32bf
 #include "bitfield.h"
ac32bf
+#include "ras-report.h"
ac32bf
 
ac32bf
 static const char *aer_errors[32] = {
ac32bf
 	/* Correctable errors */
ac32bf
@@ -115,5 +116,10 @@ int ras_aer_event_handler(struct trace_seq *s,
ac32bf
 	ras_store_aer_event(ras, &ev;;
ac32bf
 #endif
ac32bf
 
ac32bf
+#ifdef HAVE_ABRT_REPORT
ac32bf
+	/* Report event to ABRT */
ac32bf
+	ras_report_aer_event(ras, &ev;;
ac32bf
+#endif
ac32bf
+
ac32bf
 	return 0;
ac32bf
 }
ac32bf
diff --git a/ras-events.h b/ras-events.h
ac32bf
index 554a95e..64e045a 100644
ac32bf
--- a/ras-events.h
ac32bf
+++ b/ras-events.h
ac32bf
@@ -47,6 +47,9 @@ struct ras_events {
ac32bf
 
ac32bf
 	/* For the mce handler */
ac32bf
 	struct mce_priv	*mce_priv;
ac32bf
+
ac32bf
+	/* For ABRT socket*/
ac32bf
+	int socketfd;
ac32bf
 };
ac32bf
 
ac32bf
 struct pthread_data {
ac32bf
diff --git a/ras-mc-handler.c b/ras-mc-handler.c
ac32bf
index 5c24f65..ffb3805 100644
ac32bf
--- a/ras-mc-handler.c
ac32bf
+++ b/ras-mc-handler.c
ac32bf
@@ -23,6 +23,7 @@
ac32bf
 #include "ras-mc-handler.h"
ac32bf
 #include "ras-record.h"
ac32bf
 #include "ras-logger.h"
ac32bf
+#include "ras-report.h"
ac32bf
 
ac32bf
 int ras_mc_event_handler(struct trace_seq *s,
ac32bf
 			 struct pevent_record *record,
ac32bf
@@ -189,6 +190,12 @@ int ras_mc_event_handler(struct trace_seq *s,
ac32bf
 	/* Insert data into the SGBD */
ac32bf
 
ac32bf
 	ras_store_mc_event(ras, &ev;;
ac32bf
+
ac32bf
+#ifdef HAVE_ABRT_REPORT
ac32bf
+	/* Report event to ABRT */
ac32bf
+	ras_report_mc_event(ras, &ev;;
ac32bf
+#endif
ac32bf
+
ac32bf
 	return 0;
ac32bf
 
ac32bf
 parse_error:
ac32bf
diff --git a/ras-mce-handler.c b/ras-mce-handler.c
ac32bf
index 59e8d05..1431049 100644
ac32bf
--- a/ras-mce-handler.c
ac32bf
+++ b/ras-mce-handler.c
ac32bf
@@ -26,6 +26,7 @@
ac32bf
 #include "ras-mce-handler.h"
ac32bf
 #include "ras-record.h"
ac32bf
 #include "ras-logger.h"
ac32bf
+#include "ras-report.h"
ac32bf
 
ac32bf
 /*
ac32bf
  * The code below were adapted from Andi Kleen/Intel/SuSe mcelog code,
ac32bf
@@ -401,5 +402,10 @@ int ras_mce_event_handler(struct trace_seq *s,
ac32bf
 	ras_store_mce_record(ras, &e);
ac32bf
 #endif
ac32bf
 
ac32bf
+#ifdef HAVE_ABRT_REPORT
ac32bf
+	/* Report event to ABRT */
ac32bf
+	ras_report_mce_event(ras, &e);
ac32bf
+#endif
ac32bf
+
ac32bf
 	return 0;
ac32bf
 }
ac32bf
diff --git a/ras-report.c b/ras-report.c
ac32bf
new file mode 100644
ac32bf
index 0000000..d3e4a79
ac32bf
--- /dev/null
ac32bf
+++ b/ras-report.c
ac32bf
@@ -0,0 +1,429 @@
ac32bf
+#include <stdio.h>
ac32bf
+#include <string.h>
ac32bf
+#include <unistd.h>
ac32bf
+#include <sys/types.h>
ac32bf
+#include <sys/utsname.h>
ac32bf
+#include <sys/socket.h>
ac32bf
+#include <sys/un.h>
ac32bf
+
ac32bf
+#include "ras-report.h"
ac32bf
+
ac32bf
+static int setup_report_socket(void){
ac32bf
+	int sockfd = -1;
ac32bf
+	int rc = -1;
ac32bf
+	struct sockaddr_un addr;
ac32bf
+
ac32bf
+	sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
ac32bf
+	if (sockfd < 0){
ac32bf
+		return -1;
ac32bf
+	}
ac32bf
+
ac32bf
+	memset(&addr, 0, sizeof(struct sockaddr_un));
ac32bf
+	addr.sun_family = AF_UNIX;
ac32bf
+	strncpy(addr.sun_path, ABRT_SOCKET, strlen(ABRT_SOCKET));
ac32bf
+
ac32bf
+	rc = connect(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un));
ac32bf
+	if (rc < 0){
ac32bf
+		return -1;
ac32bf
+	}
ac32bf
+
ac32bf
+	return sockfd;
ac32bf
+}
ac32bf
+
ac32bf
+static int commit_report_basic(int sockfd){
ac32bf
+	char buf[INPUT_BUFFER_SIZE];
ac32bf
+	struct utsname un;
ac32bf
+	int rc = -1;
ac32bf
+
ac32bf
+	if(sockfd < 0){
ac32bf
+		return rc;
ac32bf
+	}
ac32bf
+
ac32bf
+	memset(buf, 0, INPUT_BUFFER_SIZE);
ac32bf
+	memset(&un, 0, sizeof(struct utsname));
ac32bf
+
ac32bf
+	rc = uname(&un;;
ac32bf
+	if(rc < 0){
ac32bf
+		return rc;
ac32bf
+	}
ac32bf
+
ac32bf
+	/*
ac32bf
+	 * ABRT server protocol
ac32bf
+	 */
ac32bf
+	sprintf(buf, "PUT / HTTP/1.1\r\n\r\n");
ac32bf
+	rc = write(sockfd, buf, strlen(buf) + 1);
ac32bf
+	if(rc < strlen(buf) + 1){
ac32bf
+		return -1;
ac32bf
+	}
ac32bf
+
ac32bf
+	sprintf(buf, "PID=%d", (int)getpid());
ac32bf
+	rc = write(sockfd, buf, strlen(buf) + 1);
ac32bf
+	if(rc < strlen(buf) + 1){
ac32bf
+		return -1;
ac32bf
+	}
ac32bf
+
ac32bf
+	sprintf(buf, "EXECUTABLE=/boot/vmlinuz-%s", un.release);
ac32bf
+	rc = write(sockfd, buf, strlen(buf) + 1);
ac32bf
+	if(rc < strlen(buf) + 1){
ac32bf
+		return -1;
ac32bf
+	}
ac32bf
+
ac32bf
+	sprintf(buf, "BASENAME=%s", "rasdaemon");
ac32bf
+	rc = write(sockfd, buf, strlen(buf) + 1);
ac32bf
+	if(rc < strlen(buf) + 1){
ac32bf
+		return -1;
ac32bf
+	}
ac32bf
+
ac32bf
+	return 0;
ac32bf
+}
ac32bf
+
ac32bf
+/*
ac32bf
+ *  add "DONE" string to finish message.
ac32bf
+ */
ac32bf
+static int commit_report_done(int sockfd){
ac32bf
+	int rc = -1;
ac32bf
+
ac32bf
+	if(sockfd < 0){
ac32bf
+		return -1;
ac32bf
+	}
ac32bf
+
ac32bf
+	rc = write(sockfd, "DONE\0", strlen("DONE\0"));
ac32bf
+	if(rc < strlen("DONE\0")){
ac32bf
+		return -1;
ac32bf
+	}
ac32bf
+
ac32bf
+	return 0;
ac32bf
+}
ac32bf
+
ac32bf
+static int set_mc_event_backtrace(char *buf, struct ras_mc_event *ev){
ac32bf
+	char bt_buf[MAX_BACKTRACE_SIZE];
ac32bf
+
ac32bf
+	if(!buf || !ev)
ac32bf
+		return -1;
ac32bf
+
ac32bf
+	sprintf(bt_buf, "BACKTRACE= "	\
ac32bf
+						"timestamp=%s\n"	\
ac32bf
+						"error_count=%d\n"	\
ac32bf
+						"error_type=%s\n"	\
ac32bf
+						"msg=%s\n"	\
ac32bf
+						"label=%s\n"	\
ac32bf
+						"mc_index=%c\n"	\
ac32bf
+						"top_layer=%c\n"	\
ac32bf
+						"middle_layer=%c\n"	\
ac32bf
+						"lower_layer=%c\n"	\
ac32bf
+						"address=%llu\n"	\
ac32bf
+						"grain=%llu\n"	\
ac32bf
+						"syndrome=%llu\n"	\
ac32bf
+						"driver_detail=%s\n",	\
ac32bf
+						ev->timestamp,	\
ac32bf
+						ev->error_count,	\
ac32bf
+						ev->error_type,	\
ac32bf
+						ev->msg,	\
ac32bf
+						ev->label,	\
ac32bf
+						ev->mc_index,	\
ac32bf
+						ev->top_layer,	\
ac32bf
+						ev->middle_layer,	\
ac32bf
+						ev->lower_layer,	\
ac32bf
+						ev->address,	\
ac32bf
+						ev->grain,	\
ac32bf
+						ev->syndrome,	\
ac32bf
+						ev->driver_detail);
ac32bf
+
ac32bf
+	strcat(buf, bt_buf);
ac32bf
+
ac32bf
+	return 0;
ac32bf
+}
ac32bf
+
ac32bf
+static int set_mce_event_backtrace(char *buf, struct mce_event *ev){
ac32bf
+	char bt_buf[MAX_BACKTRACE_SIZE];
ac32bf
+
ac32bf
+	if(!buf || !ev)
ac32bf
+		return -1;
ac32bf
+
ac32bf
+	sprintf(bt_buf, "BACKTRACE="	\
ac32bf
+						"timestamp=%s\n"	\
ac32bf
+						"bank_name=%s\n"	\
ac32bf
+						"error_msg=%s\n"	\
ac32bf
+						"mcgstatus_msg=%s\n"	\
ac32bf
+						"mcistatus_msg=%s\n"	\
ac32bf
+						"mcastatus_msg=%s\n"	\
ac32bf
+						"user_action=%s\n"	\
ac32bf
+						"mc_location=%s\n"	\
ac32bf
+						"mcgcap=%lu\n"	\
ac32bf
+						"mcgstatus=%lu\n"	\
ac32bf
+						"status=%lu\n"	\
ac32bf
+						"addr=%lu\n"	\
ac32bf
+						"misc=%lu\n"	\
ac32bf
+						"ip=%lu\n"	\
ac32bf
+						"tsc=%lu\n"	\
ac32bf
+						"walltime=%lu\n"	\
ac32bf
+						"cpu=%u\n"	\
ac32bf
+						"cpuid=%u\n"	\
ac32bf
+						"apicid=%u\n"	\
ac32bf
+						"socketid=%u\n"	\
ac32bf
+						"cs=%d\n"	\
ac32bf
+						"bank=%d\n"	\
ac32bf
+						"cpuvendor=%d\n",	\
ac32bf
+						ev->timestamp,	\
ac32bf
+						ev->bank_name,	\
ac32bf
+						ev->error_msg,	\
ac32bf
+						ev->mcgstatus_msg,	\
ac32bf
+						ev->mcistatus_msg,	\
ac32bf
+						ev->mcastatus_msg,	\
ac32bf
+						ev->user_action,	\
ac32bf
+						ev->mc_location,	\
ac32bf
+						ev->mcgcap,	\
ac32bf
+						ev->mcgstatus,	\
ac32bf
+						ev->status,	\
ac32bf
+						ev->addr,	\
ac32bf
+						ev->misc,	\
ac32bf
+						ev->ip,	\
ac32bf
+						ev->tsc,	\
ac32bf
+						ev->walltime,	\
ac32bf
+						ev->cpu,	\
ac32bf
+						ev->cpuid,	\
ac32bf
+						ev->apicid,	\
ac32bf
+						ev->socketid,	\
ac32bf
+						ev->cs,	\
ac32bf
+						ev->bank,	\
ac32bf
+						ev->cpuvendor);
ac32bf
+
ac32bf
+	strcat(buf, bt_buf);
ac32bf
+
ac32bf
+	return 0;
ac32bf
+}
ac32bf
+
ac32bf
+static int set_aer_event_backtrace(char *buf, struct ras_aer_event *ev){
ac32bf
+	char bt_buf[MAX_BACKTRACE_SIZE];
ac32bf
+
ac32bf
+	if(!buf || !ev)
ac32bf
+		return -1;
ac32bf
+
ac32bf
+	sprintf(bt_buf, "BACKTRACE="	\
ac32bf
+						"timestamp=%s\n"	\
ac32bf
+						"error_type=%s\n"	\
ac32bf
+						"dev_name=%s\n"	\
ac32bf
+						"msg=%s\n",	\
ac32bf
+						ev->timestamp,	\
ac32bf
+						ev->error_type,	\
ac32bf
+						ev->dev_name,	\
ac32bf
+						ev->msg);
ac32bf
+
ac32bf
+	strcat(buf, bt_buf);
ac32bf
+
ac32bf
+	return 0;
ac32bf
+}
ac32bf
+
ac32bf
+static int commit_report_backtrace(int sockfd, int type, void *ev){
ac32bf
+	char buf[MAX_BACKTRACE_SIZE];
ac32bf
+	char *pbuf = buf;
ac32bf
+	int rc = -1;
ac32bf
+	int buf_len = 0;
ac32bf
+
ac32bf
+	if(sockfd < 0 || !ev){
ac32bf
+		return -1;
ac32bf
+	}
ac32bf
+
ac32bf
+	memset(buf, 0, MAX_BACKTRACE_SIZE);
ac32bf
+
ac32bf
+	switch(type){
ac32bf
+	case MC_EVENT:
ac32bf
+		rc = set_mc_event_backtrace(buf, (struct ras_mc_event *)ev);
ac32bf
+		break;
ac32bf
+	case AER_EVENT:
ac32bf
+		rc = set_aer_event_backtrace(buf, (struct ras_aer_event *)ev);
ac32bf
+		break;
ac32bf
+	case MCE_EVENT:
ac32bf
+		rc = set_mce_event_backtrace(buf, (struct mce_event *)ev);
ac32bf
+		break;
ac32bf
+	default:
ac32bf
+		return -1;
ac32bf
+	}
ac32bf
+
ac32bf
+	if(rc < 0){
ac32bf
+		return -1;
ac32bf
+	}
ac32bf
+
ac32bf
+	buf_len = strlen(buf);
ac32bf
+
ac32bf
+	for(;buf_len > INPUT_BUFFER_SIZE - 1; buf_len -= (INPUT_BUFFER_SIZE - 1)){
ac32bf
+		rc = write(sockfd, pbuf, INPUT_BUFFER_SIZE - 1);
ac32bf
+		if(rc < INPUT_BUFFER_SIZE - 1){
ac32bf
+			return -1;
ac32bf
+		}
ac32bf
+
ac32bf
+		pbuf = pbuf + INPUT_BUFFER_SIZE - 1;
ac32bf
+	}
ac32bf
+
ac32bf
+	rc = write(sockfd, pbuf, buf_len + 1);
ac32bf
+	if(rc < buf_len){
ac32bf
+		return -1;
ac32bf
+	}
ac32bf
+
ac32bf
+	return 0;
ac32bf
+}
ac32bf
+
ac32bf
+int ras_report_mc_event(struct ras_events *ras, struct ras_mc_event *ev){
ac32bf
+	char buf[MAX_MESSAGE_SIZE];
ac32bf
+	int sockfd = -1;
ac32bf
+	int done = 0;
ac32bf
+	int rc = -1;
ac32bf
+
ac32bf
+	memset(buf, 0, sizeof(buf));
ac32bf
+
ac32bf
+	sockfd = setup_report_socket();
ac32bf
+	if(sockfd < 0){
ac32bf
+		return -1;
ac32bf
+	}
ac32bf
+
ac32bf
+	rc = commit_report_basic(sockfd);
ac32bf
+	if(rc < 0){
ac32bf
+		goto mc_fail;
ac32bf
+	}
ac32bf
+
ac32bf
+	rc = commit_report_backtrace(sockfd, MC_EVENT, ev);
ac32bf
+	if(rc < 0){
ac32bf
+		goto mc_fail;
ac32bf
+	}
ac32bf
+
ac32bf
+	sprintf(buf, "ANALYZER=%s", "rasdaemon-mc");
ac32bf
+	rc = write(sockfd, buf, strlen(buf) + 1);
ac32bf
+	if(rc < strlen(buf) + 1){
ac32bf
+		goto mc_fail;
ac32bf
+	}
ac32bf
+
ac32bf
+	sprintf(buf, "REASON=%s", "EDAC driver report problem");
ac32bf
+	rc = write(sockfd, buf, strlen(buf) + 1);
ac32bf
+	if(rc < strlen(buf) + 1){
ac32bf
+		goto mc_fail;
ac32bf
+	}
ac32bf
+
ac32bf
+	rc = commit_report_done(sockfd);
ac32bf
+	if(rc < 0){
ac32bf
+		goto mc_fail;
ac32bf
+	}
ac32bf
+
ac32bf
+	done = 1;
ac32bf
+
ac32bf
+mc_fail:
ac32bf
+
ac32bf
+	if(sockfd > 0){
ac32bf
+		close(sockfd);
ac32bf
+	}
ac32bf
+
ac32bf
+	if(done){
ac32bf
+		return 0;
ac32bf
+	}else{
ac32bf
+		return -1;
ac32bf
+	}
ac32bf
+}
ac32bf
+
ac32bf
+int ras_report_aer_event(struct ras_events *ras, struct ras_aer_event *ev){
ac32bf
+	char buf[MAX_MESSAGE_SIZE];
ac32bf
+	int sockfd = 0;
ac32bf
+	int done = 0;
ac32bf
+	int rc = -1;
ac32bf
+
ac32bf
+	memset(buf, 0, sizeof(buf));
ac32bf
+
ac32bf
+	sockfd = setup_report_socket();
ac32bf
+	if(sockfd < 0){
ac32bf
+		return -1;
ac32bf
+	}
ac32bf
+
ac32bf
+	rc = commit_report_basic(sockfd);
ac32bf
+	if(rc < 0){
ac32bf
+		goto aer_fail;
ac32bf
+	}
ac32bf
+
ac32bf
+	rc = commit_report_backtrace(sockfd, AER_EVENT, ev);
ac32bf
+	if(rc < 0){
ac32bf
+		goto aer_fail;
ac32bf
+	}
ac32bf
+
ac32bf
+	sprintf(buf, "ANALYZER=%s", "rasdaemon-aer");
ac32bf
+	rc = write(sockfd, buf, strlen(buf) + 1);
ac32bf
+	if(rc < strlen(buf) + 1){
ac32bf
+		goto aer_fail;
ac32bf
+	}
ac32bf
+
ac32bf
+	sprintf(buf, "REASON=%s", "PCIe AER driver report problem");
ac32bf
+	rc = write(sockfd, buf, strlen(buf) + 1);
ac32bf
+	if(rc < strlen(buf) + 1){
ac32bf
+		goto aer_fail;
ac32bf
+	}
ac32bf
+
ac32bf
+	rc = commit_report_done(sockfd);
ac32bf
+	if(rc < 0){
ac32bf
+		goto aer_fail;
ac32bf
+	}
ac32bf
+
ac32bf
+	done = 1;
ac32bf
+
ac32bf
+aer_fail:
ac32bf
+
ac32bf
+	if(sockfd > 0){
ac32bf
+		close(sockfd);
ac32bf
+	}
ac32bf
+
ac32bf
+	if(done){
ac32bf
+		return 0;
ac32bf
+	}else{
ac32bf
+		return -1;
ac32bf
+	}
ac32bf
+}
ac32bf
+
ac32bf
+int ras_report_mce_event(struct ras_events *ras, struct mce_event *ev){
ac32bf
+	char buf[MAX_MESSAGE_SIZE];
ac32bf
+	int sockfd = 0;
ac32bf
+	int done = 0;
ac32bf
+	int rc = -1;
ac32bf
+
ac32bf
+	memset(buf, 0, sizeof(buf));
ac32bf
+
ac32bf
+	sockfd = setup_report_socket();
ac32bf
+	if(sockfd < 0){
ac32bf
+		return -1;
ac32bf
+	}
ac32bf
+
ac32bf
+	rc = commit_report_basic(sockfd);
ac32bf
+	if(rc < 0){
ac32bf
+		goto mce_fail;
ac32bf
+	}
ac32bf
+
ac32bf
+	rc = commit_report_backtrace(sockfd, MCE_EVENT, ev);
ac32bf
+	if(rc < 0){
ac32bf
+		goto mce_fail;
ac32bf
+	}
ac32bf
+
ac32bf
+	sprintf(buf, "ANALYZER=%s", "rasdaemon-mce");
ac32bf
+	rc = write(sockfd, buf, strlen(buf) + 1);
ac32bf
+	if(rc < strlen(buf) + 1){
ac32bf
+		goto mce_fail;
ac32bf
+	}
ac32bf
+
ac32bf
+	sprintf(buf, "REASON=%s", "Machine Check driver report problem");
ac32bf
+	rc = write(sockfd, buf, strlen(buf) + 1);
ac32bf
+	if(rc < strlen(buf) + 1){
ac32bf
+		goto mce_fail;
ac32bf
+	}
ac32bf
+
ac32bf
+	rc = commit_report_done(sockfd);
ac32bf
+	if(rc < 0){
ac32bf
+		goto mce_fail;
ac32bf
+	}
ac32bf
+
ac32bf
+	done = 1;
ac32bf
+
ac32bf
+mce_fail:
ac32bf
+
ac32bf
+	if(sockfd > 0){
ac32bf
+		close(sockfd);
ac32bf
+	}
ac32bf
+
ac32bf
+	if(done){
ac32bf
+		return 0;
ac32bf
+	}else{
ac32bf
+		return -1;
ac32bf
+	}
ac32bf
+}
ac32bf
diff --git a/ras-report.h b/ras-report.h
ac32bf
new file mode 100644
ac32bf
index 0000000..7920cdf
ac32bf
--- /dev/null
ac32bf
+++ b/ras-report.h
ac32bf
@@ -0,0 +1,39 @@
ac32bf
+#ifndef __RAS_REPORT_H
ac32bf
+#define __RAS_REPORT_H
ac32bf
+
ac32bf
+#include "ras-record.h"
ac32bf
+#include "ras-events.h"
ac32bf
+#include "ras-mc-handler.h"
ac32bf
+#include "ras-mce-handler.h"
ac32bf
+#include "ras-aer-handler.h"
ac32bf
+
ac32bf
+/* Maximal length of backtrace. */
ac32bf
+#define MAX_BACKTRACE_SIZE (1024*1024)
ac32bf
+/* Amount of data received from one client for a message before reporting error. */
ac32bf
+#define MAX_MESSAGE_SIZE (4*MAX_BACKTRACE_SIZE)
ac32bf
+/* Maximal number of characters read from socket at once. */
ac32bf
+#define INPUT_BUFFER_SIZE (8*1024)
ac32bf
+/* ABRT socket file */
ac32bf
+#define ABRT_SOCKET "/var/run/abrt/abrt.socket"
ac32bf
+
ac32bf
+enum {
ac32bf
+	MC_EVENT,
ac32bf
+	MCE_EVENT,
ac32bf
+	AER_EVENT
ac32bf
+};
ac32bf
+
ac32bf
+#ifdef HAVE_ABRT_REPORT
ac32bf
+
ac32bf
+int ras_report_mc_event(struct ras_events *ras, struct ras_mc_event *ev);
ac32bf
+int ras_report_aer_event(struct ras_events *ras, struct ras_aer_event *ev);
ac32bf
+int ras_report_mce_event(struct ras_events *ras, struct mce_event *ev);
ac32bf
+
ac32bf
+#else
ac32bf
+
ac32bf
+static inline int ras_report_mc_event(struct ras_events *ras, struct ras_mc_event *ev) { return 0; };
ac32bf
+static inline int ras_report_aer_event(struct ras_events *ras, struct ras_aer_event *ev) { return 0; };
ac32bf
+static inline int ras_report_mce_event(struct ras_events *ras, struct mce_event *ev) { return 0; };
ac32bf
+
ac32bf
+#endif
ac32bf
+
ac32bf
+#endif
ac32bf
-- 
ac32bf
1.7.1
ac32bf