#include #include #include #include #include "intf.h" #include "debug.h" extern struct tsnif_np_prot udp_prot; extern struct tsnif_np_prot tcp_prot; struct tsnif_np_prot *prot[TSNIF_NP_PROT_MAX] = { &udp_prot, &tcp_prot, }; #define UDP (prot[TSNIF_NP_PROT_UDP]) #define TCP (prot[TSNIF_NP_PROT_TCP]) static int udp_init(struct tsnif_handle *h, struct tsnif_np_args *np, int flags) { int ret; if (flags & TSNIF_NP_UDP_CLIENT) ret = UDP->init_client(h, np); else ret = UDP->init_server(h, np); return ret; } int tsnif_np_init(struct tsnif_handle *h, struct tsnif_np_args *np) { int ret; int flags = np->flags; struct tsnif_np_handle *nph = &h->np; TSNIF_DEBUG(NP, "flags = %x, client %d, udp %d\n", np ? np->flags : 0, np ? np->flags & TSNIF_NP_CLIENT : 0, np ? np->flags & TSNIF_NP_UDP : 0 ); /* no proxy requested */ if (!np && (!np->flags)) return 0; memset(nph, 0x0, sizeof(*nph)); nph->fd_udp = -1; nph->fd_tcp = -1; nph->args = np; if (flags & TSNIF_NP_CLIENT) { /* only one client protocol allowed */ if ((flags & TSNIF_NP_UDP_CLIENT) && (flags & TSNIF_NP_TCP_CLIENT)) return -EINVAL; h->np_only = 1; } if (TSNIF_NP_UDP & flags) ret = udp_init(h, np, flags); TSNIF_DEBUG(NP, "ret = %d\n", ret); return ret; } int tsnif_np_fd(struct tsnif_handle *h, fd_set *set) { struct tsnif_np_handle *nph = &h->np; int fd_udp = nph->fd_udp; int fd_tcp = nph->fd_tcp; if ((TSNIF_NP_UDP & TSNIF_NP_FLAGS(nph)) && (-1 != fd_udp)) FD_SET(fd_udp, set); if ((TSNIF_NP_TCP & TSNIF_NP_FLAGS(nph)) && (-1 != fd_tcp)) FD_SET(fd_tcp, set); return (fd_udp > fd_tcp ? fd_udp : fd_tcp); } int tsnif_np_process(struct tsnif_handle *h, fd_set *set) { struct tsnif_np_handle *nph = &h->np; int ret = 0; if ((TSNIF_NP_UDP & TSNIF_NP_FLAGS(nph)) && FD_ISSET(nph->fd_udp, set)) ret = UDP->process(h); return ret; } int tsnif_np_close(struct tsnif_handle *h) { struct tsnif_np_handle *nph = &h->np; if (TSNIF_NP_UDP & TSNIF_NP_FLAGS(nph)) UDP->close(h); return 0; } int tsnif_np_send_client(struct tsnif_handle *h, struct trans_msg *msg) { struct tsnif_np_handle *nph = &h->np; int ret = 0; /* pro bile, cernochu!!! ;) */ if (!(TSNIF_NP_CLIENT & TSNIF_NP_FLAGS(nph))) return 0; if (TSNIF_NP_UDP & TSNIF_NP_FLAGS(nph)) ret = UDP->send(h, msg); return ret > 0 ? 0 : ret; } int tsnif_np_send_server(struct tsnif_handle *h, struct trans_msg *msg) { struct tsnif_np_handle *nph = &h->np; int ret = 0; if (!(TSNIF_NP_SERVER & TSNIF_NP_FLAGS(nph))) return 0; if (TSNIF_NP_UDP & TSNIF_NP_FLAGS(nph)) ret = UDP->send(h, msg); return ret > 0 ? 0 : ret; } static int dispatch_server_attach(struct tsnif_handle *h, struct trans_msg *msg) { struct tsnif_np_handle *nph = &h->np; struct tsnif_term *term; TSNIF_DEBUG(NP, "type = %d, idx = %d\n", msg->type, msg->idx); term = term_find(h, msg->type, msg->idx); if (!term) { TSNIF_DEBUG(NP, "term not found\n"); msg->err = 1; msg->error = -EINVAL; return tsnif_np_send_server(h, msg); } if (TSNIF_NP_UDP & TSNIF_NP_FLAGS(nph)) nph->udp_client.term = term; TSNIF_DEBUG(NP, "term attached\n"); msg->ack = 1; return tsnif_np_send_server(h, msg); } static int dispatch_server_detach(struct tsnif_handle *h, struct trans_msg *msg) { struct tsnif_np_handle *nph = &h->np; struct tsnif_term *term; TSNIF_DEBUG(NP, "type = %d, idx = %d\n", msg->type, msg->idx); term = term_find(h, msg->type, msg->idx); if ((!term) || (term != nph->udp_client.term)) { TSNIF_DEBUG(NP, "term not found\n"); msg->err = 1; msg->error = -EINVAL; return tsnif_np_send_server(h, msg); } if (TSNIF_NP_UDP & TSNIF_NP_FLAGS(nph)) memset(&nph->udp_client, 0x0, sizeof(nph->udp_client)); TSNIF_DEBUG(NP, "term detached\n"); msg->ack = 1; return tsnif_np_send_server(h, msg); } static int dispatch_server_list(struct tsnif_handle *h, struct trans_msg *msg) { return 0; } static int dispatch_server(struct tsnif_handle *h, struct trans_msg *msg) { int ret = -EINVAL; struct tsnif_np_handle *nph = &h->np; /* is there any client */ if ((TSNIF_NP_UDP & TSNIF_NP_FLAGS(nph)) && (!nph->udp_client.connected)) return 0; switch(msg->cmd) { case TSNIF_CMD_ATTACH: ret = dispatch_server_attach(h, msg); break; case TSNIF_CMD_DETACH: ret = dispatch_server_detach(h, msg); break; case TSNIF_CMD_TTY_LIST: ret = dispatch_server_list(h, msg); break; } return ret; } int tsnif_np_dispatch(struct tsnif_handle *h, struct trans_msg *msg) { struct tsnif_np_handle *nph = &h->np; if (TSNIF_NP_CLIENT & TSNIF_NP_FLAGS(nph)) return tsnif_dispatch(h, msg); if (TSNIF_NP_SERVER & TSNIF_NP_FLAGS(nph)) return dispatch_server(h, msg); return 0; } /* * host is expected to be int format: * * hostname (default port is used) * ip (default port is used) * hostname:port * ip:port * */ int tsnif_np_args(struct tsnif_np_args *args, int flag, char *host) { char *port; struct addrinfo *res, *rp; int ret; #define NP_STRINGIFY(macro_or_string) NP_STRINGIFY_ARG (macro_or_string) #define NP_STRINGIFY_ARG(contents) #contents port = strchr(host, ':'); if (port) *port++ = 0x0; else port = NP_STRINGIFY(TSNIF_NP_PORT); ret = getaddrinfo(host, port, NULL, &res); if (ret) { printf("resolve failed: %s\n", gai_strerror(ret)); return -1; } /* IPv4 so far.. */ for (rp = res; rp != NULL; rp = rp->ai_next) { if (rp->ai_family == AF_INET) break; } if (!rp) { freeaddrinfo(res); return -1; } memcpy(&args->sa, rp->ai_addr, sizeof(args->sa)); args->flags = flag; freeaddrinfo(res); return 0; }