📄 test_nat.c
字号:
if (li == NULL) return su_seterrno(EADDRNOTAVAIL); memcpy(nat->out_address, address, nat->out_addrlen = addrlen); nat->fake = li; return 0;}/* ====================================================================== */static struct binding *nat_binding_new(struct nat *nat, int in_socket, int out_socket){ struct binding *b = su_zalloc(nat->home, sizeof *b); su_sockaddr_t addr[1]; socklen_t addrlen = (sizeof addr); char name[64]; if (b == NULL) return NULL; nat_binding_insert(&nat->bindings, b); b->in_socket = in_socket, b->out_socket = out_socket; b->in_register = -1, b->out_register = -1; getpeername(in_socket, (void *)addr, &addrlen); inet_ntop(addr->su_family, SU_ADDR(addr), name, sizeof name); snprintf(b->in_name, sizeof b->in_name, addr->su_family == AF_INET6 ? "[%s]:%u" : "%s:%u", name, ntohs(addr->su_port)); getsockname(out_socket, (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)); return b;}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);}/* ====================================================================== */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; int in, out; su_wait_t win[1], wout[1]; 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; } if (nat->fake == NULL) { /* Xyzzy */ fprintf(stderr, "test_nat: fake address missing\n"); return -1; } in = su_socket(from->su_family, SOCK_DGRAM, IPPROTO_UDP); if (in < 0) { su_perror("new_udp: socket"); return 0; } if (su_setreuseaddr(in, 1) < 0) { su_perror("nat: su_setreuseaddr(in)"); su_close(in); return -1; } if (bind(in, (void *)nat->in_address, nat->in_addrlen) < 0) { su_perror("new_udp: bind(in)"); su_close(in); return 0; } if (connect(in, (void *)from, fromlen) < 0) { su_perror("new_udp: connect(in)"); su_close(in); return 0; } out = su_socket(nat->fake->li_family, SOCK_DGRAM, IPPROTO_UDP); if (out < 0) { su_perror("new_udp: socket"); su_close(in); return 0; } if (bind(out, (void *)nat->fake->li_addr, nat->fake->li_addrlen) < 0) { su_perror("new_udp: bind(to)"); su_close(in); su_close(out); return 0; } if (nat->symmetric) if (connect(out, (void *)nat->out_address, nat->out_addrlen) < 0) { su_perror("new_udp: connect(to)"); su_close(in); su_close(out); return 0; } if (su_wait_create(win, in, SU_WAIT_IN) < 0) { su_perror("new_udp: su_wait_create"); su_close(in); su_close(out); return 0; } if (su_wait_create(wout, out, SU_WAIT_IN) < 0) { su_perror("new_udp: su_wait_create"); su_wait_destroy(win); su_close(in); su_close(out); return 0; } b = nat_binding_new(nat, in, out); if (b == NULL) { su_perror("new_udp: nat_binding_new"); su_close(in); su_close(out); return 0; } b->in_register = su_root_register(nat->root, win, udp_in_to_out, b, 0); if (b->in_register < 0) { su_perror("new_udp: su_root_register"); su_wait_destroy(win); su_wait_destroy(wout); nat_binding_destroy(b); return 0; } b->out_register = su_root_register(nat->root, wout, udp_out_to_in, b, 0); if (b->out_register < 0) { su_perror("new_udp: su_root_register"); su_wait_destroy(wout); nat_binding_destroy(b); return 0; } printf("nat: new UDP binding %s <=> %s\n", b->in_name, b->out_name); 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); 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); 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); 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; su_sockaddr_t from[1]; socklen_t fromlen = (sizeof from); struct binding *b; int in, out; su_wait_t win[1], wout[1]; events = su_wait_events(wait, nat->tcp_socket); in = accept(nat->tcp_socket, (void *)from, &fromlen); if (in < 0) { su_perror("new_udp: accept"); return 0; } if (nat->fake == NULL) { /* Xyzzy */ fprintf(stderr, "test_nat: fake address missing\n"); su_close(in); return -1; } out = su_socket(nat->fake->li_family, SOCK_STREAM, IPPROTO_TCP); if (out < 0) { su_perror("new_tcp: socket"); su_close(in); return 0; } if (bind(out, (void *)nat->fake->li_addr, nat->fake->li_addrlen) < 0) { su_perror("new_tcp: bind"); su_close(in); su_close(out); return 0; } if (connect(out, (void *)nat->out_address, nat->out_addrlen) < 0) { su_perror("new_tcp: connect"); su_close(in); su_close(out); return 0; } if (su_wait_create(win, in, SU_WAIT_IN) < 0) { su_perror("new_tcp: su_wait_create"); su_close(in); su_close(out); return 0; } if (su_wait_create(wout, out, SU_WAIT_IN) < 0) { su_perror("new_tcp: su_wait_create"); su_wait_destroy(win); su_close(in); su_close(out); return 0; } b = nat_binding_new(nat, in, out); if (b == NULL) { su_perror("new_tcp: nat_binding_new"); su_close(in); su_close(out); return 0; } b->in_register = su_root_register(nat->root, win, tcp_in_to_out, b, 0); if (b->in_register < 0) { su_perror("new_tcp: su_root_register"); su_wait_destroy(win); su_wait_destroy(wout); nat_binding_destroy(b); return 0; } b->out_register = su_root_register(nat->root, wout, tcp_out_to_in, b, 0); if (b->out_register < 0) { su_perror("new_tcp: su_root_register"); su_wait_destroy(wout); nat_binding_destroy(b); return 0; } printf("nat: new TCP binding %s <=> %s\n", b->in_name, b->out_name); 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) { 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; } } 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) { 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) { su_perror("tcp_in_to_out: send"); break; } } printf("nat: tcp in %d/%d %s => %s\n", (int)m, (int)n, b->out_name, b->in_name); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -