📄 test_nat.c
字号:
b = su_zalloc(nat->home, sizeof *b); if (b == NULL) { su_perror("nat_binding_new: su_zalloc"); su_close(in_socket); return 0; } b->nat = nat; b->socktype = socktype; b->protocol = protocol; b->in_socket = in_socket, b->out_socket = -1; b->in_register = -1, b->out_register = -1; if (binding_init(b, protoname, connected, nat->fake, from, fromlen) < 0) nat_binding_destroy(b), b = NULL; return b;}static int binding_init(struct binding *b, char const *protoname, int connected, su_localinfo_t *li, su_sockaddr_t *from, socklen_t fromlen){ struct nat *nat = b->nat; int out_socket; su_sockaddr_t addr[1]; socklen_t addrlen = (sizeof addr); char ipname[64]; su_wait_t wait[1]; su_wakeup_f in_to_out, out_to_in; if (b->socktype == SOCK_STREAM) in_to_out = tcp_in_to_out, out_to_in = tcp_out_to_in; else in_to_out = udp_in_to_out, out_to_in = udp_out_to_in; if (b->in_socket == -1) { int in_socket; in_socket = su_socket(from->su_family, b->socktype, b->protocol); if (in_socket < 0) { su_perror("nat_binding_new: socket"); return -1; } b->in_socket = in_socket; if (su_setreuseaddr(in_socket, 1) < 0) { su_perror("nat_binding_new: su_setreuseaddr(in_socket)"); return -1; } if (bind(in_socket, (void *)nat->in_address, nat->in_addrlen) < 0) { su_perror("nat_binding_new: bind(in_socket)"); return -1; } if (connect(in_socket, (void *)from, fromlen) < 0) { su_perror("nat_binding_new: connect(in_socket)"); return -1; } } out_socket = su_socket(li->li_family, b->socktype, b->protocol); if (out_socket < 0) { su_perror("nat_binding_new: socket"); return -1; } b->out_socket = out_socket; if (bind(out_socket, (void *)li->li_addr, li->li_addrlen) < 0) { su_perror("nat_binding_new: bind(to)"); return -1; } if (connected) if (connect(out_socket, (void *)nat->out_address, nat->out_addrlen) < 0) { su_perror("nat_binding_new: connect(to)"); return -1; } getpeername(b->in_socket, (void *)addr, &addrlen); inet_ntop(addr->su_family, SU_ADDR(addr), ipname, sizeof ipname); snprintf(b->in_name, sizeof b->in_name, addr->su_family == AF_INET6 ? "[%s]:%u" : "%s:%u", ipname, ntohs(addr->su_port)); getsockname(out_socket, (void *)addr, &addrlen); inet_ntop(addr->su_family, SU_ADDR(addr), ipname, sizeof ipname); snprintf(b->out_name, sizeof b->out_name, addr->su_family == AF_INET6 ? "[%s]:%u" : "%s:%u", ipname, ntohs(addr->su_port)); if (su_wait_create(wait, b->in_socket, SU_WAIT_IN) < 0) { su_perror("nat_binding_new: su_wait_create"); return -1; } b->in_register = su_root_register(nat->root, wait, in_to_out, b, 0); if (b->in_register < 0) { su_perror("nat_binding_new: su_root_register"); su_wait_destroy(wait); return -1; } if (su_wait_create(wait, out_socket, SU_WAIT_IN) < 0) { su_perror("nat_binding_new: su_wait_create"); return -1; } b->out_register = su_root_register(nat->root, wait, out_to_in, b, 0); if (b->out_register < 0) { su_perror("nat_binding_new: su_root_register"); su_wait_destroy(wait); return -1; } nat_binding_insert(&nat->bindings, b); if (nat->logging) printf("nat: new %s binding %s <=> %s\n", protoname, b->in_name, b->out_name); return 0;}static void nat_binding_destroy(struct binding *b){ nat_binding_remove(b); if (b->in_register != -1) su_root_deregister(b->nat->root, b->in_register); if (b->out_register != -1) su_root_deregister(b->nat->root, b->out_register); su_close(b->in_socket), su_close(b->out_socket);}static void flush_bindings(struct nat *nat){ struct binding *b; for (b = nat->bindings; b; b = b->next) { if (b->in_register) su_root_deregister(nat->root, b->in_register); su_close(b->in_socket); if (b->out_register) su_root_deregister(nat->root, b->out_register); su_close(b->out_socket); }}static void invalidate_bindings(struct nat *nat){ struct binding *b; for (b = nat->bindings; b; b = b->next) { invalidate_binding(b); }}#if 0static struct binding *nat_binding_find(struct nat *nat, su_sockaddr_t *from, int fromlen){ char name[64], ipname[64]; size_t namelen; struct binding *b; inet_ntop(from->su_family, SU_ADDR(from), ipname, sizeof ipname); snprintf(name, sizeof name, from->su_family == AF_INET6 ? "[%s]:%u" : "%s:%u", ipname, ntohs(from->su_port)); namelen = strlen(name) + 1; for (b = nat->bindings; b; b = b->next) { if (memcmp(name, b->in_name, namelen) == 0) return b; } if (b == NULL) b = nat_binding_new(nat, "UDP", SOCK_DGRAM, IPPROTO_UDP, nat->symmetric, -1, from, fromlen); return b;}#endif/* ====================================================================== */LIST_BODIES(static, nat_binding, struct binding, next, prev);/* ====================================================================== */static int new_udp(struct nat *nat, su_wait_t *wait, struct binding *dummy){ int events; su_sockaddr_t from[1]; socklen_t fromlen = (sizeof from); struct binding *b; ssize_t n, m; events = su_wait_events(wait, nat->udp_socket); n = recvfrom(nat->udp_socket, nat->buffer, sizeof nat->buffer, 0, (void *)from, &fromlen); if (n < 0) { su_perror("new_udp: recvfrom"); return 0; } b = nat_binding_new(nat, "UDP", SOCK_DGRAM, IPPROTO_UDP, nat->symmetric, -1, from, fromlen); if (b == NULL) return 0; if (nat->symmetric) m = send(b->out_socket, nat->buffer, n, 0); else m = sendto(b->out_socket, nat->buffer, n, 0, (void *)nat->out_address, nat->out_addrlen); if (nat->logging) printf("nat: udp out %d/%d %s => %s\n", (int)m, (int)n, b->in_name, b->out_name); return 0;}static int udp_in_to_out(struct nat *nat, su_wait_t *wait, struct binding *b){ int events; ssize_t n, m; events = su_wait_events(wait, b->in_socket); n = recv(b->in_socket, nat->buffer, sizeof nat->buffer, 0); if (n < 0) { su_perror("udp_in_to_out: recv"); return 0; } if (nat->symmetric) m = send(b->out_socket, nat->buffer, n, 0); else m = sendto(b->out_socket, nat->buffer, n, 0, (void *)nat->out_address, nat->out_addrlen); if (nat->logging) printf("nat: udp out %d/%d %s => %s\n", (int)m, (int)n, b->in_name, b->out_name); return 0;}static int udp_out_to_in(struct nat *nat, su_wait_t *wait, struct binding *b){ int events; ssize_t n, m; events = su_wait_events(wait, b->out_socket); n = recv(b->out_socket, nat->buffer, sizeof nat->buffer, 0); if (n < 0) { su_perror("udp_out_to_out: recv"); return 0; } m = send(b->in_socket, nat->buffer, n, 0); if (nat->logging) printf("nat: udp in %d/%d %s => %s\n", (int)m, (int)n, b->out_name, b->in_name); return 0;}/* ====================================================================== */static int new_tcp(struct nat *nat, su_wait_t *wait, struct binding *dummy){ int events; int in_socket; su_sockaddr_t from[1]; socklen_t fromlen = (sizeof from); struct binding *b; events = su_wait_events(wait, nat->tcp_socket); in_socket = accept(nat->tcp_socket, (void *)from, &fromlen); if (in_socket < 0) { su_perror("new_tcp: accept"); return 0; } b = nat_binding_new(nat, "TCP", SOCK_STREAM, IPPROTO_TCP, 1, in_socket, from, fromlen); if (b == NULL) return 0; return 0;}static int tcp_in_to_out(struct nat *nat, su_wait_t *wait, struct binding *b){ int events; ssize_t n, m, o; events = su_wait_events(wait, b->in_socket); n = recv(b->in_socket, nat->buffer, sizeof nat->buffer, 0); if (n < 0) { su_perror("tcp_in_to_out: recv"); return 0; } if (n == 0) { if (nat->logging) printf("nat: tcp out FIN %s => %s\n", b->in_name, b->out_name); shutdown(b->out_socket, 1); su_root_eventmask(nat->root, b->in_register, b->in_socket, 0); b->in_closed = 1; if (b->out_closed && b->in_closed) nat_binding_destroy(b); return 0; } for (m = 0; m < n; m += o) { o = send(b->out_socket, nat->buffer + m, n - m, 0); if (o < 0) { su_perror("tcp_in_to_out: send"); break; } } if (nat->logging) printf("nat: tcp out %d/%d %s => %s\n", (int)m, (int)n, b->in_name, b->out_name); return 0;}static int tcp_out_to_in(struct nat *nat, su_wait_t *wait, struct binding *b){ int events; ssize_t n, m, o; events = su_wait_events(wait, b->out_socket); n = recv(b->out_socket, nat->buffer, sizeof nat->buffer, 0); if (n < 0) { su_perror("tcp_out_to_in: recv"); return 0; } if (n == 0) { if (nat->logging) printf("nat: tcp out FIN %s => %s\n", b->out_name, b->in_name); shutdown(b->in_socket, 1); su_root_eventmask(nat->root, b->in_register, b->out_socket, 0); b->out_closed = 1; if (b->out_closed && b->in_closed) nat_binding_destroy(b); return 0; } for (m = 0; m < n; m += o) { o = send(b->in_socket, nat->buffer + m, n - m, 0); if (o < 0) { if (su_errno() != EPIPE) su_perror("tcp_in_to_out: send"); break; } } if (nat->logging) printf("nat: tcp in %d/%d %s => %s\n", (int)m, (int)n, b->out_name, b->in_name); return 0;}static int invalidate_binding(struct binding *b){ struct nat *nat = b->nat; su_sockaddr_t addr[1]; socklen_t addrlen = (sizeof addr); int out, out_register; su_wait_t wout[1]; char name[64]; out = su_socket(nat->fake->li_family, b->socktype, 0); if (out < 0) { su_perror("new_udp: socket"); return -1; } if (bind(out, (void *)nat->fake->li_addr, nat->fake->li_addrlen) < 0) { su_perror("new_udp: bind(to)"); su_close(out); return -1; } if (nat->symmetric) if (connect(out, (void *)nat->out_address, nat->out_addrlen) < 0) { su_perror("new_udp: connect(to)"); su_close(out); return -1; } if (su_wait_create(wout, out, SU_WAIT_IN) < 0) { su_perror("new_udp: su_wait_create"); su_close(out); return -1; } if (b->socktype == SOCK_DGRAM) out_register = su_root_register(nat->root, wout, udp_out_to_in, b, 0); else out_register = su_root_register(nat->root, wout, tcp_out_to_in, b, 0); if (out_register < 0) { su_perror("new_udp: su_root_register"); su_wait_destroy(wout); su_close(out); return -1; } su_root_deregister(nat->root, b->out_register); su_close(b->out_socket); b->out_socket = out; b->out_register = out_register; getsockname(out, (void *)addr, &addrlen); inet_ntop(addr->su_family, SU_ADDR(addr), name, sizeof name); snprintf(b->out_name, sizeof b->out_name, addr->su_family == AF_INET6 ? "[%s]:%u" : "%s:%u", name, ntohs(addr->su_port)); if (nat->logging) printf("nat: flushed binding %s <=> %s\n", b->in_name, b->out_name); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -