From 50f98aec98d066129b932e53bf33eef64896938f Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 25 Apr 2011 04:38:19 +0200 Subject: Implemented tunnel list command --- qtctl.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 107 insertions(+), 13 deletions(-) (limited to 'qtctl.c') diff --git a/qtctl.c b/qtctl.c index 2468846..9a0708d 100644 --- a/qtctl.c +++ b/qtctl.c @@ -10,9 +10,10 @@ #include "quicktun.h" -void usage() +static void usage() { - fputs("Usage: qtctl add [ dev NAME ] [ mode { ethernet | ip } ]\n" + fputs("Usage: qtctl show [dev NAME]\n" + " qtctl add [ dev NAME ] [ mode { ethernet | ip } ]\n" " [ local_address ADDRESS ] [ local_port PORT ]\n" " [ remote_address ADDRESS ] [ remote_port PORT ]\n" " [ remote_float ]\n" @@ -21,12 +22,18 @@ void usage() exit(2); } -void add(int argc, char *argv[], struct nl_handle *sock, int family) +static int print_error(struct sockaddr_nl *nla, struct nlmsgerr *nlerr, void *arg) +{ + fprintf(stderr, "Error received: %s\n", strerror(-nlerr->error)); + exit(1); +} + +static void add(int argc, char *argv[], struct nl_handle *sock, int family) { struct nl_msg *msg; struct nl_cb *cb; - int p = 1; + int p = 0; uint16_t mode = QUICKTUN_MODE_ETHERNET; char *tmp_charp; @@ -111,17 +118,17 @@ void add(int argc, char *argv[], struct nl_handle *sock, int family) nlmsg_free(msg); cb = nl_cb_alloc(NL_CB_DEFAULT); - nl_cb_err(cb, NL_CB_DEBUG, NULL, NULL); + nl_cb_err(cb, NL_CB_CUSTOM, print_error, NULL); nl_recvmsgs(sock, cb); } -void del(int argc, char *argv[], struct nl_handle *sock, int family) +static void del(int argc, char *argv[], struct nl_handle *sock, int family) { struct nl_msg *msg; struct nl_cb *cb; - int p = 1; + int p = 0; char *tmp_charp; int has_dev = 0; @@ -154,7 +161,87 @@ void del(int argc, char *argv[], struct nl_handle *sock, int family) nlmsg_free(msg); cb = nl_cb_alloc(NL_CB_DEFAULT); - nl_cb_err(cb, NL_CB_DEBUG, NULL, NULL); + nl_cb_err(cb, NL_CB_CUSTOM, print_error, NULL); + + nl_recvmsgs(sock, cb); +} + +static int show_callback(struct nl_msg *msg, void *arg) +{ + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct genlmsghdr *ghdr; + struct nlattr *pos, *pos2; + struct nlattr *nested[__QUICKTUN_A_MAX]; + struct in_addr addr; + int rem; + + if (!genlmsg_valid_hdr(nlh, 0)) { + fputs("Received invalid data from kernel.", stderr); + exit(1); + } + + ghdr = nlmsg_data(nlh); + + if (ghdr->cmd != QUICKTUN_CMD_GET_DEVICE) + return NL_OK; + + nla_for_each_attr(pos, genlmsg_attrdata(ghdr, 0), genlmsg_len(ghdr), rem) { + nla_parse_nested(nested, QUICKTUN_A_MAX, pos, NULL); + + if(!nested[QUICKTUN_A_IFNAME] || !nested[QUICKTUN_A_MODE] || !nested[QUICKTUN_A_LOCAL_ADDRESS] || !nested[QUICKTUN_A_LOCAL_PORT] + || !nested[QUICKTUN_A_REMOTE_ADDRESS] || !nested[QUICKTUN_A_REMOTE_PORT]) + continue; + + printf("%s: %s ", nla_get_string(nested[QUICKTUN_A_IFNAME]), (nla_get_u16(nested[QUICKTUN_A_MODE]) == QUICKTUN_MODE_ETHERNET) ? "ethernet" : (nla_get_u16(nested[QUICKTUN_A_MODE]) == QUICKTUN_MODE_IP) ? "ip" : "unknown" ); + + addr.s_addr = nla_get_u32(nested[QUICKTUN_A_LOCAL_ADDRESS]); + printf("local %s:%u ", inet_ntoa(addr), ntohs(nla_get_u16(nested[QUICKTUN_A_LOCAL_PORT]))); + + addr.s_addr = nla_get_u32(nested[QUICKTUN_A_REMOTE_ADDRESS]); + printf("remote %s:%u ", inet_ntoa(addr), ntohs(nla_get_u16(nested[QUICKTUN_A_REMOTE_PORT]))); + + printf("remote_float %s\n", nla_get_flag(nested[QUICKTUN_A_REMOTE_FLOAT]) ? "on" : "off"); + } + + return NL_STOP; +} + +static void show(int argc, char *argv[], struct nl_handle *sock, int family) +{ + struct nl_msg *msg; + struct nl_cb *cb; + + int p = 0; + char *tmp_charp; + + int has_dev = 0; + + msg = nlmsg_alloc(); + genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_ECHO, QUICKTUN_CMD_GET_DEVICE, 1); + + while ((++p) < argc) { + if (!strcmp(argv[p], "dev")) { + if ((++p) >= argc) + usage(); + + if (has_dev) + usage(); + + tmp_charp = strndup(argv[p], IFNAMSIZ - 1); + nla_put_string(msg, QUICKTUN_A_IFNAME, tmp_charp); + free(tmp_charp); + + has_dev = 1; + } + } + + nl_send_auto_complete(sock, msg); + + nlmsg_free(msg); + + cb = nl_cb_alloc(NL_CB_DEFAULT); + nl_cb_set (cb, NL_CB_VALID, NL_CB_CUSTOM, show_callback, NULL); + nl_cb_err(cb, NL_CB_CUSTOM, print_error, NULL); nl_recvmsgs(sock, cb); } @@ -166,15 +253,22 @@ int main(int argc, char *argv[]) sock = nl_handle_alloc(); genl_connect(sock); + family = genl_ctrl_resolve(sock, "quicktun"); + if (family < 0) { + fputs("Your kernel doesn't support Quicktun.\n", stderr); + exit(1); + } - if (argc < 2) - usage(); - if (!strcmp(argv[1], "add")) - add(argc, argv, sock, family); + if (argc < 2) + show(argc, argv, sock, family); + else if (!strcmp(argv[1], "add")) + add(argc-1, argv+1, sock, family); else if (!strcmp(argv[1], "del")) - del(argc, argv, sock, family); + del(argc-1, argv+1, sock, family); + else if (!strcmp(argv[1], "show")) + show(argc-1, argv+1, sock, family); else usage(); -- cgit v1.2.3