📄 sockd_request.c
字号:
if (connect(sv[reply], &clientaddr, sizeof(clientaddr)) != 0) { iolog(&bindio.rule, &bindio.state, OPERATION_ABORT, &bindio.src, &bindio.dst, NULL, 0); break; } } if (bindio.state.extension.bind) { /* * flushio() will close all descriptors set in io packet * so dup what we need to keep going. */ if ((bindio.control.s = dup(sv[childpipe])) == -1) { switch (errno) { case EMFILE: case ENFILE: swarn("%s: dup()", function); ++emfile; continue; default: SERR(bindio.control.s); } } } else bindio.control.s = sv[client]; bindio.control.laddr = request->to; bindio.control.raddr = request->from; bindio.control.state = bindio.state; /* back to blocking. */ if (fcntl(sv[remote], F_SETFL, flags) == -1) { swarn("%s: fcntl()", function); break; } if (bindio.state.extension.bind) { bindio.in.s = sv[reply]; bindio.in.laddr = replyaddr; bindio.in.state = bindio.state; } else { bindio.in = bindio.control; bindio.in.laddr = request->from; } /* LINTED pointer casts may be troublesome */ bindio.in.raddr = *(struct sockaddr_in *)&clientaddr; bindio.out.s = sv[remote]; /* LINTED pointer casts may be troublesome */ bindio.out.laddr = *(struct sockaddr_in *)&boundaddr; /* LINTED pointer casts may be troublesome */ bindio.out.raddr = *(struct sockaddr_in *)&remoteaddr; bindio.out.state.auth.method = AUTHMETHOD_NONE; if (bindio.state.extension.bind) /* add to list, client will query. */ iolist = io_add(iolist, &bindio); else { response.host = bindio.dst; flushio(mother, sv[client], &response, &bindio); sv[client] = sv[remote] = -1; /* flushio() closes; closev(). */ break; /* only one connection to relay and that is done. */ } } if (bindio.state.extension.bind) { struct sockd_io_t *rmio; /* delete any connections we have queued. */ while ((rmio = io_find(iolist, NULL)) != NULL) { close_iodescriptors(rmio); iolist = io_remove(iolist, rmio); } } closev(sv, ELEMENTS(sv)); break; } case SOCKS_CONNECT: { socklen_t sinlen; if (socks_connect(out, &io.dst) != 0) { iolog(&io.rule, &io.state, OPERATION_ABORT, &io.src, &io.dst, NULL, 0); send_failure(request->s, &response, errno2reply(errno, response.version)); close(request->s); break; } io.in.s = request->s; io.in.laddr = request->to; io.in.raddr = request->from; io.in.state = io.state; io.out.s = out; io.out.state = io.state; sinlen = sizeof(io.out.raddr); /* LINTED pointer casts may be troublesome */ if (getpeername(io.out.s, (struct sockaddr *)&io.out.raddr, &sinlen) != 0) { swarn("%s: getpeername(io.out.s)", function); send_failure(request->s, &response, SOCKS_FAILURE); close(request->s); break; } sinlen = sizeof(io.out.laddr); /* LINTED pointer casts may be troublesome */ if (getsockname(io.out.s, (struct sockaddr *)&io.out.laddr, &sinlen) != 0) { swarn("%s: getsockname(io.out.s)", function); send_failure(request->s, &response, SOCKS_FAILURE); close(request->s); break; } /* LINTED pointer casts may be troublesome */ sockaddr2sockshost((struct sockaddr *)&io.out.laddr, &response.host); response.reply = (char)sockscode(response.version, SOCKS_SUCCESS); flushio(mother, request->s, &response, &io); break; } case SOCKS_UDPASSOCIATE: { struct sockaddr_in client; socklen_t boundlen; int clientfd; /* socket we receive datagram's from client on */ if ((clientfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { swarn("%s: socket(SOCK_DGRAM)", function); send_failure(request->s, &response, SOCKS_FAILURE); close(request->s); break; } setsockoptions(clientfd); /* LINTED pointer casts may be troublesome */ sockshost2sockaddr(&request->req.host, (struct sockaddr *)&client); io.in.s = clientfd; io.in.state = io.state; io.in.raddr = client; io.in.laddr = request->to; io.in.laddr.sin_port = htons(0); /* * bind to address for receiving udp packets so we can tell client * where to send its packets. */ /* LINTED pointer casts may be troublesome */ if (sockd_bind(clientfd, (struct sockaddr *)&io.in.laddr, 0) != 0) { /* LINTED pointer casts may be troublesome */ swarn("%s: bind(%s)", function, sockaddr2string((struct sockaddr *)&io.in.laddr, a, sizeof(a))); send_failure(request->s, &response, SOCKS_FAILURE); close(request->s); close(clientfd); break; } boundlen = sizeof(io.in.laddr); /* LINTED pointer casts may be troublesome */ if (getsockname(clientfd, (struct sockaddr *)&io.in.laddr, &boundlen) != 0) { swarn("%s: getsockname(clientfd)", function); send_failure(request->s, &response, SOCKS_FAILURE); close(request->s); close(clientfd); break; } io.out.s = out; io.out.state = io.state; io.out.state.auth.method = AUTHMETHOD_NONE; boundlen = sizeof(io.out.laddr); /* LINTED pointer casts may be troublesome */ if (getsockname(out, (struct sockaddr *)&io.out.laddr, &boundlen) != 0) { swarn("%s: getsockname(out)", function); send_failure(request->s, &response, SOCKS_FAILURE); close(request->s); close(clientfd); break; } /* remote out changes each time, set to INADDR_ANY for now. */ bzero(&io.out.raddr, sizeof(io.out.raddr)); io.out.raddr.sin_family = AF_INET; io.out.raddr.sin_addr.s_addr = htonl(INADDR_ANY); io.out.raddr.sin_port = htons(0); io.control.s = request->s; io.control.laddr = request->from; io.control.raddr = request->to; io.control.state = io.state; if (request->req.flag & SOCKS_USECLIENTPORT) if (client.sin_port == io.out.laddr.sin_port) response.flag |= SOCKS_USECLIENTPORT; /* LINTED pointer casts may be troublesome */ sockaddr2sockshost((struct sockaddr *)&io.in.laddr, &response.host); response.reply = (char)sockscode(response.version, SOCKS_SUCCESS); flushio(mother, request->s, &response, &io); break; } default: SERRX(request->req.command); } close(out);}static voidflushio(mother, clientcontrol, response, io) int mother; int clientcontrol; const struct response_t *response; struct sockd_io_t *io;{ const char *function = "flushio()"; socklen_t len; int sndlowat, value; float skew; switch (io->state.command) { case SOCKS_UDPASSOCIATE: sndlowat = SOCKD_BUFSIZEUDP; skew = 1.0; /* no skew. */ break; default: sndlowat = SOCKD_BUFSIZETCP; skew = LOWATSKEW; } /* set socket options for relay process. */#if SOCKD_IOMAX == 1 /* only one client per process; doesn't matter much whether we block. */ io->in.sndlowat = sndlowat; io->out.sndlowat = sndlowat;#elif HAVE_SO_SNDLOWAT len = sizeof(value); if (getsockopt(io->in.s, SOL_SOCKET, SO_SNDBUF, &value, &len) != 0) swarn("%s: getsockopt(in, SO_SNDBUF)", function); sndlowat = MIN(sndlowat, value * skew); if (setsockopt(io->in.s, SOL_SOCKET, SO_SNDLOWAT, &sndlowat, sizeof(sndlowat)) != 0) swarn("%s: setsockopt(in, SO_SNDLOWAT)", function); len = sizeof(io->in.sndlowat); if (getsockopt(io->in.s, SOL_SOCKET, SO_SNDLOWAT, &io->in.sndlowat, &len) != 0) swarn("%s: getsockopt(in, SO_SNDLOWAT)", function); len = sizeof(value); if (getsockopt(io->out.s, SOL_SOCKET, SO_SNDBUF, &value, &len) != 0) swarn("%s: getsockopt(out, SO_SNDBUF)", function); sndlowat = MIN(sndlowat, value * skew); if (setsockopt(io->out.s, SOL_SOCKET, SO_SNDLOWAT, &sndlowat, sizeof(sndlowat)) != 0) swarn("%s: setsockopt(out, SO_SNDLOWAT", function); len = sizeof(io->out.sndlowat); if (getsockopt(io->in.s, SOL_SOCKET, SO_SNDLOWAT, &io->out.sndlowat, &len) != 0) swarn("%s: getsockopt(in, SO_SNDLOWAT", function);#else /* SOCKD_IOMAX > 1 && !HAVE_SO_SNDLOWAT. */ switch (io->state.command) { case SOCKS_UDPASSOCIATE: len = sizeof(sndlowat); if (getsockopt(io->in.s, SOL_SOCKET, SO_SNDBUF, &sndlowat, &len) != 0){ swarn("%s: getsockopt(SO_SNDBUF", function); io->in.sndlowat = SOCKD_BUFSIZEUDP; } else if (sndlowat == 0) io->in.sndlowat = SOCKD_BUFSIZEUDP; else io->in.sndlowat = sndlowat; len = sizeof(sndlowat); if (getsockopt(io->out.s, SOL_SOCKET, SO_SNDBUF, &sndlowat, &len) != 0) { swarn("%s: getsockopt(SO_SNDBUF", function); io->out.sndlowat = SOCKD_BUFSIZEUDP; } else if (sndlowat == 0) io->out.sndlowat = SOCKD_BUFSIZEUDP; else io->out.sndlowat = sndlowat; break; default: /* TCP; use minimum guess. */ io->in.sndlowat = SO_SNDLOWAT_SIZE; io->out.sndlowat = SO_SNDLOWAT_SIZE; }#endif /* SOCKD_IOMAX > 1 && !HAVE_SO_SNDLOWAT */ SASSERTX(io->in.sndlowat > 0 && io->out.sndlowat >= sizeof(struct udpheader_t)); if (send_response(clientcontrol, response) == 0) if (send_io(mother, io) != 0) serr(EXIT_FAILURE, "%s: sending io to mother failed", function); close_iodescriptors(io);}static voidproctitleupdate(from) const struct sockaddr *from;{ char fromstring[MAXSOCKADDRSTRING]; setproctitle("requestcompleter: %s", from == NULL ? "<idle>" : sockaddr2string(from, fromstring, sizeof(fromstring)));}static struct sockd_io_t *io_add(iolist, newio) struct sockd_io_t *iolist; const struct sockd_io_t *newio;{ const char *function = "io_add()"; struct sockd_io_t *io, *previo; SASSERTX(newio->next == NULL); previo = io = iolist; while (io != NULL) { previo = io; io = io->next; } if ((io = (struct sockd_io_t *)malloc(sizeof(*newio))) == NULL) swarnx("%s: %s", function, NOMEM); else { *io = *newio; if (previo == NULL) previo = io; else previo->next = io; } return iolist == NULL ? previo : iolist;}static struct sockd_io_t *io_remove(iolist, rmio) struct sockd_io_t *iolist; struct sockd_io_t *rmio;{ struct sockd_io_t *io, *previo; SASSERTX(iolist != NULL); if (iolist == rmio) { iolist = rmio->next; free(rmio); return iolist; } previo = iolist; io = iolist->next; while (io != NULL) { if (io == rmio) { previo->next = rmio->next; free(rmio); break; } previo = io; io = io->next; } return iolist;}static struct sockd_io_t *io_find(iolist, addr) struct sockd_io_t *iolist; const struct sockaddr *addr;{ struct sockd_io_t *io; if (addr == NULL) return iolist; io = iolist; while (io != NULL) /* LINTED pointer casts may be troublesome */ if (sockaddrareeq((struct sockaddr *)&io->in.laddr, addr) || sockaddrareeq((struct sockaddr *)&io->out.laddr, addr) || sockaddrareeq((struct sockaddr *)&io->control.laddr, addr)) return io; else io = io->next; /* XXX should actually check that the io is still "active". */ return NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -