.Sh SYNOPSIS
.Nm
.Op Fl dv
+.Op Fl u Ar file
.Op Fl f Ar format
.Op Fl c Ar file
.Op Ar command ...
.Nm lldpctl
.Op Fl dv
+.Op Fl u Ar file
.Op Fl f Ar format
.Op Ar interfaces ...
.Sh DESCRIPTION
.Bl -tag -width Ds
.It Fl d
Enable more debugging information.
+.It Fl u
+Specify the Unix-domain socket used for communication with
+.Xr lldpd 8 .
.It Fl v
Show
.Nm
fprintf(stderr, "\n");
fprintf(stderr, "-d Enable more debugging information.\n");
+ fprintf(stderr, "-u Specify the Unix-domain socket used for communication with lldpd(8).\n");
fprintf(stderr, "-f format Choose output format (plain, keyvalue or xml).\n");
if (!is_lldpctl(NULL))
fprintf(stderr, "-c Read the provided configuration file.\n");
lldpctl_conn_t *conn = NULL;
const char *options = is_lldpctl(argv[0])?"hdvf:":"hdsvf:c:";
+ const char *ctlname = lldpctl_get_default_transport();
int gotinputs = 0;
struct inputs inputs;
TAILQ_INIT(&inputs);
case 'h':
usage();
break;
+ case 'u':
+ ctlname = optarg;
+ break;
case 'v':
fprintf(stdout, "%s\n", PACKAGE_VERSION);
exit(0);
/* Make a connection */
log_debug("lldpctl", "connect to lldpd");
- conn = lldpctl_new(NULL, NULL, NULL);
+ conn = lldpctl_new_name(ctlname, NULL, NULL, NULL);
if (conn == NULL) goto end;
/* Process file inputs */
* @return The socket when successful, -1 otherwise.
*/
int
-ctl_create(char *name)
+ctl_create(const char *name)
{
int s;
struct sockaddr_un su;
* @return The socket when successful, -1 otherwise.
*/
int
-ctl_connect(char *name)
+ctl_connect(const char *name)
{
int s;
struct sockaddr_un su;
* @param name The name of the Unix socket.
*/
void
-ctl_cleanup(char *name)
+ctl_cleanup(const char *name)
{
log_debug("control", "cleanup control socket");
if (unlink(name) == -1)
#define HMSG_MAX_SIZE (1<<19)
/* ctl.c */
-int ctl_create(char *);
-int ctl_connect(char *);
-void ctl_cleanup(char *);
+int ctl_create(const char *);
+int ctl_connect(const char *);
+void ctl_cleanup(const char *);
int ctl_msg_send_unserialized(uint8_t **, size_t *,
enum hmsg_type,
.Op Fl P Ar platform
.Op Fl X Ar socket
.Op Fl m Ar management
+.Op Fl u Ar file
.Op Fl I Ar interfaces
.Op Fl C Ar interfaces
.Op Fl M Ar class
addresses are chosen. Otherwise, many of them can be selected. If you
want to blacklist IPv6 addresses, you can use
.Em !*:* .
+.It Fl u Ar file
+Specify the Unix-domain socket used for communication with
+.Xr lldpctl 8 .
.It Fl I Ar interfaces
Specify which interface to listen to. Without this option,
.Nm
fprintf(stderr, "-S descr Override the default system description.\n");
fprintf(stderr, "-P name Override the default hardware platform.\n");
fprintf(stderr, "-m IP Specify the IPv4 management addresses of this system.\n");
+ fprintf(stderr, "-u file Specify the Unix-domain socket used for communication with lldpctl(8).\n");
fprintf(stderr, "-H mode Specify the behaviour when detecting multiple neighbors.\n");
fprintf(stderr, "-I iface Limit interfaces to use.\n");
#ifdef ENABLE_LLDPMED
struct lldpd_hardware *hardware, *hardware_next;
log_debug("main", "exit lldpd");
close(cfg->g_ctl);
- priv_ctl_cleanup();
+ priv_ctl_cleanup(cfg->g_ctlname);
log_debug("main", "cleanup hardware information");
for (hardware = TAILQ_FIRST(&cfg->g_hardware); hardware != NULL;
hardware = hardware_next) {
int snmp = 0;
char *agentx = NULL; /* AgentX socket */
#endif
+ char *ctlname = LLDPD_CTL_SOCKET;
char *mgmtp = NULL;
char *cidp = NULL;
char *interfaces = NULL;
char *popt, opts[] =
- "H:vhkrdD:xX:m:4:6:I:C:p:M:P:S:iL:@ ";
+ "H:vhkrdD:xX:m:u:4:6:I:C:p:M:P:S:iL:@ ";
int i, found, advertise_version = 1;
#ifdef ENABLE_LLDPMED
int lldpmed = 0, noinventory = 0;
case 'm':
mgmtp = optarg;
break;
+ case 'u':
+ ctlname = optarg;
+ break;
case 'I':
interfaces = optarg;
break;
/* Create and setup socket */
int retry = 1;
log_debug("main", "creating control socket");
- while ((ctl = ctl_create(LLDPD_CTL_SOCKET)) == -1) {
+ while ((ctl = ctl_create(ctlname)) == -1) {
if (retry-- && errno == EADDRINUSE) {
/* Check if a daemon is really listening */
int tfd;
log_info("main", "unable to create control socket because it already exists");
log_info("main", "check if another instance is running");
- if ((tfd = ctl_connect(LLDPD_CTL_SOCKET)) != -1) {
+ if ((tfd = ctl_connect(ctlname)) != -1) {
/* Another instance is running */
close(tfd);
log_warnx("main", "another instance is running, please stop it");
} else if (errno == ECONNREFUSED) {
/* Nobody is listening */
log_info("main", "old control socket is present, clean it");
- ctl_cleanup(LLDPD_CTL_SOCKET);
+ ctl_cleanup(ctlname);
continue;
}
log_warn("main", "cannot determine if another daemon is already running");
log_warn("main", "unable to create control socket");
fatalx("giving up");
}
- if (chown(LLDPD_CTL_SOCKET, uid, gid) == -1)
+ if (chown(ctlname, uid, gid) == -1)
log_warn("main", "unable to chown control socket");
- if (chmod(LLDPD_CTL_SOCKET,
+ if (chmod(ctlname,
S_IRUSR | S_IWUSR | S_IXUSR |
S_IRGRP | S_IWGRP | S_IXGRP) == -1)
log_warn("main", "unable to chmod control socket");
calloc(1, sizeof(struct lldpd))) == NULL)
fatal("main", NULL);
+ cfg->g_ctlname = ctlname;
cfg->g_ctl = ctl;
cfg->g_config.c_mgmt_pattern = mgmtp;
cfg->g_config.c_cid_pattern = cidp;
#endif /* USE_SNMP */
/* Unix socket handling */
+ const char *g_ctlname;
int g_ctl;
struct event *g_ctl_event;
struct event *g_iface_event; /* Triggered when there is an interface change */
/* priv.c */
void priv_init(const char*, int, uid_t, gid_t);
-void priv_ctl_cleanup(void);
+void priv_ctl_cleanup(const char *ctlname);
char *priv_gethostbyname(void);
#ifdef HOST_OS_LINUX
int priv_open(char*);
/* Proxy for ctl_cleanup */
void
-priv_ctl_cleanup()
+priv_ctl_cleanup(const char *ctlname)
{
int cmd, rc;
+ int len = strlen(ctlname);
cmd = PRIV_DELETE_CTL_SOCKET;
must_write(remote, &cmd, sizeof(int));
+ must_write(remote, &len, sizeof(int));
+ must_write(remote, ctlname, len);
must_read(remote, &rc, sizeof(int));
}
static void
asroot_ctl_cleanup()
{
+ int len;
+ char *ctlname;
int rc = 0;
- ctl_cleanup(LLDPD_CTL_SOCKET);
+
+ must_read(remote, &len, sizeof(int));
+ if ((ctlname = (char*)malloc(len+1)) == NULL)
+ fatal("ctlname", NULL);
+
+ must_read(remote, ctlname, len);
+ ctlname[len] = 0;
+
+ ctl_cleanup(ctlname);
/* Ack */
must_write(remote, &rc, sizeof(int));
/* Connect to the remote end */
static int
-sync_connect()
+sync_connect(lldpctl_conn_t *lldpctl)
{
- return ctl_connect(LLDPD_CTL_SOCKET);
+ return ctl_connect(lldpctl->ctlname);
}
/* Synchronously send data to remote end. */
size_t nb;
if (conn->fd == -1 &&
- ((conn->fd = sync_connect()) == -1)) {
+ ((conn->fd = sync_connect(lldpctl)) == -1)) {
return LLDPCTL_ERR_CANNOT_CONNECT;
}
size_t nb;
if (conn->fd == -1 &&
- ((conn->fd = sync_connect()) == -1)) {
+ ((conn->fd = sync_connect(lldpctl)) == -1)) {
lldpctl->error = LLDPCTL_ERR_CANNOT_CONNECT;
return LLDPCTL_ERR_CANNOT_CONNECT;
}
}
-
lldpctl_conn_t*
lldpctl_new(lldpctl_send_callback send, lldpctl_recv_callback recv, void *user_data)
+{
+ return lldpctl_new_name(lldpctl_get_default_transport(), send, recv, user_data);
+}
+
+lldpctl_conn_t*
+lldpctl_new_name(const char *ctlname, lldpctl_send_callback send, lldpctl_recv_callback recv, void *user_data)
{
lldpctl_conn_t *conn = NULL;
struct lldpctl_conn_sync_t *data = NULL;
if ((conn = calloc(1, sizeof(lldpctl_conn_t))) == NULL)
return NULL;
+ conn->ctlname = strdup(ctlname);
+ if (conn->ctlname == NULL) {
+ free(conn);
+ return NULL;
+ }
if (!send && !recv) {
if ((data = malloc(sizeof(struct lldpctl_conn_sync_t))) == NULL) {
free(conn);
lldpctl_release(lldpctl_conn_t *conn)
{
if (conn == NULL) return 0;
+ free(conn->ctlname);
if (conn->send == sync_send) {
struct lldpctl_conn_sync_t *data = conn->user_data;
if (data->fd != -1) close(data->fd);
lldpctl_conn_t *lldpctl_new(lldpctl_send_callback send,
lldpctl_recv_callback recv, void *user_data);
+/**
+ * Allocate a new handler for connecting to lldpd.
+ *
+ * @param ctlname the Unix-domain socket to connect to lldpd.
+ * @param send Callback to be used when sending new data is requested.
+ * @param recv Callback to be used when receiving new data is requested.
+ * @param user_data Data to pass to callbacks.
+ * @return An handler to be used to connect to lldpd or @c NULL in
+ * case of error. In the later case, the error is probable an
+ * out of memory condition.
+ *
+ * The allocated handler can be released with @c lldpctl_release(). If the
+ * provided parameters are both @c NULL, default synchronous callbacks will be
+ * used.
+ */
+lldpctl_conn_t *lldpctl_new_name(const char *ctlname, lldpctl_send_callback send,
+ lldpctl_recv_callback recv, void *user_data);
+
/**
* Release resources associated with a connection to lldpd.
*
/* connection.c */
struct lldpctl_conn_t {
+ /* the Unix-domain socket to connect to lldpd */
+ const char *ctlname;
+
/* Callback handling */
lldpctl_recv_callback recv; /* Receive callback */
lldpctl_send_callback send; /* Send callback */