From f58c955a15789c4bcdc3392d8d94d93694a83be0 Mon Sep 17 00:00:00 2001 From: root <245051644@qq.com> Date: Wed, 1 Mar 2023 12:57:40 +0800 Subject: [PATCH] Add remote port query. A new device, qtfs_utilities, has been added to obtain the status of the remote port, and will be extended in the future with more functionality. Signed-off-by: yangxin <245051644@qq.com> --- qtfs/qtfs/Makefile | 2 +- qtfs/qtfs/qtfs-mod.c | 4 ++ qtfs/qtfs/utilities.c | 96 +++++++++++++++++++++++++++ qtfs/qtfs_server/fsops.c | 47 +++++++++++++ qtfs/req.h | 22 +++++- qtfs/test/remote_port_query_example.c | 55 +++++++++++++++ qtfs/utils.h | 26 ++++++++ 7 files changed, 250 insertions(+), 2 deletions(-) create mode 100644 qtfs/qtfs/utilities.c create mode 100644 qtfs/test/remote_port_query_example.c create mode 100644 qtfs/utils.h diff --git a/qtfs/qtfs/Makefile b/qtfs/qtfs/Makefile index f03ec52..12d971d 100644 --- a/qtfs/qtfs/Makefile +++ b/qtfs/qtfs/Makefile @@ -2,7 +2,7 @@ ccflags-y += -I$(src)/../ -I$(src) -DQTFS_CLIENT KBUILD=/lib/modules/$(shell uname -r)/build/ obj-m:=qtfs.o -qtfs-objs:=qtfs-mod.o sb.o syscall.o ../conn.o xattr.o proc.o ../misc.o miss.o +qtfs-objs:=qtfs-mod.o sb.o syscall.o ../conn.o xattr.o proc.o ../misc.o miss.o utilities.o all: qtfs diff --git a/qtfs/qtfs/qtfs-mod.c b/qtfs/qtfs/qtfs-mod.c index a4fe720..c339e62 100644 --- a/qtfs/qtfs/qtfs-mod.c +++ b/qtfs/qtfs/qtfs-mod.c @@ -14,6 +14,8 @@ static struct file_system_type qtfs_fs_type = { }; MODULE_ALIAS_FS("qtfs"); +extern int qtfs_utilities_register(void); +extern void qtfs_utilities_destroy(void); /* * 转发框架层: * 1. 调用者先在pvar里预留框架头后,填好自己的私有发送数据。 @@ -212,6 +214,7 @@ static int __init qtfs_init(void) } qtfs_misc_register(); + qtfs_utilities_register(); qtfs_kallsyms_hack_init(); qtfs_conn_param_init(); qtfs_syscall_init(); @@ -231,6 +234,7 @@ static void __exit qtfs_exit(void) qtfs_conn_param_fini(); qtfs_misc_destroy(); + qtfs_utilities_destroy(); if (qtfs_epoll_var != NULL) { qtfs_epoll_cut_conn(qtfs_epoll_var); if (qtfs_epoll_var->sock != NULL) { diff --git a/qtfs/qtfs/utilities.c b/qtfs/qtfs/utilities.c new file mode 100644 index 0000000..ad7c667 --- /dev/null +++ b/qtfs/qtfs/utilities.c @@ -0,0 +1,96 @@ +#include +#include +#include "conn.h" + +#include "qtfs-mod.h" +#include "req.h" + +#define QTFS_IOCTL_MAGIC 'Q' +enum { + _QTFS_IOCTL_QUERY_PORT, +}; + +#define QTFS_IOCTL_QUERYPORT _IO(QTFS_IOCTL_MAGIC, _QTFS_IOCTL_QUERY_PORT) + +extern int qtfs_query_port(void *query_req); +long qtfs_utilities_ioctl(struct file *file, unsigned int cmd, unsigned long arg); +struct file_operations qtfs_utilities_fops = { + .owner=THIS_MODULE, + .unlocked_ioctl = qtfs_utilities_ioctl, +}; +static struct miscdevice qtfs_utilities_dev = { + .minor = MISC_DYNAMIC_MINOR, + .name = "qtfs_utilities", + .fops = &qtfs_utilities_fops, +}; + +int qtfs_utilities_register(void) +{ + int ret = misc_register(&qtfs_utilities_dev); + if (ret) { + qtfs_err("qtfs utilities register failed, ret:%d.", ret); + return -EFAULT; + } + return 0; +} + +void qtfs_utilities_destroy(void) +{ + misc_deregister(&qtfs_utilities_dev); + return; +} + + +int qtfs_query_port(void *query_req) +{ + struct qtfs_sock_var_s *pvar = qtfs_conn_get_param(); + struct qtreq_queryport *req; + struct qtrsp_queryport *rsp; + int optslen; + int ret; + + if (!pvar) { + qtfs_err("Failed to get qtfs sock var"); + return -EINVAL; + } + + if(copy_from_user(&optslen, query_req, sizeof(int))) { + qtfs_err("qtfs_query_port: wrong addr %lx"); + qtfs_conn_put_param(pvar); + return -EFAULT; + } + + req = qtfs_sock_msg_buf(pvar, QTFS_SEND); + rsp = qtfs_sock_msg_buf(pvar, QTFS_RECV); + if (sizeof(struct qtreq_queryport) + optslen * sizeof(struct socketopt) > QTFS_REQ_MAX_LEN) { + qtfs_conn_put_param(pvar); + return -EINVAL; + } + if(copy_from_user(req, query_req, sizeof(struct qtreq_queryport) + optslen * sizeof(struct socketopt))) { + qtfs_err("qtfs_query_port: wrong addr %lx"); + qtfs_conn_put_param(pvar); + return -EFAULT; + } + rsp = qtfs_remote_run(pvar, QTFS_REQ_QUERYPORT, sizeof(struct qtreq_queryport) + optslen * sizeof(struct socketopt)); + if (IS_ERR(rsp) || rsp == NULL) { + qtfs_conn_put_param(pvar); + return -EINVAL; + } + ret = rsp->ret; + qtfs_conn_put_param(pvar); + return ret; +} + + +long qtfs_utilities_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + long ret = QTOK; + switch (cmd) { + case QTFS_IOCTL_QUERYPORT: + { + ret = qtfs_query_port((void *)arg); + break; + } + } + return ret; +} diff --git a/qtfs/qtfs_server/fsops.c b/qtfs/qtfs_server/fsops.c index bf16d14..ce52917 100644 --- a/qtfs/qtfs_server/fsops.c +++ b/qtfs/qtfs_server/fsops.c @@ -17,6 +17,7 @@ #include "qtfs-server.h" #include "req.h" #include "log.h" +#include "req.h" #include "fsops.h" #include "comm.h" @@ -1178,6 +1179,50 @@ end: return sizeof(struct qtrsp_llseek); } +int handle_query_port(struct qtserver_arg *arg) +{ + struct qtreq_queryport *req = (struct qtreq_queryport *)REQ(arg); + struct qtrsp_queryport *rsp = (struct qtrsp_queryport *)RSP(arg); + struct sockaddr *saddr; + struct socket *sock; + int ret, err, i; + size_t addrlen; + struct sockaddr_in *addr4; + addr4 = (struct sockaddr_in *)&(req->addr); + saddr = &(req->addr); + switch (saddr->sa_family) { + case AF_INET6: + addrlen = sizeof(struct sockaddr_in6); + break; + case AF_INET: + addrlen = sizeof(struct sockaddr_in); + break; + default: + rsp->ret = -EAFNOSUPPORT; + return sizeof(struct qtrsp_queryport); + } + ret = sock_create_kern(&init_net, saddr->sa_family, SOCK_STREAM, 0, &sock); + if (ret) { + qtfs_err("handle_query_port create sock failed.\n"); + rsp->ret = ret; + } else { + for (i = 0; i < req->optslen; i++) { + sockptr_t optval = KERNEL_SOCKPTR(req->opts[i].optval); + if (req->opts[i].level == SOL_SOCKET) + err = sock_setsockopt(sock, req->opts[i].level, req->opts[i].optname, optval, req->opts[i].optlen); + else if (unlikely(!sock->ops->setsockopt)) + err = -EOPNOTSUPP; + else + err = sock->ops->setsockopt(sock, req->opts[i].level, req->opts[i].optname, optval, req->opts[i].optlen); + } + ret = sock->ops->bind(sock, saddr, addrlen); + rsp->ret = ret; + } + sock_release(sock); + + return sizeof(struct qtrsp_queryport); +} + int handle_exit(struct qtserver_arg *arg) { return 4; @@ -1228,6 +1273,8 @@ static struct qtserver_ops qtfs_server_handles[] = { {QTFS_REQ_LLSEEK, handle_llseek, "llseek"}, + {QTFS_REQ_QUERYPORT, handle_query_port, "query_port"}, + {QTFS_REQ_EXIT, handle_exit, "exit"}, // keep this handle at the end }; diff --git a/qtfs/req.h b/qtfs/req.h index 29f8964..98d19a0 100644 --- a/qtfs/req.h +++ b/qtfs/req.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "log.h" enum qtreq_type { @@ -46,6 +47,7 @@ enum qtreq_type { QTFS_REQ_LLSEEK, + QTFS_REQ_QUERYPORT, QTFS_REQ_EXIT, // exit server thread QTFS_REQ_INV, }; @@ -508,7 +510,6 @@ struct qtrsp_epollctl { int ret; }; - // server epoll 通知 client #define QTFS_EPOLL_MAX_EVENTS 128 struct qtreq_epollevt { @@ -530,4 +531,23 @@ struct qtrsp_llseek { int ret; loff_t off; }; + +#define OPTVAL_MAX 264 +struct socketopt +{ + int level; + int optname; + char optval[OPTVAL_MAX]; + unsigned int optlen; +}; + +struct qtreq_queryport { + int optslen; + struct sockaddr addr; + struct socketopt opts[0]; +}; + +struct qtrsp_queryport { + int ret; +}; #endif diff --git a/qtfs/test/remote_port_query_example.c b/qtfs/test/remote_port_query_example.c new file mode 100644 index 0000000..80dd1b2 --- /dev/null +++ b/qtfs/test/remote_port_query_example.c @@ -0,0 +1,55 @@ +/* + compile: gcc ./remote_port_query_example.c -o test -I../ + usage: ./test +*/ +#include +#include +#include +#include +#include +#include +#include + +#include "utils.h" +void querry_port(int fd, int family, char *ipaddr, int port) +{ + int ret; + int flag = 1; + struct remote_port_query *query_req = (struct remote_port_query *)malloc(sizeof(struct remote_port_query) + 2 * sizeof(struct socketopt)); + query_req->optslen = 2; + if (family == 10) { + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&(query_req->addr); + addr6->sin6_family = 10; + addr6->sin6_port = htons(port); + addr6->sin6_addr = in6addr_any; + } else if (family == 2) { + struct sockaddr_in *addr4 = (struct sockaddr_in *)&(query_req->addr); + addr4->sin_family = 2; + addr4->sin_port = htons(port); + addr4->sin_addr.s_addr = inet_addr(ipaddr); + } + query_req->opts[0].level = SOL_SOCKET; + query_req->opts[0].optname = SO_REUSEADDR; + memcpy(query_req->opts[0].optval, &flag, sizeof(flag)); + query_req->opts[0].optlen = sizeof(flag); + int v6only = 0; + query_req->opts[1].level = IPPROTO_IPV6; + query_req->opts[1].optname = IPV6_V6ONLY; + memcpy(query_req->opts[1].optval, &v6only, sizeof(v6only)); + query_req->opts[1].optlen = sizeof(v6only); + ret = ioctl(fd, QTFS_IOCTL_QUERYPORT, query_req); + if (ret != 0) { + printf("qtfs query remote port :%d failed, errno %d.\n", port, errno); + return; + } + struct sockaddr_in *addr4 = (struct sockaddr_in *)&(query_req->addr); + printf("qtfs query remote %s port %d success.\n", ipaddr, port); + return; +} + +int main(int argc, char *argv[]) +{ + int fd = open(QTFS_UTILITIES_DEV, O_RDONLY|O_NONBLOCK); + + querry_port(fd, atoi(argv[1]), argv[2], atoi(argv[3])); +} \ No newline at end of file diff --git a/qtfs/utils.h b/qtfs/utils.h new file mode 100644 index 0000000..f57bcba --- /dev/null +++ b/qtfs/utils.h @@ -0,0 +1,26 @@ +#include + +#define QTFS_UTILITIES_DEV "/dev/qtfs_utilities" + +#define QTFS_IOCTL_MAGIC 'Q' +enum { + _QTFS_IOCTL_QUERY_PORT, +}; + + +#define QTFS_IOCTL_QUERYPORT _IO(QTFS_IOCTL_MAGIC, _QTFS_IOCTL_QUERY_PORT) + +#define OPTVAL_MAX 264 +struct socketopt +{ + int level; + int optname; + char optval[OPTVAL_MAX]; + unsigned int optlen; +}; + +struct remote_port_query { + int optslen; + struct sockaddr addr; + struct socketopt opts[0]; +}; \ No newline at end of file -- Gitee