#include <arpa/inet.h>
#include <assert.h>
#include <fcntl.h>
#include <libdlpi.h>
#include <libnwam.h>
#include <net/if.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/fcntl.h>
#include <unistd.h>
#include "events.h"
#include "ncp.h"
#include "ncu.h"
#include "objects.h"
#include "util.h"
static void
nwamd_dlpi_notify(dlpi_handle_t dhp, dlpi_notifyinfo_t *info, void *arg)
{
nwamd_event_t ev;
char *name = arg;
if (info->dni_note & DL_NOTE_LINK_UP)
ev = nwamd_event_init_link_state(name, B_TRUE);
else
ev = nwamd_event_init_link_state(name, B_FALSE);
if (ev != NULL)
nwamd_event_enqueue(ev);
}
static void *
nwamd_dlpi_thread(void *arg)
{
int rc;
dlpi_handle_t *dh = arg;
do {
rc = dlpi_recv(*dh, NULL, NULL, NULL, NULL, -1, NULL);
} while (rc == DLPI_SUCCESS);
nlog(LOG_ERR, "dlpi_recv failed: %s", dlpi_strerror(rc));
return (NULL);
}
void
nwamd_dlpi_add_link(nwamd_object_t obj)
{
nwamd_ncu_t *ncu = obj->nwamd_object_data;
nwamd_link_t *link;
dlpi_notifyid_t id;
int rc;
nlog(LOG_DEBUG, "nwamd_dlpi_add_link: ncu %p (%s) type %d",
ncu, obj->nwamd_object_name, ncu != NULL ? ncu->ncu_type : -1);
assert(ncu != NULL && ncu->ncu_type == NWAM_NCU_TYPE_LINK);
link = &ncu->ncu_link;
if (link->nwamd_link_dlpi_thread != 0) {
nlog(LOG_DEBUG, "nwamd_dlpi_add_link(%s) already running",
obj->nwamd_object_name);
return;
}
rc = dlpi_open(ncu->ncu_name, &link->nwamd_link_dhp, 0);
if (rc != DLPI_SUCCESS) {
nlog(LOG_ERR, "nwamd_dlpi_add_link: dlpi_open(%s) = %s",
ncu->ncu_name, dlpi_strerror(rc));
return;
}
nwamd_set_unset_link_properties(ncu, B_TRUE);
rc = dlpi_enabnotify(link->nwamd_link_dhp,
DL_NOTE_LINK_UP | DL_NOTE_LINK_DOWN, nwamd_dlpi_notify,
ncu->ncu_name, &id);
if (rc != DLPI_SUCCESS) {
nlog(LOG_ERR,
"nwamd_dlpi_add_link: dlpi_enabnotify(%s) = %s",
obj->nwamd_object_name, dlpi_strerror(rc));
dlpi_close(link->nwamd_link_dhp);
return;
}
rc = pthread_create(&link->nwamd_link_dlpi_thread, NULL,
nwamd_dlpi_thread, &link->nwamd_link_dhp);
if (rc != 0) {
nlog(LOG_ERR, "nwamd_dlpi_add_link: couldn't create "
"dlpi thread for %s: %s", obj->nwamd_object_name,
strerror(rc));
dlpi_close(link->nwamd_link_dhp);
}
}
void
nwamd_dlpi_delete_link(nwamd_object_t obj)
{
nwamd_ncu_t *ncu = obj->nwamd_object_data;
nlog(LOG_DEBUG, "nwamd_dlpi_delete_link: ncu %p (%s) type %d",
ncu, obj->nwamd_object_name, ncu != NULL ? ncu->ncu_type : -1);
if (ncu->ncu_link.nwamd_link_dlpi_thread != 0) {
(void) pthread_cancel(
ncu->ncu_link.nwamd_link_dlpi_thread);
(void) pthread_join(ncu->ncu_link.nwamd_link_dlpi_thread, NULL);
ncu->ncu_link.nwamd_link_dlpi_thread = 0;
nwamd_set_unset_link_properties(ncu, B_FALSE);
}
dlpi_close(ncu->ncu_link.nwamd_link_dhp);
ncu->ncu_link.nwamd_link_dhp = NULL;
}