[PATCH 07/18] usbip: Add proper error reporting
From: Maximilian Eschenbacher
Date: Tue Sep 16 2014 - 18:10:52 EST
From: Dominik Paulus <dominik.paulus@xxxxxx>
This patch adds new error codes and features extended error reporting in
op_common packets.
Signed-off-by: Maximilian Eschenbacher <maximilian@xxxxxxxxxxxxxxxxxx>
Signed-off-by: Fjodor Schelichow <fjodor.schelichow@xxxxxxxxxxx>
Signed-off-by: Johannes Stadlinger <johannes.stadlinger@xxxxxx>
Signed-off-by: Dominik Paulus <dominik.paulus@xxxxxx>
Signed-off-by: Tobias Polzer <tobias.polzer@xxxxxx>
---
tools/usb/usbip/src/usbip_attach.c | 4 +--
tools/usb/usbip/src/usbip_list.c | 3 ++-
tools/usb/usbip/src/usbip_network.c | 51 ++++++++++++++++++++++++++++---------
tools/usb/usbip/src/usbip_network.h | 17 +++++++++++--
tools/usb/usbip/src/usbipd.c | 25 ++++++++++--------
5 files changed, 73 insertions(+), 27 deletions(-)
diff --git a/tools/usb/usbip/src/usbip_attach.c b/tools/usb/usbip/src/usbip_attach.c
index 4421ebc..51c67a2 100644
--- a/tools/usb/usbip/src/usbip_attach.c
+++ b/tools/usb/usbip/src/usbip_attach.c
@@ -147,7 +147,7 @@ static int query_import_device(int sockfd, char *busid)
/* receive a reply */
rc = usbip_net_recv_op_common(sockfd, &code);
if (rc < 0) {
- err("recv op_common");
+ err("recv op_common: %s", usbip_net_strerror(rc));
return -1;
}
@@ -177,7 +177,7 @@ static int attach_device(char *host, char *busid)
sockfd = usbip_net_connect(host);
if (sockfd < 0) {
- err("tcp connect");
+ err("connection attempt failed");
return -1;
}
diff --git a/tools/usb/usbip/src/usbip_list.c b/tools/usb/usbip/src/usbip_list.c
index 6042b7e..c122f41 100644
--- a/tools/usb/usbip/src/usbip_list.c
+++ b/tools/usb/usbip/src/usbip_list.c
@@ -64,7 +64,8 @@ static int get_exported_devices(char *host, int sockfd)
rc = usbip_net_recv_op_common(sockfd, &code);
if (rc < 0) {
- dbg("usbip_net_recv_op_common failed");
+ err("usbip_net_recv_op_common failed: %s",
+ usbip_net_strerror(rc));
return -1;
}
diff --git a/tools/usb/usbip/src/usbip_network.c b/tools/usb/usbip/src/usbip_network.c
index 6b8f949..f68741d 100644
--- a/tools/usb/usbip/src/usbip_network.c
+++ b/tools/usb/usbip/src/usbip_network.c
@@ -182,7 +182,7 @@ int usbip_net_recv_op_common(int sockfd, uint16_t *code)
rc = usbip_net_recv(sockfd, &op_common, sizeof(op_common));
if (rc < 0) {
dbg("usbip_net_recv failed: %d", rc);
- goto err;
+ return -ERR_SYSERR;
}
PACK_OP_COMMON(0, &op_common);
@@ -190,30 +190,49 @@ int usbip_net_recv_op_common(int sockfd, uint16_t *code)
if (op_common.version != USBIP_VERSION) {
dbg("version mismatch: %d %d", op_common.version,
USBIP_VERSION);
- goto err;
+ return -ERR_MISMATCH;
}
switch (*code) {
case OP_UNSPEC:
break;
default:
- if (op_common.code != *code) {
+ /*
+ * Only accept expected opcode. Exception: OP_REPLY
+ * flag set may be sent as a reply to all requests,
+ * if only used for status reporting.
+ */
+ if (op_common.code != *code && op_common.code != OP_REPLY) {
dbg("unexpected pdu %#0x for %#0x", op_common.code,
*code);
- goto err;
+ return -ERR_UNEXPECTED;
}
}
- if (op_common.status != ST_OK) {
- dbg("request failed at peer: %d", op_common.status);
- goto err;
- }
-
*code = op_common.code;
- return 0;
-err:
- return -1;
+ return -op_common.status;
+}
+
+const char *usbip_net_strerror(int status)
+{
+ static const char *const errs[] = {
+ /* ERR_OK */ "Success",
+ /* ERR_NA */ "Command failed",
+ /* ERR_MISMATCH */ "Protocol version mismatch",
+ /* ERR_SYSERR */ "System error",
+ /* ERR_UNEXPECTED */ "Unexpected opcode received",
+ /* ERR_AUTHREQ */ "Server requires authentication",
+ /* ERR_PERM */ "Permission denied",
+ /* ERR_NOTFOUND */ "Requested device not found",
+ /* ERR_NOAUTH */ "Server doesn't support authentication"
+ };
+ if (status < 0)
+ status = -status;
+ if (status >= (int) (sizeof(errs) / sizeof(*errs)) ||
+ status < 0) /* Happens if status was INT_MIN before */
+ return "Invalid";
+ return errs[status];
}
int usbip_net_set_reuseaddr(int sockfd)
@@ -467,6 +486,7 @@ int usbip_net_connect(char *hostname)
#ifdef HAVE_GNUTLS
if (usbip_srp_password) {
int rc;
+ uint16_t code = OP_REP_STARTTLS;
rc = usbip_net_send_op_common(sockfd, OP_REQ_STARTTLS, 0);
if (rc < 0) {
@@ -474,6 +494,13 @@ int usbip_net_connect(char *hostname)
return EAI_SYSTEM;
}
+ rc = usbip_net_recv_op_common(sockfd, &code);
+ if (rc < 0) {
+ err("STARTTLS attempt failed: %s",
+ usbip_net_strerror(rc));
+ return -1;
+ }
+
rc = usbip_net_srp_client_handshake(sockfd);
if (rc < 0) {
err("Unable to perform TLS handshake (wrong password?): %s",
diff --git a/tools/usb/usbip/src/usbip_network.h b/tools/usb/usbip/src/usbip_network.h
index 292d584..151e815 100644
--- a/tools/usb/usbip/src/usbip_network.h
+++ b/tools/usb/usbip/src/usbip_network.h
@@ -28,8 +28,15 @@ struct op_common {
uint16_t code;
/* add more error code */
-#define ST_OK 0x00
-#define ST_NA 0x01
+#define ERR_OK 0x00
+#define ERR_NA 0x01
+#define ERR_MISMATCH 0x02
+#define ERR_SYSERR 0x03
+#define ERR_UNEXPECTED 0x04
+#define ERR_AUTHREQ 0x05
+#define ERR_PERM 0x06
+#define ERR_NOTFOUND 0x07
+#define ERR_NOAUTH 0x08
uint32_t status; /* op_code status (for reply) */
} __attribute__((packed));
@@ -178,10 +185,16 @@ void usbip_net_pack_uint32_t(int pack, uint32_t *num);
void usbip_net_pack_uint16_t(int pack, uint16_t *num);
void usbip_net_pack_usb_device(int pack, struct usbip_usb_device *udev);
void usbip_net_pack_usb_interface(int pack, struct usbip_usb_interface *uinf);
+const char *usbip_net_strerror(int status);
ssize_t usbip_net_recv(int sockfd, void *buff, size_t bufflen);
ssize_t usbip_net_send(int sockfd, void *buff, size_t bufflen);
int usbip_net_send_op_common(int sockfd, uint32_t code, uint32_t status);
+/*
+ * Receive opcode.
+ * Returns: 0 on success, negative error code (that may be passed to
+ * usbip_net_strerror) on failure.
+ */
int usbip_net_recv_op_common(int sockfd, uint16_t *code);
int usbip_net_set_reuseaddr(int sockfd);
int usbip_net_set_nodelay(int sockfd);
diff --git a/tools/usb/usbip/src/usbipd.c b/tools/usb/usbip/src/usbipd.c
index 7c0a46d..4ac4206 100644
--- a/tools/usb/usbip/src/usbipd.c
+++ b/tools/usb/usbip/src/usbipd.c
@@ -167,7 +167,7 @@ static int recv_request_import(int sockfd)
char sysfs_attr[SYSFS_IP_ACLS_MAX];
char ip_attr_path[SYSFS_PATH_MAX];
int found = 0;
- int error = 0;
+ int error = ERR_OK;
int rc;
memset(&req, 0, sizeof(req));
@@ -196,7 +196,7 @@ static int recv_request_import(int sockfd)
/* export device needs a TCP/IP socket descriptor */
rc = usbip_host_export_device(edev, sockfd);
if (rc < 0)
- error = 1;
+ error = ERR_SYSERR;
/* check for allowed IPs */
snprintf(ip_attr_path, sizeof(ip_attr_path), "%s/%s",
@@ -213,17 +213,16 @@ static int recv_request_import(int sockfd)
}
} else {
info("requested device not found: %s", req.busid);
- error = 1;
+ error = ERR_NOTFOUND;
}
- rc = usbip_net_send_op_common(sockfd, OP_REP_IMPORT,
- (!error ? ST_OK : ST_NA));
+ rc = usbip_net_send_op_common(sockfd, OP_REP_IMPORT, error);
if (rc < 0) {
dbg("usbip_net_send_op_common failed: %#0x", OP_REP_IMPORT);
return -1;
}
- if (error) {
+ if (error != 0) {
dbg("import request busid %s: failed", req.busid);
return -1;
}
@@ -258,7 +257,7 @@ static int send_reply_devlist(int connfd)
}
info("exportable devices: %d", reply.ndev);
- rc = usbip_net_send_op_common(connfd, OP_REP_DEVLIST, ST_OK);
+ rc = usbip_net_send_op_common(connfd, OP_REP_DEVLIST, ERR_OK);
if (rc < 0) {
dbg("usbip_net_send_op_common failed: %#0x", OP_REP_DEVLIST);
return -1;
@@ -341,7 +340,8 @@ static int recv_pdu(int connfd)
ret = usbip_net_recv_op_common(connfd, &code);
if (ret < 0) {
- dbg("could not receive opcode: %#0x", code);
+ dbg("could not receive opcode: %#0x: %s", code,
+ usbip_net_strerror(ret));
return -1;
}
@@ -349,7 +349,8 @@ static int recv_pdu(int connfd)
/* We require an authenticated encryption */
if (!auth && code != OP_REQ_STARTTLS) {
- usbip_net_send_op_common(connfd, OP_REPLY, ST_NA);
+ info("Unauthenticated connection attempt");
+ usbip_net_send_op_common(connfd, OP_REPLY, ERR_AUTHREQ);
return -1;
}
@@ -357,9 +358,13 @@ static int recv_pdu(int connfd)
#ifdef HAVE_GNUTLS
case OP_REQ_STARTTLS:
if (!need_auth) {
- ret = -1;
+ usbip_net_send_op_common(connfd, OP_REPLY,
+ ERR_NOAUTH);
err("Unexpected TLS handshake attempt (client uses password, server doesn't)");
+ ret = -1;
} else {
+ usbip_net_send_op_common(connfd, OP_REPLY,
+ ERR_OK);
ret = net_srp_server_handshake(connfd);
if (ret != 0)
err("TLS handshake failed");
--
2.1.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/