From: Vincent Bernat Date: Fri, 24 Apr 2020 17:29:36 +0000 (+0200) Subject: lib: introduce lldpctl_watch_callback2() X-Git-Tag: 1.0.6~20^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F388%2Fhead;p=thirdparty%2Flldpd.git lib: introduce lldpctl_watch_callback2() This is similar to `lldpctl_watch_callback()` (which is getting deprecated), except the callback won't receive the current connection. This prevents a user to use the connection which is unusable because it is now dedicated to watch events. Minor ABI dump due to new function, but everything is backward-compatible, except you may now get an error if you use the connection while watching (but this was already not supported). Fix #380 --- diff --git a/NEWS b/NEWS index f9860917..2f3bc551 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,9 @@ lldpd (1.0.6) * Fix: + Do not loose chassis local information when interface status changes. + * Changes: + + Deprecate use of lldpctl_watch_callback(). Use + lldpctl_watch_callback2() instead. lldpd (1.0.5) * Changes: diff --git a/src/client/display.c b/src/client/display.c index faaa8b15..5dd914c3 100644 --- a/src/client/display.c +++ b/src/client/display.c @@ -714,7 +714,7 @@ display_interface(lldpctl_conn_t *conn, struct writer *w, int hidden, display_chassis(w, chassis, details); display_port(w, port, details); - if (details && local) + if (details && local && conn) display_local_ttl(w, conn, details); if (details == DISPLAY_DETAILS) { display_vlans(w, port); diff --git a/src/client/show.c b/src/client/show.c index 8ba8acb4..139a3cb3 100644 --- a/src/client/show.c +++ b/src/client/show.c @@ -154,8 +154,7 @@ struct watcharg { * Callback for the next function to display a new neighbor. */ static void -watchcb(lldpctl_conn_t *conn, - lldpctl_change_t type, +watchcb(lldpctl_change_t type, lldpctl_atom_t *interface, lldpctl_atom_t *neighbor, void *data) @@ -201,7 +200,7 @@ watchcb(lldpctl_conn_t *conn, break; default: return; } - display_interface(conn, w, 1, interface, neighbor, + display_interface(NULL, w, 1, interface, neighbor, cmdenv_get(env, "summary")?DISPLAY_BRIEF: cmdenv_get(env, "detailed")?DISPLAY_DETAILS: DISPLAY_NORMAL, protocol); @@ -234,7 +233,7 @@ cmd_watch_neighbors(struct lldpctl_conn_t *conn, struct writer *w, } log_debug("lldpctl", "watch for neighbor changes"); - if (lldpctl_watch_callback(conn, watchcb, &wa) < 0) { + if (lldpctl_watch_callback2(conn, watchcb, &wa) < 0) { log_warnx("lldpctl", "unable to watch for neighbors. %s", lldpctl_last_strerror(conn)); return 0; diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 2a5cdb3e..f9810392 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -54,7 +54,7 @@ CLEANFILES = atom-glue.c # -version-number could be computed from -version-info, mostly major # is `current` - `age`, minor is `age` and revision is `revision' and # major.minor should be used when updaing lldpctl.map. -liblldpctl_la_LDFLAGS = $(AM_LDFLAGS) -version-info 12:0:8 +liblldpctl_la_LDFLAGS = $(AM_LDFLAGS) -version-info 13:0:9 liblldpctl_la_DEPENDENCIES = libfixedpoint.la if HAVE_LD_VERSION_SCRIPT diff --git a/src/lib/atom.c b/src/lib/atom.c index 54e94ae6..39ea5f87 100644 --- a/src/lib/atom.c +++ b/src/lib/atom.c @@ -380,6 +380,26 @@ lldpctl_watch_callback(lldpctl_conn_t *conn, return rc; } +int +lldpctl_watch_callback2(lldpctl_conn_t *conn, + lldpctl_change_callback2 cb, + void *data) +{ + int rc; + + RESET_ERROR(conn); + + rc = _lldpctl_do_something(conn, + CONN_STATE_SET_WATCH_SEND, CONN_STATE_SET_WATCH_RECV, NULL, + SUBSCRIBE, NULL, NULL, NULL, NULL); + if (rc == 0) { + conn->watch_cb2 = cb; + conn->watch_data = data; + conn->state = CONN_STATE_WATCHING; + } + return rc; +} + int lldpctl_watch(lldpctl_conn_t *conn) { diff --git a/src/lib/atom.h b/src/lib/atom.h index d6ae218f..0b1d4bc0 100644 --- a/src/lib/atom.h +++ b/src/lib/atom.h @@ -65,6 +65,7 @@ struct lldpctl_conn_t { /* Handling notifications */ lldpctl_change_callback watch_cb; + lldpctl_change_callback2 watch_cb2; void *watch_data; int watch_triggered; }; diff --git a/src/lib/connection.c b/src/lib/connection.c index 191d7c6a..03107440 100644 --- a/src/lib/connection.c +++ b/src/lib/connection.c @@ -196,7 +196,7 @@ check_for_notification(lldpctl_conn_t *conn) change = p; /* We have a notification, call the callback */ - if (conn->watch_cb) { + if (conn->watch_cb || conn->watch_cb2) { switch (change->state) { case NEIGHBOR_CHANGE_DELETED: type = lldpctl_c_deleted; break; case NEIGHBOR_CHANGE_ADDED: type = lldpctl_c_added; break; @@ -212,7 +212,10 @@ check_for_notification(lldpctl_conn_t *conn) neighbor = _lldpctl_new_atom(conn, atom_port, 0, NULL, change->neighbor, NULL); if (neighbor == NULL) goto end; - conn->watch_cb(conn, type, interface, neighbor, conn->watch_data); + if (conn->watch_cb) + conn->watch_cb(conn, type, interface, neighbor, conn->watch_data); + else + conn->watch_cb2(type, interface, neighbor, conn->watch_data); conn->watch_triggered = 1; goto end; } diff --git a/src/lib/lldpctl.h b/src/lib/lldpctl.h index 2369bf20..21222bb3 100644 --- a/src/lib/lldpctl.h +++ b/src/lib/lldpctl.h @@ -449,7 +449,7 @@ void lldpctl_atom_dec_ref(lldpctl_atom_t *atom); /** * Possible events for a change (notification). * - * @see lldpctl_watch_callback + * @see lldpctl_watch_callback2 */ typedef enum { lldpctl_c_deleted, /**< The neighbor has been deleted */ @@ -482,6 +482,25 @@ typedef void (*lldpctl_change_callback)(lldpctl_conn_t *conn, lldpctl_atom_t *neighbor, void *data); +/** + * Callback function invoked when a change is detected. + * + * @param type Type of change detected. + * @param interface Physical interface on which the change has happened. + * @param neighbor Changed neighbor. + * @param data Data provided when registering the callback. + * + * The provided interface and neighbor atoms are stolen by the callback: their + * reference count are decremented when the callback ends. If you want to keep a + * reference to it, be sure to increment the reference count in the callback. + * + * @see lldpctl_watch_callback2 + */ +typedef void (*lldpctl_change_callback2)(lldpctl_change_t type, + lldpctl_atom_t *interface, + lldpctl_atom_t *neighbor, + void *data); + /** * Register a callback to be called on changes. * @@ -497,9 +516,32 @@ typedef void (*lldpctl_change_callback)(lldpctl_conn_t *conn, * @warning Once a callback is registered, the connection shouldn't be used for * anything else than receiving notifications. If you do, you will get a @c * LLDPCTL_ERR_INVALID_STATE error. + * + * @deprecated This function is deprecated and lldpctl_watch_callback2 should be + * used instead. */ int lldpctl_watch_callback(lldpctl_conn_t *conn, lldpctl_change_callback cb, + void *data) __attribute__ ((deprecated)); + +/** + * Register a callback to be called on changes. + * + * @param conn Connection with lldpd. + * @param cb Replace the current callback with the provided one. + * @param data Data that will be passed to the callback. + * @return 0 in case of success or -1 in case of errors. + * + * This function will register the necessity to push neighbor changes to lldpd + * and therefore will issue IO operations. The error code could then be @c + * LLDPCTL_ERR_WOULDBLOCK. + * + * @warning Once a callback is registered, the connection shouldn't be used for + * anything else than receiving notifications. If you do, you will get a @c + * LLDPCTL_ERR_INVALID_STATE error. + */ +int lldpctl_watch_callback2(lldpctl_conn_t *conn, + lldpctl_change_callback2 cb, void *data); /** diff --git a/src/lib/lldpctl.map b/src/lib/lldpctl.map index c725381a..c602b641 100644 --- a/src/lib/lldpctl.map +++ b/src/lib/lldpctl.map @@ -1,3 +1,8 @@ +LIBLLDPCTL_4.9 { + global: + lldpctl_watch_callback2; +}; + LIBLLDPCTL_4.8 { global: lldpctl_get_default_port;