📄 sockd_child.c
字号:
} /* io children, last in chain. */ for (i = 0; i < iochildc; ++i) { SASSERTX(iochildv[i].s >= 0); FD_SET(iochildv[i].s, set); dbits = MAX(dbits, iochildv[i].s); SASSERTX(iochildv[i].ack >= 0); FD_SET(iochildv[i].ack, set); dbits = MAX(dbits, iochildv[i].ack); } return dbits;}voidclearset(type, child, set) int type; const struct sockd_child_t *child; fd_set *set;{ switch (type) { case SOCKD_FREESLOT: FD_CLR(child->ack, set); break; case SOCKD_NEWREQUEST: FD_CLR(child->s, set); break; default: SERRX(type); }}struct sockd_child_t *getset(type, set) int type; fd_set *set;{ int i; /* check negotiator children for match. */ for (i = 0; i < negchildc; ++i) switch (type) { case SOCKD_NEWREQUEST: if (FD_ISSET(negchildv[i].s, set)) return &negchildv[i]; break; case SOCKD_FREESLOT: if (FD_ISSET(negchildv[i].ack, set)) return &negchildv[i]; break; } /* check request children for match. */ for (i = 0; i < reqchildc; ++i) switch (type) { case SOCKD_NEWREQUEST: if (FD_ISSET(reqchildv[i].s, set)) return &reqchildv[i]; break; case SOCKD_FREESLOT: if (FD_ISSET(reqchildv[i].ack, set)) return &reqchildv[i]; break; } /* check io children for match. */ for (i = 0; i < iochildc; ++i) switch (type) { case SOCKD_NEWREQUEST: if (FD_ISSET(iochildv[i].s, set)) return &iochildv[i]; break; case SOCKD_FREESLOT: if (FD_ISSET(iochildv[i].ack, set)) return &iochildv[i]; break; } return NULL;}intremovechild(pid) pid_t pid;{ const char *function = "removechild()"; struct sockd_child_t **childv; struct sockd_child_t *newchildv; int *childc; int child; slog(LOG_DEBUG, "%s: %d", function, (int)pid); setchildtype(childtype(pid), &childv, &childc, NULL); child = findchild(pid, *childc, *childv); SASSERTX(child >= 0); close((*childv)[child].s); close((*childv)[child].ack); /* shift all following one down */ while (child < *childc - 1) (*childv)[child] = (*childv)[++child]; --*childc; if ((newchildv = (struct sockd_child_t *)realloc(*childv, sizeof(**childv) * (*childc + 1))) == NULL) { slog(LOG_WARNING, NOMEM); return -1; } *childv = newchildv; return 0;}struct sockd_child_t *nextchild(type) int type;{ const char *function = "nextchild()"; struct timeval timeout; struct sockd_child_t **childv; int *childc; int i, maxd; fd_set wset; setchildtype(type, &childv, &childc, NULL); FD_ZERO(&wset); for (i = 0, maxd = -1; i < *childc; ++i) if ((*childv)[i].freec > 0) { FD_SET((*childv)[i].s, &wset); maxd = MAX(maxd, (*childv)[i].s); } if (maxd < 0) return NULL; ++maxd; timeout.tv_sec = 0; timeout.tv_usec = 0; switch (selectn(maxd, NULL, &wset, NULL, &timeout)) { case -1: SERR(-1); /* NOTREACHED */ case 0: slog(LOG_DEBUG, "%s: no child writable", function); return NULL; } return getset(SOCKD_NEWREQUEST, &wset);}static intsetchildtype(type, childv, childc, function) int type; struct sockd_child_t ***childv; int **childc; void (**function)(struct sockd_mother_t *mother);{ switch (type) { case CHILD_IO: if (childv != NULL) *childv = &iochildv; if (childc != NULL) *childc = &iochildc; if (function != NULL) *function = &run_io; break; case CHILD_NEGOTIATE: if (childv != NULL) *childv = &negchildv; if (childc != NULL) *childc = &negchildc; if (function != NULL) *function = &run_negotiate; break; case CHILD_REQUEST: if (childv != NULL) *childv = &reqchildv; if (childc != NULL) *childc = &reqchildc; if (function != NULL) *function = &run_request; break; default: SASSERTX(type); } return type;}intchildtype(pid) pid_t pid;{ if (findchild(pid, iochildc, iochildv) != -1) return CHILD_IO; if (findchild(pid, negchildc, negchildv) != -1) return CHILD_NEGOTIATE; if (findchild(pid, reqchildc, reqchildv) != -1) return CHILD_REQUEST; if (pidismother(pid)) return CHILD_MOTHER; SERRX(pid); /* NOTREACHED */}static intfindchild(pid, childc, childv) pid_t pid; int childc; const struct sockd_child_t *childv;{ int i; for (i = 0; i < childc; ++i) if (childv[i].pid == pid) return i; return -1;}struct sockd_child_t *getchild(pid) pid_t pid;{ int child, type; int *childc; struct sockd_child_t **childv; switch (type = childtype(pid)) { case CHILD_IO: case CHILD_NEGOTIATE: case CHILD_REQUEST: break; case CHILD_MOTHER: return NULL; default: SERRX(type); } setchildtype(type, &childv, &childc, NULL); if ((child = findchild(pid, *childc, *childv)) != -1) return &(*childv)[child]; return NULL;}intsend_io(s, io) int s; const struct sockd_io_t *io;{ const char *function = "send_io()"; struct iovec iovec[1]; struct msghdr msg; int w, fdsent, length; CMSG_AALLOC(sizeof(int) * FDPASS_MAX); length = 0; /* LINTED operands have incompatible pointer types */ iovec[0].iov_base = (const void *)io; iovec[0].iov_len = sizeof(*io); length += iovec[0].iov_len; fdsent = 0; CMSG_ADDOBJECT(io->in.s, sizeof(io->in.s) * fdsent++); CMSG_ADDOBJECT(io->out.s, sizeof(io->out.s) * fdsent++); switch (io->state.command) { case SOCKS_BIND: case SOCKS_BINDREPLY: if (!io->state.extension.bind) break; /* else: */ /* FALLTHROUGH */ case SOCKS_UDPASSOCIATE: CMSG_ADDOBJECT(io->control.s, sizeof(io->control.s) * fdsent++); break; case SOCKS_CONNECT: break; default: SERRX(io->state.command); } msg.msg_iov = iovec; msg.msg_iovlen = ELEMENTS(iovec); msg.msg_name = NULL; msg.msg_namelen = 0; CMSG_SETHDR_SEND(sizeof(int) * fdsent); if ((w = sendmsg(s, &msg, 0)) != length) { swarn("%s: sendmsg(): %d of %d", function, w, length); return -1; }#if DEBUG printfd(io, "sent");#endif return 0;}intsend_client(s, client) int s; int client;{ const char *function = "send_client()"; const char command = SOCKD_NEWREQUEST; struct iovec iovec[1]; struct msghdr msg; CMSG_AALLOC(sizeof(int)); int fdsent; /* LINTED operands have incompatible pointer types */ iovec[0].iov_base = (const void *)&command; iovec[0].iov_len = sizeof(command); fdsent = 0; CMSG_ADDOBJECT(client, sizeof(client) * fdsent++); msg.msg_iov = iovec; msg.msg_iovlen = ELEMENTS(iovec); msg.msg_name = NULL; msg.msg_namelen = 0; CMSG_SETHDR_SEND(sizeof(int) * fdsent); if (sendmsg(s, &msg, 0) != sizeof(command)) { swarn("%s: sendmsg()", function); return -1; } return 0;}intsend_req(s, req) int s; const struct sockd_request_t *req;{ const char *function = "send_req()"; struct iovec iovec[1]; struct msghdr msg; int fdsent; CMSG_AALLOC(sizeof(int)); /* LINTED operands have incompatible pointer types */ iovec[0].iov_base = (const void *)req; iovec[0].iov_len = sizeof(*req); fdsent = 0; CMSG_ADDOBJECT(req->s, sizeof(req->s) * fdsent++); msg.msg_iov = iovec; msg.msg_iovlen = ELEMENTS(iovec); msg.msg_name = NULL; msg.msg_namelen = 0; CMSG_SETHDR_SEND(sizeof(int) * fdsent); if (sendmsg(s, &msg, 0) != sizeof(*req)) { swarn("%s: sendmsg()", function); return -1; } return 0;}const char *childtype2string(type) int type;{ switch (type) { case CHILD_IO: return "io"; case CHILD_MOTHER: return "mother"; case CHILD_NEGOTIATE: return "negotiator"; case CHILD_REQUEST: return "request"; default: SERRX(type); } /* NOTREACHED */}voidsigchildbroadcast(sig, childtype) int sig; int childtype;{ int i; if (childtype & CHILD_NEGOTIATE) for (i = 0; i < negchildc; ++i) kill(negchildv[i].pid, sig); if (childtype & CHILD_REQUEST) for (i = 0; i < reqchildc; ++i) kill(reqchildv[i].pid, sig); if (childtype & CHILD_IO) for (i = 0; i < iochildc; ++i) kill(iochildv[i].pid, sig);}#if DEBUGvoidprintfd(io, prefix) const struct sockd_io_t *io; const char *prefix;{ const char *function = "printfd()"; struct sockaddr name; socklen_t namelen; char namestring[MAXSOCKADDRSTRING]; bzero(&name, sizeof(name)); namelen = sizeof(name); /* LINTED pointer casts may be troublesome */ if (getsockname(io->in.s, &name, &namelen) != 0) swarn("%s: getsockname(io->in)", function); else slog(LOG_DEBUG, "%s: io->in (%d), name: %s", prefix, io->in.s, sockaddr2string(&name, namestring, sizeof(namestring))); bzero(&name, sizeof(name)); namelen = sizeof(name); /* LINTED pointer casts may be troublesome */ if (getsockname(io->out.s, &name, &namelen) != 0) swarn("%s: getsockname(io->out)", function); else slog(LOG_DEBUG, "%s: io->out (%d), name: %s", prefix, io->out.s, sockaddr2string(&name, namestring, sizeof(namestring))); switch (io->state.command) { case SOCKS_BIND: case SOCKS_BINDREPLY: if (!io->state.extension.bind) break; /* else: */ /* FALLTHROUGH */ case SOCKS_UDPASSOCIATE: bzero(&name, sizeof(name)); namelen = sizeof(name); /* LINTED pointer casts may be troublesome */ if (getpeername(io->control.s, &name, &namelen) != 0) swarn("%s: getpeername(io->control)", function); else { if (namelen == 0) slog(LOG_DEBUG, "%s: io->control (%d), name: <none>", prefix, io->control.s); else slog(LOG_DEBUG, "%s: io->control (%d), name: %s", prefix, io->control.s, sockaddr2string(&name, namestring, sizeof(namestring))); } break; case SOCKS_CONNECT: break; default: SERRX(io->state.command); }}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -