#include #include #include #include "intf.h" #include "net-proxy.h" #include "debug.h" static int init_fd(struct tsnif_handle *h, struct tsnif_np_args *args, int server) { struct tsnif_np_handle *nph = &h->np; struct sockaddr_in *sa = &args->sa; int fd; fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (-1 == fd) { TSNIF_DEBUG(NP, "failed to create udp socket\n"); return -1; } nph->fd_udp = fd; if (server) { if (-1 == bind(fd, sa, sizeof(*sa))) { close(fd); TSNIF_DEBUG(NP, "failed to bind\n"); return -1; } } TSNIF_DEBUG(NP, "socket created %d\n", fd); return 0; } int udp_init_server(struct tsnif_handle *h, struct tsnif_np_args *args) { TSNIF_DEBUG(NP, "creating server socket\n"); return init_fd(h, args, 1); } int udp_init_client(struct tsnif_handle *h, struct tsnif_np_args *args) { TSNIF_DEBUG(NP, "creating client socket\n"); return init_fd(h, args, 0); } int udp_close(struct tsnif_handle *h) { struct tsnif_np_handle *nph = &h->np; TSNIF_DEBUG(NP, "closing client socket\n"); close(nph->fd_udp); return 0; } int udp_send(struct tsnif_handle *h, struct trans_msg *msg) { struct tsnif_np_msg *m; struct tsnif_np_handle *nph = &h->np; int size = sizeof(*msg); TSNIF_DEBUG(NP, "sending cmd = %d\n", msg->cmd); if (TSNIF_CMD_DATA == msg->cmd) size += msg->data.len; m = malloc(size); if (!m) return -1; m->msg = *msg; if (TSNIF_CMD_DATA == msg->cmd) memcpy(m->data, msg->data.ptr, msg->data.len); if (TSNIF_NP_UDP_SERVER & TSNIF_NP_FLAGS(nph)) return sendto(nph->fd_udp, m, size, 0, &nph->udp_client.sa, sizeof(nph->udp_client.sa)); return sendto(nph->fd_udp, m, size, 0, &nph->args->sa, sizeof(nph->args->sa)); } int udp_process(struct tsnif_handle *h) { struct tsnif_np_handle *nph = &h->np; struct trans_msg msg; char *data = NULL; int ret; struct sockaddr_in sa; socklen_t sl = sizeof(sa); ret = recvfrom(nph->fd_udp, &msg, sizeof(msg), 0, &sa, &sl); if (ret <= 0) return ret; /* just one client supported for now */ if (memcmp(&nph->udp_client.sa, &sa, sizeof(sa))) { TSNIF_DEBUG(NP, "got new client\n"); memset(&nph->udp_client, 0x0, sizeof(nph->udp_client)); nph->udp_client.sa = sa; nph->udp_client.connected = 1; } /* receive the data part */ if (TSNIF_CMD_DATA == msg.cmd) { /* XXX some size check would be nice.. */ data = malloc(msg.data.len); if (!data) return -1; ret = recvfrom(nph->fd_udp, data, msg.data.len, 0, &sa, &sl); if (ret <= 0) { free(data); return ret; } msg.data.ptr = data; } ret = tsnif_np_dispatch(h, &msg); if (data) free(data); return ret; } struct tsnif_np_prot udp_prot = { .init_server = udp_init_server, .init_client = udp_init_client, .close = udp_close, .send = udp_send, .process = udp_process, };