lldpd_LDADD = @LIBOBJS@
lldpctl_LDADD = @LIBOBJS@
+lldpctl_CFLAGS = -DCLIENT_ONLY
if USE_SNMP
lldpd_SOURCES += agent.c agent_priv.c
{ 0, NULL } };
void
-client_handle_client(struct lldpd *cfg, struct lldpd_client *client,
+client_handle_client(struct lldpd *cfg, struct lldpd_callback *callback,
char *buffer, int n)
{
struct hmsg *h; /* Reception */
t->hdr.len = 0;
t->hdr.type = HMSG_NONE;
}
- if (ctl_msg_send(client->fd, t) == -1)
+ if (ctl_msg_send(callback->fd, t) == -1)
LLOG_WARN("unable to send answer to client %d",
h->hdr.pid);
free(t);
return s;
}
-int
-ctl_accept(struct lldpd *cfg, int c)
+#ifndef CLIENT_ONLY
+static void
+ctl_callback(struct lldpd *cfg, struct lldpd_callback *callback)
+{
+ char *buffer;
+ int n;
+
+ if ((buffer = (char *)malloc(MAX_HMSGSIZE)) ==
+ NULL) {
+ LLOG_WARN("failed to alloc reception buffer");
+ return;
+ }
+ if ((n = recv(callback->fd, buffer,
+ MAX_HMSGSIZE, 0)) == -1) {
+ LLOG_WARN("error while receiving message");
+ free(buffer);
+ return;
+ }
+ if (n > 0)
+ client_handle_client(cfg, callback, buffer, n);
+ else {
+ close(callback->fd);
+ lldpd_callback_del(cfg, callback->fd, ctl_callback);
+ }
+ free(buffer);
+}
+
+void
+ctl_accept(struct lldpd *cfg, struct lldpd_callback *callback)
{
int s;
- struct lldpd_client *lc;
- if ((s = accept(c, NULL, NULL)) == -1) {
+ if ((s = accept(callback->fd, NULL, NULL)) == -1) {
LLOG_WARN("unable to accept connection from socket");
- return -1;
+ return;
}
- if ((lc = (struct lldpd_client *)malloc(sizeof(
- struct lldpd_client))) == NULL) {
- LLOG_WARN("failed to allocate memory for new client");
+ if (lldpd_callback_add(cfg, s, ctl_callback, NULL) != 0) {
+ LLOG_WARN("unable to add callback for new client");
close(s);
- return -1;
}
- lc->fd = s;
- TAILQ_INSERT_TAIL(&cfg->g_clients, lc, next);
- return 1;
+ return;
}
+#endif
void
ctl_msg_init(struct hmsg *t, enum hmsg_type type)
return 1;
}
-int
-ctl_close(struct lldpd *cfg, int c)
-{
- struct lldpd_client *client, *client_next;
- for (client = TAILQ_FIRST(&cfg->g_clients);
- client != NULL;
- client = client_next) {
- client_next = TAILQ_NEXT(client, next);
- if (client->fd == c) {
- close(client->fd);
- TAILQ_REMOVE(&cfg->g_clients, client, next);
- free(client);
- return 1;
- }
- }
- /* Not found */
- return -1;
-}
-
void
ctl_cleanup(char *name)
{
memcpy(&ochassis->c_entries, &entries, sizeof(entries));
}
+int
+lldpd_callback_add(struct lldpd *cfg, int fd, void(*fn)(CALLBACK_SIG), void *data)
+{
+ struct lldpd_callback *callback;
+ if ((callback = (struct lldpd_callback *)
+ malloc(sizeof(struct lldpd_callback))) == NULL)
+ return -1;
+ callback->fd = fd;
+ callback->function = fn;
+ callback->data = data;
+ TAILQ_INSERT_TAIL(&cfg->g_callbacks, callback, next);
+ return 0;
+}
+
+void
+lldpd_callback_del(struct lldpd *cfg, int fd, void(*fn)(CALLBACK_SIG))
+{
+ struct lldpd_callback *callback, *callback_next;
+ for (callback = TAILQ_FIRST(&cfg->g_callbacks);
+ callback;
+ callback = callback_next) {
+ callback_next = TAILQ_NEXT(callback, next);
+ if ((callback->fd == fd) &&
+ (callback->function = fn)) {
+ free(callback->data);
+ TAILQ_REMOVE(&cfg->g_callbacks, callback, next);
+ free(callback);
+ }
+ }
+}
static void
lldpd_recv_all(struct lldpd *cfg)
{
struct lldpd_hardware *hardware;
- struct lldpd_client *client, *client_next;
+ struct lldpd_callback *callback, *callback_next;
fd_set rfds;
struct timeval tv;
#ifdef USE_SNMP
nfds = n;
}
}
- TAILQ_FOREACH(client, &cfg->g_clients, next) {
- FD_SET(client->fd, &rfds);
- if (nfds < client->fd)
- nfds = client->fd;
+ TAILQ_FOREACH(callback, &cfg->g_callbacks, next) {
+ FD_SET(callback->fd, &rfds);
+ if (nfds < callback->fd)
+ nfds = callback->fd;
}
- FD_SET(cfg->g_ctl, &rfds);
- if (nfds < cfg->g_ctl)
- nfds = cfg->g_ctl;
#ifdef USE_SNMP
if (cfg->g_snmp)
free(buffer);
break;
}
- if (FD_ISSET(cfg->g_ctl, &rfds)) {
- if (ctl_accept(cfg, cfg->g_ctl) == -1)
- LLOG_WARN("unable to accept new client");
- }
- for (client = TAILQ_FIRST(&cfg->g_clients);
- client != NULL;
- client = client_next) {
- client_next = TAILQ_NEXT(client, next);
- if (FD_ISSET(client->fd, &rfds)) {
- /* Got a message */
- if ((buffer = (char *)malloc(MAX_HMSGSIZE)) ==
- NULL) {
- LLOG_WARN("failed to alloc reception buffer");
- continue;
- }
- if ((n = recv(client->fd, buffer,
- MAX_HMSGSIZE, 0)) == -1) {
- LLOG_WARN("error while receiving message");
- free(buffer);
- continue;
- }
- if (n > 0)
- client_handle_client(cfg, client, buffer, n);
- else
- ctl_close(cfg, client->fd); /* Will use TAILQ_REMOVE ! */
- free(buffer);
- }
+ for (callback = TAILQ_FIRST(&cfg->g_callbacks);
+ callback;
+ callback = callback_next) {
+ /* Callback function can use TAILQ_REMOVE */
+ callback_next = TAILQ_NEXT(callback, next);
+ if (FD_ISSET(callback->fd, &rfds))
+ callback->function(cfg, callback);
}
#ifdef USE_SNMP
TAILQ_INSERT_TAIL(&cfg->g_chassis, lchassis, c_entries);
lchassis->c_refcount++;
+ TAILQ_INIT(&cfg->g_callbacks);
+
#ifdef USE_SNMP
if (snmp) {
cfg->g_snmp = 1;
/* Create socket */
if ((cfg->g_ctl = priv_ctl_create(cfg)) == -1)
fatalx("unable to create control socket " LLDPD_CTL_SOCKET);
- TAILQ_INIT(&cfg->g_clients);
+ if (lldpd_callback_add(cfg, cfg->g_ctl, ctl_accept, NULL) != 0)
+ fatalx("unable to add callback for control socket");
gcfg = cfg;
if (atexit(lldpd_exit) != 0) {
};
#define STRUCT_LLDPD_INTERFACE "(Ls)"
-struct lldpd_client {
- TAILQ_ENTRY(lldpd_client) next;
- int fd;
-};
-
#define PROTO_SEND_SIG struct lldpd *, struct lldpd_hardware *
#define PROTO_DECODE_SIG struct lldpd *, char *, int, struct lldpd_hardware *, struct lldpd_chassis **, struct lldpd_port **
#define PROTO_GUESS_SIG char *, int
size_t filterlen; /* Size of BPF filter */
};
+#define CALLBACK_SIG struct lldpd*, struct lldpd_callback*
+struct lldpd_callback {
+ TAILQ_ENTRY(lldpd_callback) next;
+ int fd; /* FD that will trigger this callback */
+ void(*function)(CALLBACK_SIG); /* Function called */
+ void *data; /* Optional data for this callback*/
+};
+
struct lldpd {
int g_sock;
int g_delay;
/* Unix socket handling */
int g_ctl;
- TAILQ_HEAD(, lldpd_client) g_clients;
+
+ TAILQ_HEAD(, lldpd_callback) g_callbacks;
char *g_mgmt_pattern;
void lldpd_remote_cleanup(struct lldpd *, struct lldpd_hardware *, int);
void lldpd_port_cleanup(struct lldpd_port *, int);
void lldpd_chassis_cleanup(struct lldpd_chassis *, int);
+int lldpd_callback_add(struct lldpd *, int, void(*fn)(CALLBACK_SIG), void *);
+void lldpd_callback_del(struct lldpd *, int, void(*fn)(CALLBACK_SIG));
/* lldp.c */
int lldp_send(PROTO_SEND_SIG);
int ctl_create(char *);
int ctl_connect(char *);
void ctl_cleanup(char *);
-int ctl_accept(struct lldpd *, int);
-int ctl_close(struct lldpd *, int);
+#ifndef CLIENT_ONLY
+void ctl_accept(struct lldpd *, struct lldpd_callback *);
+#endif
void ctl_msg_init(struct hmsg *, enum hmsg_type);
int ctl_msg_send(int, struct hmsg *);
int ctl_msg_recv(int, struct hmsg *);
void (*handle)(struct lldpd*, struct hmsg*, struct hmsg*);
};
-void client_handle_client(struct lldpd *, struct lldpd_client *,
- char *, int);
+void client_handle_client(struct lldpd *, struct lldpd_callback *,
+ char *, int);
void client_handle_none(struct lldpd *, struct hmsg *,
struct hmsg *);
void client_handle_get_interfaces(struct lldpd *, struct hmsg *,