Discussion:
[PATCH] ppp: Detailed last error support
(too old to reply)
Hans Dedecker
2015-04-08 14:20:21 UTC
Permalink
Enables last error support for the PPP protocol handlers.
In generic teardown the PPP daemon exit code is translated into
a self explaining error string which is set as interface error
by proto_notify_error in case of failure.

Signed-off-by: Johan Peeters <***@gmail.com>
Signed-off-by: Hans Dedecker <***@gmail.com>
---
package/network/services/ppp/files/ppp.sh | 51 ++++++++++++++++++++++++++++---
1 file changed, 47 insertions(+), 4 deletions(-)

diff --git a/package/network/services/ppp/files/ppp.sh b/package/network/services/ppp/files/ppp.sh
index b4a7467..99fdc87 100755
--- a/package/network/services/ppp/files/ppp.sh
+++ b/package/network/services/ppp/files/ppp.sh
@@ -8,6 +8,38 @@
init_proto "$@"
}

+ppp_exitcode_tostring()
+{
+ local errorcode=$1
+ [ -n "$errorcode" ] || errorcode=5
+
+ case "$errorcode" in
+ 0) echo "OK" ;;
+ 1) echo "FATAL_ERROR" ;;
+ 2) echo "OPTION_ERROR" ;;
+ 3) echo "NOT_ROOT" ;;
+ 4) echo "NO_KERNEL_SUPPORT" ;;
+ 5) echo "USER_REQUEST" ;;
+ 6) echo "LOCK_FAILED" ;;
+ 7) echo "OPEN_FAILED" ;;
+ 8) echo "CONNECT_FAILED" ;;
+ 9) echo "PTYCMD_FAILED" ;;
+ 10) echo "NEGOTIATION_FAILED" ;;
+ 11) echo "PEER_AUTH_FAILED" ;;
+ 12) echo "IDLE_TIMEOUT" ;;
+ 13) echo "CONNECT_TIME" ;;
+ 14) echo "CALLBACK" ;;
+ 15) echo "PEER_DEAD" ;;
+ 16) echo "HANGUP" ;;
+ 17) echo "LOOPBACK" ;;
+ 18) echo "INIT_FAILED" ;;
+ 19) echo "AUTH_TOPEER_FAILED" ;;
+ 20) echo "TRAFFIC_LIMIT" ;;
+ 21) echo "CNID_AUTH_FAILED";;
+ *) echo "UNKNOWN_ERROR" ;;
+ esac
+}
+
ppp_generic_init_config() {
proto_config_add_string username
proto_config_add_string password
@@ -72,20 +104,27 @@ ppp_generic_setup() {

ppp_generic_teardown() {
local interface="$1"
+ local errorstring=$(ppp_exitcode_tostring $ERROR)

case "$ERROR" in
+ 0)
+ ;;
+ 2)
+ proto_notify_error "$interface" "$errorstring"
+ proto_block_restart "$interface"
+ ;;
11|19)
- proto_notify_error "$interface" AUTH_FAILED
json_get_var authfail authfail
+ proto_notify_error "$interface" "$errorstring"
if [ "${authfail:-0}" -gt 0 ]; then
proto_block_restart "$interface"
fi
;;
- 2)
- proto_notify_error "$interface" INVALID_OPTIONS
- proto_block_restart "$interface"
+ *)
+ proto_notify_error "$interface" "$errorstring"
;;
esac
+
proto_kill_command "$interface"
}

@@ -96,6 +135,7 @@ proto_ppp_init_config() {
ppp_generic_init_config
no_device=1
available=1
+ lasterror=1
}

proto_ppp_setup() {
@@ -114,6 +154,7 @@ proto_pppoe_init_config() {
proto_config_add_string "ac"
proto_config_add_string "service"
proto_config_add_string "host_uniq"
+ lasterror=1
}

proto_pppoe_setup() {
@@ -151,6 +192,7 @@ proto_pppoa_init_config() {
proto_config_add_string "encaps"
no_device=1
available=1
+ lasterror=1
}

proto_pppoa_setup() {
@@ -184,6 +226,7 @@ proto_pptp_init_config() {
proto_config_add_string "interface"
available=1
no_device=1
+ lasterror=1
}

proto_pptp_setup() {
--
1.9.1
Hans Dedecker
2015-04-08 14:20:22 UTC
Permalink
Adds interface last error support which preserves the last reported
error reported by the protocol handler till the interface is up;
e.g. survives network reload and interface restarts.
This is mainly usefull for tracking down why an interface fails
to establish; eg auth failure/traffic limit for PPP interfaces

Protocol handlers register last error support by setting lasterror=1
in the proto_init function

Signed-off-by: Johan Peeters <***@gmail.com>
Signed-off-by: Hans Dedecker <***@gmail.com>
---
interface.c | 27 ++++++++++++++++++++++++++-
proto-shell.c | 4 ++++
proto.c | 6 +++++-
proto.h | 1 +
scripts/netifd-proto.sh | 1 +
5 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/interface.c b/interface.c
index 444f3ac..8239eac 100644
--- a/interface.c
+++ b/interface.c
@@ -80,7 +80,7 @@ const struct uci_blob_param_list interface_attr_list = {
};

static void
-interface_clear_errors(struct interface *iface)
+interface_error_flush(struct interface *iface)
{
struct interface_error *error, *tmp;

@@ -90,6 +90,17 @@ interface_clear_errors(struct interface *iface)
}
}

+static void
+interface_clear_errors(struct interface *iface)
+{
+ /* don't flush the errors in case the configured protocol handler matches the
+ running protocol handler and is having the last error capability */
+ if (!(iface->proto &&
+ (iface->proto->handler->flags & PROTO_FLAG_LASTERROR) &&
+ (iface->proto->handler->name == iface->proto_handler->name)))
+ interface_error_flush(iface);
+}
+
void interface_add_error(struct interface *iface, const char *subsystem,
const char *code, const char **data, int n_data)
{
@@ -98,6 +109,14 @@ void interface_add_error(struct interface *iface, const char *subsystem,
int *datalen = NULL;
char *dest, *d_subsys, *d_code;

+ /* if the configured protocol handler has the last error support capability,
+ errors should only be added if the running protocol handler matches the
+ configured one */
+ if (iface->proto &&
+ (iface->proto->handler->flags & PROTO_FLAG_LASTERROR) &&
+ (iface->proto->handler->name != iface->proto_handler->name))
+ return;
+
if (n_data) {
len = n_data * sizeof(char *);
datalen = alloca(len);
@@ -113,6 +132,11 @@ void interface_add_error(struct interface *iface, const char *subsystem,
if (!error)
return;

+ /* Only keep the last flagged error, prevent this list grows unlimitted in case the
+ protocol can't be established (e.g auth failure) */
+ if (iface->proto_handler->flags & PROTO_FLAG_LASTERROR)
+ interface_error_flush(iface);
+
list_add_tail(&error->list, &iface->errors);

dest = (char *) &error->data[n_data + 1];
@@ -188,6 +212,7 @@ interface_event(struct interface *iface, enum interface_event ev)

switch (ev) {
case IFEV_UP:
+ interface_error_flush(iface);
adev = iface->l3_dev.dev;
/* fall through */
case IFEV_DOWN:
diff --git a/proto-shell.c b/proto-shell.c
index 977cdbc..7a1896b 100644
--- a/proto-shell.c
+++ b/proto-shell.c
@@ -819,6 +819,10 @@ proto_shell_add_handler(const char *script, const char *name, json_object *obj)
if (tmp && json_object_get_boolean(tmp))
handler->proto.flags |= PROTO_FLAG_RENEW_AVAILABLE;

+ tmp = json_get_field(obj, "lasterror", json_type_boolean);
+ if (tmp && json_object_get_boolean(tmp))
+ handler->proto.flags |= PROTO_FLAG_LASTERROR;
+
config = json_get_field(obj, "config", json_type_array);
if (config)
handler->config_buf = netifd_handler_parse_config(&handler->config, config);
diff --git a/proto.c b/proto.c
index 0ba2fbe..eaec913 100644
--- a/proto.c
+++ b/proto.c
@@ -586,16 +586,20 @@ void
proto_attach_interface(struct interface *iface, const char *proto_name)
{
const struct proto_handler *proto = &no_proto;
+ const char *error = NULL;

if (proto_name) {
proto = get_proto_handler(proto_name);
if (!proto) {
- interface_add_error(iface, "proto", "INVALID_PROTO", NULL, 0);
+ error = "INVALID_PROTO";
proto = &no_proto;
}
}

iface->proto_handler = proto;
+
+ if (error)
+ interface_add_error(iface, "proto", error, NULL, 0);
}

int
diff --git a/proto.h b/proto.h
index 7210f48..87dec4e 100644
--- a/proto.h
+++ b/proto.h
@@ -37,6 +37,7 @@ enum {
PROTO_FLAG_INIT_AVAILABLE = (1 << 2),
PROTO_FLAG_RENEW_AVAILABLE = (1 << 3),
PROTO_FLAG_FORCE_LINK_DEFAULT = (1 << 4),
+ PROTO_FLAG_LASTERROR = (1 << 5),
};

struct interface_proto_state {
diff --git a/scripts/netifd-proto.sh b/scripts/netifd-proto.sh
index ce60cd0..95c1bb3 100644
--- a/scripts/netifd-proto.sh
+++ b/scripts/netifd-proto.sh
@@ -375,6 +375,7 @@ init_proto() {
json_add_boolean no-device "$no_device"
json_add_boolean available "$available"
json_add_boolean renew-handler "$renew_handler"
+ json_add_boolean lasterror "$lasterror"
json_dump
}
;;
--
1.9.1
Loading...