void set_adrs(SymTbl *tp) /* 変数・引数の番地割当 */ { int i, size = INTSIZE; switch (tp->nmKind) { case varId: /* 変数 */ if (tp->aryLen > 0) size *= tp->aryLen; /* 配列ならサイズ計算 */ if (is_global()) tp->adrs = mallocG(size); /* 大域変数 */ else tp->adrs = mallocL(size); /* 局所変数 */ break; case fncId: /* 関数 */ tp->adrs = nextCodeCt(); /* 関数入口アドレス設定 */ for (i=1; i<=tp->args; i++) { (tp+i)->adrs = mallocL(size); /* 引数のアドレス割当 */ } } }
// returns -1 for failures including the other end closing the socket // returns 0 if successful in reading data, but still not read the data fully // returns 1 if successful in reading all the data mDNSlocal int ProxyTCPRead(ProxyTCPInfo_t *tcpInfo) { long n; mDNSBool closed; if (tcpInfo->nread < 2) // First read the two-byte length preceeding the DNS message { mDNSu8 *lenptr = (mDNSu8 *)&tcpInfo->replyLen; n = mDNSPlatformReadTCP(&tcpInfo->sock, lenptr + tcpInfo->nread, 2 - tcpInfo->nread, &closed); if (n < 0 || closed) { LogMsg("ProxyTCPRead: attempt to read message length failed"); return -1; } tcpInfo->nread += n; if (tcpInfo->nread < 2) { LogMsg("ProxyTCPRead: nread %d, n %d", tcpInfo->nread, n); return 0; } tcpInfo->replyLen = (mDNSu16)((mDNSu16)lenptr[0] << 8 | lenptr[1]); if (tcpInfo->replyLen < sizeof(DNSMessageHeader)) { LogMsg("ProxyTCPRead: Message length too short (%d bytes)", tcpInfo->replyLen); return -1; } tcpInfo->reply = mallocL("ProxyTCPInfo", tcpInfo->replyLen); if (!tcpInfo->reply) { LogMsg("ProxyTCPRead: Memory failure"); return -1; } } n = mDNSPlatformReadTCP(&tcpInfo->sock, ((char *)tcpInfo->reply) + (tcpInfo->nread - 2), tcpInfo->replyLen - (tcpInfo->nread - 2), &closed); if (n < 0 || closed) { LogMsg("ProxyTCPRead: read failure n %d, closed %d", n, closed); return -1; } tcpInfo->nread += n; if ((tcpInfo->nread - 2) != tcpInfo->replyLen) return 0; else return 1; }
mDNSlocal void ProxyTCPAccept(int s1, short filter, void *context) { int newfd; struct sockaddr_storage ss; socklen_t sslen = sizeof(ss); const int on = 1; KQSocketSet *listenSet = (KQSocketSet *)context; (void) filter; while ((newfd = accept(s1, (struct sockaddr *)&ss, &sslen)) != -1) { int err; int *s; KQueueEntry *k; KQSocketSet *kq; // Even though we just need a single KQueueEntry, for simplicity we re-use // the KQSocketSet ProxyTCPInfo_t *ti = mallocL("ProxyTCPContext", sizeof(ProxyTCPInfo_t)); if (!ti) { LogMsg("ProxyTCPAccept: cannot allocate TCPSocket"); close(newfd); return; } mDNSPlatformMemZero(ti, sizeof(ProxyTCPInfo_t)); TCPSocket *sock = &ti->sock; kq = &sock->ss; kq->sktv4 = -1; kq->sktv6 = -1; kq->m = listenSet->m; fcntl(newfd, F_SETFL, fcntl(newfd, F_GETFL, 0) | O_NONBLOCK); // set non-blocking if (ss.ss_family == AF_INET) { s = &kq->sktv4; k = &kq->kqsv4; // Receive interface identifiers err = setsockopt(newfd, IPPROTO_IP, IP_RECVIF, &on, sizeof(on)); if (err) { LogMsg("ProxyTCPAccept: IP_RECVIF %d errno %d (%s)", newfd, errno, strerror(errno)); mDNSPlatformDisposeProxyContext(ti); return; } } else { s = &kq->sktv6; k = &kq->kqsv6; // We want to receive destination addresses and receive interface identifiers err = setsockopt(newfd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)); if (err) { LogMsg("ProxyTCPAccept: IP_RECVPKTINFO %d errno %d (%s)", newfd, errno, strerror(errno)); mDNSPlatformDisposeProxyContext(ti); return; } } *s = newfd; // mDNSPlatformReadTCP/WriteTCP (unlike the UDP counterpart) does not provide the destination address // from which we can infer the destination address family. Hence we need to remember that here. // Instead of remembering the address family, we remember the right fd. sock->fd = newfd; sock->kqEntry = k; k->KQcallback = ProxyTCPSocketCallBack; k->KQcontext = ti; k->KQtask = "TCP Proxy packet reception"; #ifdef MDNSRESPONDER_USES_LIB_DISPATCH_AS_PRIMARY_EVENT_LOOP_MECHANISM k->readSource = mDNSNULL; k->writeSource = mDNSNULL; k->fdClosed = mDNSfalse; #endif KQueueSet(*s, EV_ADD, EVFILT_READ, k); } }