fwudp.c revision 1c08b0ec28ca5c600c21c0ab5a53cae73f1c821d
/* -*- indent-tabs-mode: nil; -*- */
#define LOG_GROUP LOG_GROUP_NAT_SERVICE
#include "winutils.h"
#include "proxy.h"
#include "proxy_pollmgr.h"
#include "portfwd.h"
#include "pxremap.h"
#ifndef RT_OS_WINDOWS
#include <stdio.h>
#include <string.h>
#include <poll.h>
#include <err.h> /* BSD'ism */
#else
#include <stdio.h>
#include <string.h>
#include "winpoll.h"
#endif
struct fwudp_dgram {
struct pbuf *p;
};
/**
* UDP port-forwarding.
*
* Unlike pxudp that uses 1:1 mapping between pcb and socket, for
* port-forwarded UDP the setup is bit more elaborated.
*
* For fwtcp things are simple since incoming TCP connection get a new
* socket that we just hand off to pxtcp. Thus fwtcp only handles
* connection initiation.
*
* For fwudp all proxied UDP conversations share the same socket, so
* single fwudp multiplexes to several UDP pcbs.
*
* XXX: TODO: Currently pcbs point back directly to fwudp. It might
* make sense to introduce a per-pcb structure that points to fwudp
* and carries additional information, like pre-mapped peer address.
*/
struct fwudp {
/**
* Our poll manager handler.
*/
struct pollmgr_handler pmhdl;
/**
* Forwarding specification.
*/
/**
* XXX: lwip-format copy of destination
*/
/**
* Listening socket.
*/
/**
* Ring-buffer for inbound datagrams.
*/
struct {
struct fwudp_dgram *buf;
} inbuf;
struct tcpip_msg msg_delete;
};
/* poll manager callback for fwudp socket */
/* lwip thread callbacks called via proxy_lwip_post() */
static void fwudp_pcb_send(void *);
static void fwudp_pcb_delete(void *);
/**
* Linked list of active fwtcp forwarders.
*/
void
fwudp_init(void)
{
return;
}
void
{
return;
}
/* fwudp_create has put fwudp on the linked list */
}
void
{
break;
}
}
return;
}
/* let pending msg_send be processed before we delete fwudp */
}
struct fwudp *
{
int status;
if (sock == INVALID_SOCKET) {
perror("socket");
return NULL;
}
return NULL;
}
/* XXX */
}
else { /* PF_INET6 */
}
sizeof(struct fwudp_dgram));
return (NULL);
}
do { \
} while (0)
if (status < 0) {
return NULL;
}
fwudp_list = fwudp;
return fwudp;
}
/**
* Poll manager callaback for fwudp::sock
*/
int
{
struct sockaddr_storage ss;
struct fwudp_dgram *dgram;
struct pbuf *p;
int status;
if (nread < 0) {
return POLLIN;
}
/* Check that ring buffer is not full */
if (lim == 0) {
}
else {
--lim;
}
return POLLIN;
}
if (status == PXREMAP_FAILED) {
return POLLIN;
}
}
else { /* PF_INET6 */
}
if (p == NULL) {
return POLLIN;
}
pbuf_free(p);
return POLLIN;
}
dgram->p = p;
++beg;
beg = 0;
}
return POLLIN;
}
/**
* Lwip thread callback invoked via fwudp::msg_send
*/
void
fwudp_pcb_send(void *arg)
{
struct fwudp_dgram dgram;
int isv6;
/* empty buffer - shouldn't happen! */
return;
}
#if 1 /* valgrind hint */
#endif
idx = 0;
}
/* XXX: this is *STUPID* */
pprev = &udp_proxy_pcbs;
{
break;
}
else {
}
}
/*
* XXX: check that its ours and not accidentally created by
* outbound traffic.
*
* ???: Otherwise? Expire it and set pcb = NULL; to create a
* new one below?
*/
}
goto out;
}
/* equivalent of udp_bind */
/* equivalent to udp_connect */
}
out:
}
/**
* udp_recv() callback.
*/
void
{
if (p == NULL) {
DPRINTF(("%s: pcb %p (fwudp %p); sock %d: expired\n",
/* NB: fwudp is "global" and not deleted */
/* XXX: TODO: delete local reference when we will keep one */
return;
}
else {
}
}
/*
* XXX: This is pxudp_pcb_forward_outbound modulo:
* - destination is specified since host socket is not connected
*/
static void
struct pbuf *p)
{
union {
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
} peer;
#if HAVE_SA_LEN
#endif
}
else {
#if HAVE_SA_LEN
#endif
}
pbuf_free(p);
}
/**
* Lwip thread callback invoked via fwudp::msg_delete
*/
static void
fwudp_pcb_delete(void *arg)
{
pprev = &udp_proxy_pcbs;
}
else {
}
}
}