diff --git a/include/libvirt/libvirt.h b/include/libvirt/libvirt.h
index 35b80d0..53ad6b7 100644
--- a/include/libvirt/libvirt.h
+++ b/include/libvirt/libvirt.h
@@ -993,6 +993,65 @@ char *                  virStorageVolGetPath            (virStorageVolPtr vol);
 virDomainPtr            virDomainCreateLinux    (virConnectPtr conn,
                                                  const char *xmlDesc,
                                                  unsigned int flags);
+
+/*
+ * Domain Event Notification
+ */
+
+typedef enum {
+      VIR_DOMAIN_EVENT_ADDED,
+      VIR_DOMAIN_EVENT_REMOVED,
+      VIR_DOMAIN_EVENT_STARTED,
+      VIR_DOMAIN_EVENT_SUSPENDED,
+      VIR_DOMAIN_EVENT_RESUMED,
+      VIR_DOMAIN_EVENT_STOPPED,
+      VIR_DOMAIN_EVENT_SAVED,
+      VIR_DOMAIN_EVENT_RESTORED,
+} virDomainEventType;
+
+typedef int (*virConnectDomainEventCallback)(virConnectPtr conn,
+                                             virDomainPtr dom,
+                                             int event,
+                                             void *opaque);
+
+int virConnectDomainEventRegister(virConnectPtr conn,
+                                  virConnectDomainEventCallback cb,
+                                  void *opaque);
+
+int virConnectDomainEventDeregister(virConnectPtr conn,
+                                    virConnectDomainEventCallback cb);
+
+/**
+ * virEventHandleCallback: callback for receiving file handle events
+ *
+ * @fd: file handle on which the event occurred
+ * @events: bitset of events from POLLnnn constants
+ * @opaque: user data registered with handle
+ */
+typedef void (*virEventHandleCallback)(int fd, int events, void *opaque);
+
+typedef int (*virEventAddHandleFunc)(int, int, virEventHandleCallback, void *);
+typedef void (*virEventUpdateHandleFunc)(int, int);
+typedef int (*virEventRemoveHandleFunc)(int);
+
+/**
+ * virEventTimeoutCallback: callback for receiving timer events
+ *
+ * @timer: timer id emitting the event
+ * @opaque: user data registered with handle
+ */
+typedef void (*virEventTimeoutCallback)(int timer, void *opaque);
+
+typedef int (*virEventAddTimeoutFunc)(int, virEventTimeoutCallback, void *);
+typedef void (*virEventUpdateTimeoutFunc)(int, int);
+typedef int (*virEventRemoveTimeoutFunc)(int);
+
+void virEventRegisterImpl(virEventAddHandleFunc addHandle,
+                          virEventUpdateHandleFunc updateHandle,
+                          virEventRemoveHandleFunc removeHandle,
+                          virEventAddTimeoutFunc addTimeout,
+                          virEventUpdateTimeoutFunc updateTimeout,
+                          virEventRemoveTimeoutFunc removeTimeout);
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 3624367..6af5329 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -993,6 +993,65 @@ char *                  virStorageVolGetPath            (virStorageVolPtr vol);
 virDomainPtr            virDomainCreateLinux    (virConnectPtr conn,
                                                  const char *xmlDesc,
                                                  unsigned int flags);
+
+/*
+ * Domain Event Notification
+ */
+
+typedef enum {
+      VIR_DOMAIN_EVENT_ADDED,
+      VIR_DOMAIN_EVENT_REMOVED,
+      VIR_DOMAIN_EVENT_STARTED,
+      VIR_DOMAIN_EVENT_SUSPENDED,
+      VIR_DOMAIN_EVENT_RESUMED,
+      VIR_DOMAIN_EVENT_STOPPED,
+      VIR_DOMAIN_EVENT_SAVED,
+      VIR_DOMAIN_EVENT_RESTORED,
+} virDomainEventType;
+
+typedef int (*virConnectDomainEventCallback)(virConnectPtr conn,
+                                             virDomainPtr dom,
+                                             int event,
+                                             void *opaque);
+
+int virConnectDomainEventRegister(virConnectPtr conn,
+                                  virConnectDomainEventCallback cb,
+                                  void *opaque);
+
+int virConnectDomainEventDeregister(virConnectPtr conn,
+                                    virConnectDomainEventCallback cb);
+
+/**
+ * virEventHandleCallback: callback for receiving file handle events
+ *
+ * @fd: file handle on which the event occurred
+ * @events: bitset of events from POLLnnn constants
+ * @opaque: user data registered with handle
+ */
+typedef void (*virEventHandleCallback)(int fd, int events, void *opaque);
+
+typedef int (*virEventAddHandleFunc)(int, int, virEventHandleCallback, void *);
+typedef void (*virEventUpdateHandleFunc)(int, int);
+typedef int (*virEventRemoveHandleFunc)(int);
+
+/**
+ * virEventTimeoutCallback: callback for receiving timer events
+ *
+ * @timer: timer id emitting the event
+ * @opaque: user data registered with handle
+ */
+typedef void (*virEventTimeoutCallback)(int timer, void *opaque);
+
+typedef int (*virEventAddTimeoutFunc)(int, virEventTimeoutCallback, void *);
+typedef void (*virEventUpdateTimeoutFunc)(int, int);
+typedef int (*virEventRemoveTimeoutFunc)(int);
+
+void virEventRegisterImpl(virEventAddHandleFunc addHandle,
+                          virEventUpdateHandleFunc updateHandle,
+                          virEventRemoveHandleFunc removeHandle,
+                          virEventAddTimeoutFunc addTimeout,
+                          virEventUpdateTimeoutFunc updateTimeout,
+                          virEventRemoveTimeoutFunc removeTimeout);
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/libvirt.c b/src/libvirt.c
index ca2675a..33df94e 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -5345,3 +5345,259 @@ void virStringListFree(virStringList *list)
         list = p;
     }
 }
+
+/*
+ * Domain Event Notification
+ */
+
+/**
+ * virDomainEventCallbackListFree:
+ * @list: event callback list head
+ *
+ * Free the memory in the domain event callback list
+ */
+void virDomainEventCallbackListFree(virDomainEventCallbackListPtr list)
+{
+    int i;
+    for(i=0; i<list->count;i++) {
+        VIR_FREE(list->callbacks[i]);
+    }
+    VIR_FREE(list);
+}
+
+/**
+ * virConnectDomainEventRegister:
+ * @conn: pointer to the connection
+ * @cb: callback to the function handling domain events
+ * @opaque: opaque data to pass on to the callback
+ *
+ * Adds a Domain Event Callback
+ *
+ * Returns 0 on success, -1 on failure
+ */
+int virConnectDomainEventRegister(virConnectPtr conn,
+                                  virConnectDomainEventCallback cb,
+                                  void *opaque)
+{
+    /* Registering for a domain callback will enable delivery by default */
+    if (conn->driver && conn->driver->domainEventRegister)
+        return conn->driver->domainEventRegister (conn, cb, opaque);
+    return -1;
+}
+
+/**
+ * virConnectDomainEventDeregister:
+ * @conn: pointer to the connection
+ * @cb: callback to the function handling domain events
+ *
+ * Removes a Domain Event Callback
+ *
+ * Returns 0 on success, -1 on failure
+ */
+int virConnectDomainEventDeregister(virConnectPtr conn, virConnectDomainEventCallback cb)
+{
+    /* De-registering for a domain callback will disable delivery of this event type*/
+    if (conn->driver && conn->driver->domainEventDeregister)
+        return conn->driver->domainEventDeregister (conn, cb);
+
+    return -1;
+}
+
+/**
+ * virDispatchDomainEvent:
+ * @dom: the domain
+ * @event: the domain event code
+ *
+ * Internal function by which drivers to dispatch domain events.
+ */
+void virDispatchDomainEvent(virDomainPtr dom,
+                            int event)
+{
+    if (dom->conn && dom->conn->driver &&
+        dom->conn->driver->domainEventDispatch)
+        dom->conn->driver->domainEventDispatch(dom, event);
+}
+
+/**
+ * virDomainEventCallbackListRemove:
+ * @cbList: the list
+ * @callback: the callback to remove
+ *
+ * Internal function to remove a callback from a virDomainEventCallbackListPtr
+ */
+int __virDomainEventCallbackListRemove(virConnectPtr conn,
+                                       virDomainEventCallbackListPtr cbList,
+                                       virConnectDomainEventCallback callback)
+{
+    int i;
+    for (i = 0 ; i < cbList->count ; i++) {
+        if(cbList->callbacks[i]->cb == callback &&
+           cbList->callbacks[i]->conn == conn) {
+            virUnrefConnect(cbList->callbacks[i]->conn);
+            VIR_FREE(cbList->callbacks[i]);
+
+            if (i < (cbList->count - 1))
+                memmove(cbList->callbacks + i,
+                        cbList->callbacks + i + 1,
+                        sizeof(*(cbList->callbacks)) *
+                                (cbList->count - (i + 1)));
+
+            if (VIR_REALLOC_N(cbList->callbacks,
+                              cbList->count - 1) < 0) {
+                ; /* Failure to reduce memory allocation isn't fatal */
+            }
+            cbList->count--;
+
+            return 0;
+        }
+    }
+    return -1;
+}
+
+/**
+ * virDomainEventCallbackListAdd:
+ * @cbList: the list
+ * @callback: the callback to add
+ * @opaque: opaque data tio pass to callback
+ *
+ * Internal function to add a callback from a virDomainEventCallbackListPtr
+ */
+int __virDomainEventCallbackListAdd(virConnectPtr conn,
+                                    virDomainEventCallbackListPtr cbList,
+                                    virConnectDomainEventCallback callback,
+                                    void *opaque)
+{
+    virDomainEventCallbackPtr event;
+    int n;
+
+    /* Check incoming */
+    if ( !cbList ) {
+        return -1;
+    }
+
+    /* check if we already have this callback on our list */
+    for( n=0; n < cbList->count; n++ )
+    {
+        if(cbList->callbacks[n]->cb == callback &&
+           conn == cbList->callbacks[n]->conn) {
+            DEBUG0("WARNING: Callback already tracked");
+            return -1;
+        }
+    }
+    /* Allocate new event */
+    if (VIR_ALLOC(event) < 0) {
+        DEBUG0("Error allocating event");
+        return -1;
+    }
+    event->conn = conn;
+    event->cb = callback;
+    event->opaque = opaque;
+
+    /* Make space on list */
+    n = cbList->count;
+    if (VIR_REALLOC_N(cbList->callbacks,
+                      n + 1) < 0) {
+        DEBUG0("Error reallocating list");
+        VIR_FREE(event);
+        return -1;
+    }
+
+    event->conn->refs++;
+
+    cbList->callbacks[n] = event;
+    cbList->count++;
+    return 0;
+}
+
+/**
+ * virDomainEventQueueFree:
+ * @queue: fron of queue
+ *
+ * Free the memory in the queue. We process this like a list here
+ */
+void virDomainEventQueueFree(virDomainEventQueuePtr queue)
+{
+    int i;
+    for(i=0; i<queue->count;i++) {
+        VIR_FREE(queue->events[i]);
+    }
+    VIR_FREE(queue);
+}
+
+/**
+ * virDomainEventCallbackQueuePop:
+ * @evtQueue: the queue of events
+ *
+ * Internal function to pop off, and return the front of the queue
+ * NOTE: The caller is responsible for freeing the returned object
+ *
+ * Returns: virDomainEventPtr on success NULL on failure.
+ */
+virDomainEventPtr virDomainEventCallbackQueuePop(virDomainEventQueuePtr evtQueue)
+{
+    virDomainEventPtr ret;
+
+    if(!evtQueue || evtQueue->count == 0 )
+        return NULL;
+
+    ret = evtQueue->events[0];
+
+    memmove(evtQueue->events,
+            evtQueue->events + 1,
+            sizeof(*(evtQueue->events)) *
+                    (evtQueue->count - 1));
+
+    if (VIR_REALLOC_N(evtQueue->events,
+                        evtQueue->count - 1) < 0) {
+        ; /* Failure to reduce memory allocation isn't fatal */
+    }
+    evtQueue->count--;
+
+    return ret;
+}
+
+/**
+ * virDomainEventCallbackQueuePush:
+ * @evtQueue: the dom event queue
+ * @dom: the domain to add
+ * @event: the event to add
+ *
+ * Internal function to push onto the back of an virDomainEventQueue
+ *
+ * Returns: 0 on success, -1 on failure
+ */
+int virDomainEventCallbackQueuePush(virDomainEventQueuePtr evtQueue,
+                                  virDomainPtr dom,
+                                  virDomainEventType event,
+                                  virConnectDomainEventCallback cb,
+                                  void *opaque)
+{
+    virDomainEventPtr domEvent;
+
+    /* Check incoming */
+    if ( !evtQueue ) {
+        return -1;
+    }
+
+    /* Allocate new event */
+    if (VIR_ALLOC(domEvent) < 0) {
+        DEBUG0("Error allocating event");
+        return -1;
+    }
+    domEvent->dom = dom;
+    domEvent->event = event;
+    domEvent->cb = cb;
+    domEvent->opaque = opaque;
+
+    /* Make space on queue */
+    if (VIR_REALLOC_N(evtQueue->events,
+                      evtQueue->count + 1) < 0) {
+        DEBUG0("Error reallocating queue");
+        VIR_FREE(domEvent);
+        return -1;
+    }
+
+    evtQueue->events[evtQueue->count] = domEvent;
+    evtQueue->count++;
+    return 0;
+}
diff --git a/src/libvirt_sym.version b/src/libvirt_sym.version
index 3cc4505..5776cf9 100644
--- a/src/libvirt_sym.version
+++ b/src/libvirt_sym.version
@@ -147,6 +147,10 @@
 	virStorageVolGetXMLDesc;
 	virStorageVolGetPath;
 
+        virEventRegisterImpl;
+        virConnectDomainEventRegister;
+        virConnectDomainEventDeregister;
+
         /* Symbols with __ are private only
            for use by the libvirtd daemon.
            They are not part of stable ABI
@@ -167,8 +171,6 @@
 	__virGetStoragePool;
 	__virGetStorageVol;
 
-	__virEventRegisterImpl;
-
 	__virStateInitialize;
 	__virStateCleanup;
 	__virStateReload;
@@ -198,5 +200,8 @@
         __virReallocN;
         __virFree;
 
+        __virDomainEventCallbackListFree;
+        __virDomainEventCallbackListAdd;
+        __virDomainEventCallbackListRemove;
     local: *;
 };


