From 91acf0feb219b78e84542ea575d86dfe8bdf30ed Mon Sep 17 00:00:00 2001 From: Michael Blizek Date: Sat, 9 Jan 2016 08:03:35 +0100 Subject: [PATCH] forwards --- libcor.h | 5 +- test_listen.c | 2 +- test_routed.c | 4 +- test_routed2.c | 501 ++++++++++++++++++++++++++++++++++++++++++++++----------- 4 files changed, 410 insertions(+), 102 deletions(-) diff --git a/libcor.h b/libcor.h index 7c41a1f..2d6138a 100644 --- a/libcor.h +++ b/libcor.h @@ -273,7 +273,8 @@ extern int read_neigh_list(int fd, void *ptr, void (*next_neigh)(void *ptr, __u32 addrlen, char *addr)); -#define SOL_COR 281 +#define SOL_COR 281 + #define COR_PASS_ON_CLOSE 1 @@ -282,6 +283,8 @@ extern int read_neigh_list(int fd, void *ptr, #define CONNECTERROR_TIMEDOUT 3 #define CONNECTERROR_REFUSED 4 +#define COR_PUBLISH_SERVICE 2 + extern int pass_socket(int fd, __u64 cookie); extern int send_rdsock_version_nonblock(int fd, diff --git a/test_listen.c b/test_listen.c index 0239d15..30f13a6 100644 --- a/test_listen.c +++ b/test_listen.c @@ -42,7 +42,7 @@ int main(void) goto early_out; } - rc = bind(fd, (struct sockaddr*)&addr, sizeof(addr)); + rc = bind(fd, (struct sockaddr *) &addr, sizeof(addr)); printf("bind\n"); if(rc < 0) { perror("bind"); diff --git a/test_routed.c b/test_routed.c index 896a2dc..7c03013 100644 --- a/test_routed.c +++ b/test_routed.c @@ -394,7 +394,7 @@ struct rdscmd_connect_data{ int rds_fd; }; -static int rdscmd_void_connect(void *ptr, __u64 cookie, +static int rdscmd_connect(void *ptr, __u64 cookie, struct cor_sockaddr *addr) { int fd, rc; @@ -473,7 +473,7 @@ static int proc_rdsock_cmd(int fd, struct rdsock_cmd *cmd) if (cmd->cmd == CRD_KTU_CONNECT) { struct rdscmd_connect_data data; data.rds_fd = fd; - return parse_rdsock_connect(&data, cmd, rdscmd_void_connect); + return parse_rdsock_connect(&data, cmd, rdscmd_connect); } else { printf("error in proc_rdsock_cmd: unknown cmd: %u\n", cmd->cmd); assert(0); diff --git a/test_routed2.c b/test_routed2.c index abb775e..81947c8 100644 --- a/test_routed2.c +++ b/test_routed2.c @@ -125,8 +125,9 @@ int rdsock_fd = 0; #define EPOLLDATA_DISCOVERNETWORK 1 #define EPOLLDATA_RDSCONNECT 2 #define EPOLLDATA_RDSOCKCMD 3 -#define EPOLLDATA_FWD_TO_RSERVICE 4 -#define EPOLLDATA_FORWARD 5 +#define EPOLLDATA_FWD_TO_R 4 +#define EPOLLDATA_FWD_TO_LSERVICE 5 +#define EPOLLDATA_FORWARD 6 struct nonblock_resumeinfo_connect_to_host_send{ int fd; @@ -187,8 +188,17 @@ struct nonblock_resumeinfo{ }rdsock_cmd; struct{ + __u8 fwd_to_host; + char *addr; + __u32 addrlen; __be16 targetport; - }fwd_to_rservice; + }fwd_to_r; + + struct{ + int af; + struct sockaddr *saddr; + socklen_t saddrlen; + }fwd_to_lservice; struct{ /** @@ -206,14 +216,27 @@ struct nonblock_resumeinfo{ }data; }; -struct fwd_to_rservice_item{ +struct fwd_to_r_item{ struct list_head allfwds; int bindfd; + __u8 fwd_to_host; + char *addr; + __u32 addrlen; __be16 targetport; }; +struct fwd_to_lservice_item{ + struct list_head allfwds; + + int bindfd; + + int af; + struct sockaddr *saddr; + socklen_t saddrlen; +}; + #define offsetof(type, member) __builtin_offsetof (type, member) @@ -909,7 +932,7 @@ static void send_unreach_error(__u64 cookie) } //cookie+addr are not passed on nonblocking resume -static void _rdscmd_void_connect(struct nonblock_resumeinfo *nr) +static void _rdscmd_connect(struct nonblock_resumeinfo *nr) { int rc = RC_OK; @@ -934,13 +957,13 @@ static void _rdscmd_void_connect(struct nonblock_resumeinfo *nr) &(nr->data.rds_connect.connect_send), nr->data.rds_connect.node); nr->data.rds_connect.state = 1; - if (check_rc(rc, "_rdscmd_void_connect: connect_to_host_send error")) + if (check_rc(rc, "_rdscmd_connect: connect_to_host_send error")) goto out; state_1: rc = send_connect_port_nonblock(nr->fd, lnr, nr->data.rds_connect.port); nr->data.rds_connect.state = 2; - if (check_rc(rc, "_rdscmd_void_connect: send_connect_port error")) + if (check_rc(rc, "_rdscmd_connect: send_connect_port error")) goto out; state_2: @@ -956,7 +979,7 @@ state_2: nr->data.rds_connect.state = 3; state_3: rc = read_resp_nonblock(nr->fd, lnr); - if (check_rc(rc, "_rdscmd_void_connect: read_resp error")) + if (check_rc(rc, "_rdscmd_connect: read_resp error")) goto out; rc = pass_socket(nr->fd, nr->data.rds_connect.cookie); @@ -976,7 +999,7 @@ err: send_unreach_error(nr->data.rds_connect.cookie); } -static int rdscmd_void_connect(void *ptr, __u64 cookie, +static int rdscmd_connect(void *ptr, __u64 cookie, struct cor_sockaddr *addr) { int fd, rc; @@ -1034,7 +1057,7 @@ static int rdscmd_void_connect(void *ptr, __u64 cookie, epe.data.ptr = nr; epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &epe); - _rdscmd_void_connect(nr); + _rdscmd_connect(nr); if (0) { out: @@ -1048,7 +1071,7 @@ out_noclose: static int proc_rdsock_cmd(int fd, struct rdsock_cmd *cmd) { if (cmd->cmd == CRD_KTU_CONNECT) { - return parse_rdsock_connect(0, cmd, rdscmd_void_connect); + return parse_rdsock_connect(0, cmd, rdscmd_connect); } else { printf("error in proc_rdsock_cmd: unknown cmd: %u\n", cmd->cmd); ASSERT(0); @@ -1056,7 +1079,7 @@ static int proc_rdsock_cmd(int fd, struct rdsock_cmd *cmd) } } -static struct nonblock_resumeinfo *_init_fwd(int fd) +static struct nonblock_resumeinfo *_init_fwd(int fd, __u8 is_connected) { struct nonblock_resumeinfo *nr = malloc(sizeof(struct nonblock_resumeinfo)); @@ -1067,6 +1090,7 @@ static struct nonblock_resumeinfo *_init_fwd(int fd) nr->fd = fd; nr->type = EPOLLDATA_FORWARD; nr->data.forward.buf = malloc(FORWARD_BUF_SIZE); + nr->data.forward.is_connected = is_connected; bzero(&epe, sizeof(struct epoll_event)); epe.events = (EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLERR | EPOLLET); epe.data.ptr = nr; @@ -1076,22 +1100,26 @@ static struct nonblock_resumeinfo *_init_fwd(int fd) return nr; } -static void init_fwd(int fd0, int fd1) +static void init_fwd(int fd0, __u8 fd0connected, int fd1, __u8 fd1connected) { - struct nonblock_resumeinfo *dir0 = _init_fwd(fd0); - struct nonblock_resumeinfo *dir1 = _init_fwd(fd1); + struct nonblock_resumeinfo *dir0 = _init_fwd(fd0, fd0connected); + struct nonblock_resumeinfo *dir1 = _init_fwd(fd1, fd1connected); dir0->data.forward.reversedir = dir1; dir1->data.forward.reversedir = dir0; } -static void fwd_to_rservice_accept(int listenerfd, __be16 targetport) +static void fwd_to_r_accept(int listenerfd, __u8 fwd_to_host, char *hostaddr, + __u32 hostaddrlen, __be16 targetport) { while (1) { int localfd; struct node *node; struct cor_sockaddr addr; int remotefd; + __u8 remote_fd_isconnected = 0; + + #warning todo remote_fd_isconnected = 1 bug localfd = accept(listenerfd, 0, 0); if (localfd < 0) @@ -1099,11 +1127,25 @@ static void fwd_to_rservice_accept(int listenerfd, __be16 targetport) set_nonblock(localfd, 1); - if (service_list_contains(&(localservices), targetport) != 0) { - node = 0; - } else if ((node = try_find_neigh_byservice(targetport)) == 0) { - printf("fwd_to_rservice_accept no host with service found\n"); - goto failed; + if (fwd_to_host != 0) { + if (addr_eq(hostaddr, hostaddrlen, 0, 0) != 0 || + addr_eq(hostaddr, hostaddrlen, + localaddr, localaddrlen) != 0) { + node = 0; + } else if ((node = try_find_neigh_byaddr(hostaddrlen, + hostaddr)) == 0) { + printf("fwd_to_r_accept host not found\n"); + goto failed; + } + } else { + if (service_list_contains(&(localservices), targetport) + != 0) { + node = 0; + } else if ((node = try_find_neigh_byservice(targetport)) + == 0) { + printf("fwd_to_r_accept no host with service found\n"); + goto failed; + } } bzero(&addr, sizeof(struct cor_sockaddr)); @@ -1116,6 +1158,7 @@ static void fwd_to_rservice_accept(int listenerfd, __be16 targetport) memcpy(&(addr.addr[0]), node->addr, node->addrlen); } + remotefd = socket(PF_COR, SOCK_STREAM, 0); if (remotefd == -1) { perror("socket"); @@ -1126,20 +1169,66 @@ static void fwd_to_rservice_accept(int listenerfd, __be16 targetport) if (connect(remotefd, (struct sockaddr *) &addr, sizeof(struct cor_sockaddr)) != 0) { - perror("connect"); - goto failed; + if (errno == EINPROGRESS) { + remote_fd_isconnected = 0; + } else { + perror("connect"); + goto failed; + } } - init_fwd(localfd, remotefd); + init_fwd(localfd, 1, remotefd, remote_fd_isconnected); if (0) { failed: close(localfd); } + } +} + +static void fwd_to_lservice_accept(int listenerfd, int af, + struct sockaddr *saddr, socklen_t saddrlen) +{ + while (1) { + int localfd; + int remotefd; + __u8 remote_fd_isconnected = 1; + + localfd = accept(listenerfd, 0, 0); + + if (localfd < 0) + return; + + set_nonblock(localfd, 1); + + remotefd = socket(af, SOCK_STREAM, 0); + if (remotefd == -1) { + perror("socket"); + goto failed; + } + + set_nonblock(remotefd, 1); + + if (connect(remotefd, saddr, saddrlen) != 0) { + if (errno == EINPROGRESS) { + remote_fd_isconnected = 0; + } else { + perror("connect"); + goto failed; + } + } + init_fwd(localfd, 1, remotefd, remote_fd_isconnected); + + if (0) { +failed: + close(localfd); + } } } + + #define RC_FORWARD_OK 1 #define RC_FORWARD_WOULDBLOCK 2 #define RC_FORWARD_ERROR 3 @@ -1268,9 +1357,8 @@ static void forward(struct nonblock_resumeinfo *nr, __u32 eventflags) ASSERT(nr->type == EPOLLDATA_FORWARD); ASSERT(nr->data.forward.reversedir->type == EPOLLDATA_FORWARD); - if ((eventflags & EPOLLOUT) != 0) { + if ((eventflags & EPOLLOUT) != 0) nr->data.forward.is_connected = 1; - } if (nr->data.forward.is_connected == 0 || nr->data.forward.reversedir->data.forward.is_connected @@ -1300,7 +1388,7 @@ static void nonblock_resume(struct nonblock_resumeinfo *nr, __u32 eventflags) if (rc != RC_OK) return; - _rdscmd_void_connect(nr); + _rdscmd_connect(nr); } else if (nr->type == EPOLLDATA_RDSOCKCMD) { struct rdsock_cmd cmd; @@ -1319,9 +1407,15 @@ static void nonblock_resume(struct nonblock_resumeinfo *nr, __u32 eventflags) rc = proc_rdsock_cmd(rdsock_fd, &cmd); free_rdsockcmd_data(&cmd); ASSERT(rc == 0); - } else if (nr->type == EPOLLDATA_FWD_TO_RSERVICE) { - fwd_to_rservice_accept(nr->fd, - nr->data.fwd_to_rservice.targetport); + } else if (nr->type == EPOLLDATA_FWD_TO_R) { + fwd_to_r_accept(nr->fd, nr->data.fwd_to_r.fwd_to_host, + nr->data.fwd_to_r.addr, + nr->data.fwd_to_r.addrlen, + nr->data.fwd_to_r.targetport); + } else if (nr->type == EPOLLDATA_FWD_TO_LSERVICE) { + fwd_to_lservice_accept(nr->fd, nr->data.fwd_to_lservice.af, + nr->data.fwd_to_lservice.saddr, + nr->data.fwd_to_lservice.saddrlen); } else if (nr->type == EPOLLDATA_FORWARD) { forward(nr, eventflags); } else { @@ -1370,12 +1464,43 @@ static int rdsock_negotiate_version(void) return 0; } -static void epoll_add_fwd_to_rservice(struct list_head *rservice_fwds) +static void epoll_add_fwd_to_r(struct list_head *r_fwds) +{ + while (list_empty(r_fwds) == 0) { + struct fwd_to_r_item *item = container_of(r_fwds->next, + struct fwd_to_r_item, allfwds); + + struct nonblock_resumeinfo *nr; + + struct epoll_event epe; + + set_nonblock(item->bindfd, 1); + + nr = malloc(sizeof(struct nonblock_resumeinfo)); + bzero(nr, sizeof(struct nonblock_resumeinfo)); + nr->fd = item->bindfd; + nr->type = EPOLLDATA_FWD_TO_R; + nr->data.fwd_to_r.fwd_to_host = item->fwd_to_host; + nr->data.fwd_to_r.addr = item->addr; + nr->data.fwd_to_r.addrlen = item->addrlen; + nr->data.fwd_to_r.targetport = item->targetport; + bzero(&epe, sizeof(struct epoll_event)); + epe.events = (EPOLLIN | EPOLLERR); + epe.data.ptr = nr; + + epoll_ctl(epoll_fd, EPOLL_CTL_ADD, item->bindfd, &epe); + + list_del(&(item->allfwds)); + free(item); + } +} + +static void epoll_add_fwd_to_lservice(struct list_head *lservice_fwds) { - while (list_empty(rservice_fwds) == 0) { - struct fwd_to_rservice_item *item = container_of( - rservice_fwds->next, - struct fwd_to_rservice_item, + while (list_empty(lservice_fwds) == 0) { + struct fwd_to_lservice_item *item = container_of( + lservice_fwds->next, + struct fwd_to_lservice_item, allfwds); struct nonblock_resumeinfo *nr; @@ -1387,8 +1512,10 @@ static void epoll_add_fwd_to_rservice(struct list_head *rservice_fwds) nr = malloc(sizeof(struct nonblock_resumeinfo)); bzero(nr, sizeof(struct nonblock_resumeinfo)); nr->fd = item->bindfd; - nr->type = EPOLLDATA_FWD_TO_RSERVICE; - nr->data.fwd_to_rservice.targetport = item->targetport; + nr->type = EPOLLDATA_FWD_TO_LSERVICE; + nr->data.fwd_to_lservice.af = item->af; + nr->data.fwd_to_lservice.saddr = item->saddr; + nr->data.fwd_to_lservice.saddrlen = item->saddrlen; bzero(&epe, sizeof(struct epoll_event)); epe.events = (EPOLLIN | EPOLLERR); epe.data.ptr = nr; @@ -1400,6 +1527,7 @@ static void epoll_add_fwd_to_rservice(struct list_head *rservice_fwds) } } + static int parse_hexchar(char c) { if (c == '0') @@ -1460,26 +1588,27 @@ static int parse_hex(char *target, char *src, int srclen) return 0; } -static int parse_addr(char *argv_addr) +static int _parse_addr(char *arg, size_t arg_len, char **addr, __u32 *addrlen, + int noaddr_allowed) { - int rc; - int len = strlen(argv_addr); char *noaddr = "noaddr"; - if (strncmp(argv_addr, noaddr, len) == 0) { - localaddr = 0; - localaddrlen = 0; + if (arg_len > 1048576) + return 1; + + if (noaddr_allowed != 0 && arg_len == 6 && memcmp(arg, noaddr, 6) == 0){ + *addr = 0; + *addrlen = 0; return 0; } - if ((len < 2) || (len%2) != 0) + if ((arg_len < 2) || (arg_len%2) != 0) goto parseerror; - localaddr = malloc(len/2); - localaddrlen = len/2; + *addr = malloc(arg_len/2); + *addrlen = arg_len/2; - rc = parse_hex(localaddr, argv_addr, len); - if (rc != 0) + if (parse_hex(*addr, arg, arg_len) != 0) goto parseerror; return 0; @@ -1488,10 +1617,36 @@ parseerror: fprintf(stderr, "error: argv_addr is not a valid address (contains " "non-hex characters or number of hex characters is not " "a multiple of 2)\n"); - return -1; + return 1; } -static int parse_port(char *arg, __u32 len, __u16 *port) +static size_t _parse_addr_lastarglen(char *arg, size_t len) +{ + size_t lastarglen = 0; + + while (lastarglen < len) { + if (arg[len-lastarglen-1] == ':') + break; + lastarglen++; + } + return lastarglen; +} + +static int parse_addr(char *arg, size_t arg_len, size_t *arg_addrlen, + char **addr, __u32 *addrlen) +{ + size_t lastarglen = _parse_addr_lastarglen(arg, arg_len); + + if (lastarglen == 0 || lastarglen >= arg_len) + return 1; + + *arg_addrlen = lastarglen + 1; // +1 ... ':' + + return _parse_addr(arg + arg_len - lastarglen, lastarglen, + addr, addrlen, 0); +} + +static int _parse_port(char *arg, size_t len, __u16 *port) { char *tmpbuf; char *endptr = 0; @@ -1515,13 +1670,52 @@ static int parse_port(char *arg, __u32 len, __u16 *port) return 1; *port = (__u16) tmpport; + + return 0; +} + +static int parse_port_firstarg(char *arg, size_t len, size_t *p_portlen, + __u16 *port) +{ + size_t portlen = 0; + + while (portlen < len) { + if (arg[portlen] == ':') + break; + portlen++; + } + + if (portlen == 0 || portlen >= len) + return 1; + + if (_parse_port(arg, portlen, port) != 0) + return 1; + + *p_portlen = portlen + 1;// +1 ... ':' return 0; } -static int parse_inetaddr(char *addr, __u32 len, int *af, +static int parse_port_lastarg(char *arg, size_t len, size_t *p_portlen, + __u16 *port) +{ + size_t portlen = 0; + + portlen = _parse_addr_lastarglen(arg, len); + + if (portlen == 0 || portlen >= len) + return 1; + + if (_parse_port(arg + len - portlen, portlen, port) != 0) + return 1; + + *p_portlen = portlen + 1;// +1 ... ':' + return 0; +} + +static int parse_inetaddr(char *addr, size_t len, int *af, struct sockaddr **saddr, socklen_t *saddrlen) { - __u32 idx = len - 1; + size_t portlen = 0; __u16 port; @@ -1530,22 +1724,15 @@ static int parse_inetaddr(char *addr, __u32 len, int *af, struct in_addr inaddr; struct in6_addr in6addr; - while (idx > 0) { - if (addr[idx] == ':') { - break; - } - idx--; - } - - if (idx <= 0 || idx >= len - 1) + if (parse_port_lastarg(addr, len, &portlen, &port) != 0) return 1; - if (parse_port(addr + idx + 1, len - idx - 1, &port) != 0) + if (portlen >= len) return 1; - host = malloc(idx + 1); - memcpy(host, addr, idx); - host[idx] = 0; + host = malloc(len - portlen + 1); + memcpy(host, addr, len - portlen); + host[len - portlen] = 0; if (inet_pton(AF_INET, host, &inaddr) == 1) { struct sockaddr_in *ret; @@ -1579,44 +1766,45 @@ static int parse_inetaddr(char *addr, __u32 len, int *af, } } -static int parse_fwd_to_rservice(char *argv_fwd, - struct list_head *rservice_fwds) +static int parse_fwd_to_r(char *argv_fwd, + struct list_head *r_fwds, __u8 fwd_to_host) { - struct fwd_to_rservice_item *item; + struct fwd_to_r_item *item; int af; struct sockaddr *saddr; socklen_t saddrlen; + size_t portlen = 0; + + char *addr = 0; + __u32 addrlen = 0; __u16 serviceport; - __u32 idx = 0; - __u32 len = 0; + size_t len = strlen(argv_fwd); int optval; - while (1) { - if (argv_fwd[len] == 0) { - break; - } else if (argv_fwd[len] == ':') { - idx = len; - } - len++; - } - - if (idx <= 0 || idx >= len - 1) + if (parse_port_lastarg(argv_fwd, len, &portlen, &serviceport) != 0) return 1; - if (parse_inetaddr(argv_fwd, idx, &af, &saddr, &saddrlen) != 0) - return 1; + len -= portlen; - if (parse_port(argv_fwd + idx + 1, len - idx - 1, &serviceport) != 0) + if (fwd_to_host != 0) { + size_t arg_addrlen = 0; + if (parse_addr(argv_fwd, len, &arg_addrlen, + &addr, &addrlen) != 0) + return 1; + len -= arg_addrlen; + } + + if (parse_inetaddr(argv_fwd, len, &af, &saddr, &saddrlen) != 0) return 1; - item = malloc(sizeof(struct fwd_to_rservice_item)); + item = malloc(sizeof(struct fwd_to_r_item)); item->bindfd = socket(af, SOCK_STREAM, 0); if (item->bindfd < 0) { perror("socket"); - goto err; + goto err_noclose; } optval = 1; if (setsockopt(item->bindfd, SOL_SOCKET, SO_REUSEADDR, &optval, @@ -1624,12 +1812,84 @@ static int parse_fwd_to_rservice(char *argv_fwd, perror("setsockopt"); goto err; } - if (setsockopt(item->bindfd, SOL_SOCKET, SO_REUSEADDR, &optval, + if (bind(item->bindfd, saddr, saddrlen) != 0) { + perror("bind"); + goto err; + } + if (listen(item->bindfd, 100) != 0) { + perror("listen"); + goto err; + } + item->fwd_to_host = fwd_to_host; + if (fwd_to_host) { + item->addr = addr; + item->addrlen = addrlen; + } + item->targetport = htons(serviceport); + + list_add_tail(&(item->allfwds), r_fwds); + + free(saddr); + + return 0; + +err: + close(item->bindfd); +err_noclose: + free(item); + free(saddr); + + return 1; +} + +static int parse_fwd_to_lservice(char *argv_fwd, + struct list_head *lservice_fwds, __u8 publish) +{ + size_t portlen = 0; + + __u16 serviceport; + + struct cor_sockaddr bind_saddr; + + int optval; + + struct fwd_to_lservice_item *item; + + int af; + struct sockaddr *saddr; + socklen_t saddrlen; + + size_t len = strlen(argv_fwd); + + if (parse_port_firstarg(argv_fwd, len, &portlen, &serviceport) != 0) + return 1; + + argv_fwd += portlen; + len -= portlen; + + if (parse_inetaddr(argv_fwd, len, &af, &saddr, &saddrlen) != 0) + return 1; + + memset(&bind_saddr, 0, sizeof(struct cor_sockaddr)); + bind_saddr.sin_family = AF_COR; + bind_saddr.port = htons(serviceport); + + #warning todo + + item = malloc(sizeof(struct fwd_to_lservice_item)); + item->bindfd = socket(PF_COR, SOCK_STREAM, 0); + if (item->bindfd < 0) { + perror("socket"); + goto err; + } + optval = publish == 0 ? 0 : 1; + if (setsockopt(item->bindfd, SOL_COR, COR_PUBLISH_SERVICE, &optval, sizeof(optval)) != 0) { perror("setsockopt"); goto err; } - if (bind(item->bindfd, saddr, saddrlen) != 0) { + if (bind(item->bindfd, (struct sockaddr *) &bind_saddr, + sizeof(bind_saddr)) != 0) { perror("bind"); goto err; } @@ -1637,28 +1897,32 @@ static int parse_fwd_to_rservice(char *argv_fwd, perror("listen"); goto err; } - item->targetport = htons(serviceport); - list_add_tail(&(item->allfwds), rservice_fwds); + item->af = af; + item->saddr = saddr; + item->saddrlen = saddrlen; - free(saddr); + list_add_tail(&(item->allfwds), lservice_fwds); return 0; err: + close(item->bindfd); +err_noclose: free(item); free(saddr); return 1; } -static int parse_args(int argc, char *argv[], struct list_head *rservice_fwds) +static int parse_args(int argc, char *argv[], struct list_head *r_fwds, + struct list_head *lservice_fwds) { int rc; int addrfound = 0; __u32 argsconsumed = 0; - if (argc > 1000000) + if (argc > 10000) goto usage; while (1) { @@ -1672,7 +1936,9 @@ static int parse_args(int argc, char *argv[], struct list_head *rservice_fwds) if (addrfound != 0) goto usage; - rc = parse_addr(argv[argsconsumed + 2]); + rc = _parse_addr(argv[argsconsumed + 2], + strlen(argv[argsconsumed + 2]), + &localaddr, &localaddrlen, 1); if (rc != 0) goto usage; @@ -1689,8 +1955,40 @@ static int parse_args(int argc, char *argv[], struct list_head *rservice_fwds) if (argc <= argsconsumed + 2) goto usage; - rc = parse_fwd_to_rservice(argv[argsconsumed + 2], - rservice_fwds); + rc = parse_fwd_to_r(argv[argsconsumed + 2], + r_fwds, 0); + if (rc != 0) + goto usage; + + argsconsumed += 2; + } else if (strcmp(argv[argsconsumed + 1], + "--fwd-to-rhost") == 0) { + if (argc <= argsconsumed + 2) + goto usage; + + rc = parse_fwd_to_r(argv[argsconsumed + 2], + r_fwds, 1); + if (rc != 0) + goto usage; + + argsconsumed += 2; + } else if (strcmp(argv[argsconsumed + 1], + "--fwd-to-lservice") == 0) { + if (argc <= argsconsumed + 2) + goto usage; + + rc = parse_fwd_to_lservice(argv[argsconsumed + 2], + lservice_fwds, 0); + if (rc != 0) + goto usage; + argsconsumed += 2; + } else if (strcmp(argv[argsconsumed + 1], + "--fwd-to-lservice-pub") == 0) { + if (argc <= argsconsumed + 2) + goto usage; + + rc = parse_fwd_to_lservice(argv[argsconsumed + 2], + lservice_fwds, 1); if (rc != 0) goto usage; @@ -1708,6 +2006,9 @@ usage: fprintf(stderr, "usage: test_routed2" " [--export-servicelist]" " [--fwd-to-rservice bindaddr:bindport:remoteport]" + " [--fwd-to-rhost bindaddr:bindport:remotaaddr:remoteport]" + " [--fwd-to-lservice bindport:localaddr:localport]" + " [--fwd-to-lservice-pub bindport:localaddr:localport]" " --addr addr (even number of hex digits or noaddr)\n"); rc = 1; } @@ -1718,7 +2019,8 @@ usage: int main(int argc, char *argv[]) { int rc; - struct list_head rservice_fwds; + struct list_head r_fwds; + struct list_head lservice_fwds; struct nonblock_resumeinfo rds_nr; @@ -1727,11 +2029,12 @@ int main(int argc, char *argv[]) discover_finished = 0; epoll_fd = 0; - init_list_head(&rservice_fwds); + init_list_head(&r_fwds); + init_list_head(&lservice_fwds); umask(0); - rc = parse_args(argc, argv, &rservice_fwds); + rc = parse_args(argc, argv, &r_fwds, &lservice_fwds); if (rc != 0) goto out; @@ -1766,6 +2069,8 @@ int main(int argc, char *argv[]) set_nonblock(rdsock_fd, 1); + epoll_add_fwd_to_lservice(&lservice_fwds); + sleep(30); discover_network(0, 0); @@ -1787,7 +2092,7 @@ int main(int argc, char *argv[]) epoll_ctl(epoll_fd, EPOLL_CTL_ADD, rdsock_fd, &rds_epe); - epoll_add_fwd_to_rservice(&rservice_fwds); + epoll_add_fwd_to_r(&r_fwds); discover_finished_executed = 1; printf("discover finished\n"); -- 2.11.4.GIT