// reference: ngx_http_proxy_process_status_line ngx_int_t ngx_http_fetch_decode(ngx_http_request_t *r) { ngx_http_fetch_ctx_t * ctx = ngx_http_fetch_get_module_ctx(r); if (!ctx) { return NGX_ERROR; } ngx_http_upstream_t * u = r->upstream; ngx_int_t rc = ngx_http_parse_status_line(r, &u->buffer, &ctx->status); if (rc == NGX_AGAIN) { return rc; } if (rc == NGX_ERROR) { r->http_version = NGX_HTTP_VERSION_9; u->state->status = NGX_HTTP_OK; u->headers_in.connection_close = 1; return NGX_OK; } if (u->state && u->state->status == 0) { u->state->status = ctx->status.code; } u->headers_in.status_n = ctx->status.code; size_t len = ctx->status.end - ctx->status.start; u->headers_in.status_line.len = len; u->headers_in.status_line.data = ngx_pnalloc(r->pool, len); if (!u->headers_in.status_line.data) { return NGX_ERROR; } ngx_memcpy(u->headers_in.status_line.data, ctx->status.start, len); if (ctx->status.http_version < NGX_HTTP_VERSION_11) { u->headers_in.connection_close = 1; } u->process_header = __decode_header; return __decode_header(r); }
int __dns_lookup(const char *name, int type, int nscount, char **nsip, unsigned char **outpacket, struct resolv_answer *a) { int i, j, len, fd, pos, rc; struct timeval tv; fd_set fds; struct resolv_header h; struct resolv_question q; int retries = 0; unsigned char * packet = malloc(PACKETSZ); int outpacketlen; char *dns, *lookup = malloc(MAXDNAME); int variant = 0; struct sockaddr_in sa; #ifdef __UCLIBC_HAS_IPV6__ int v6; struct sockaddr_in6 sa6; #endif fd = -1; if (!packet || !lookup || !nscount) goto fail; DPRINTF("Looking up type %d answer for '%s'\n", type, name); LOCK; ns %= nscount; UNLOCK; while (retries++ < MAX_RETRIES) { if (fd != -1) close(fd); memset(packet, 0, PACKETSZ); memset(&h, 0, sizeof(h)); /* Mess with globals while under lock */ LOCK; ++id; id &= 0xffff; h.id = id; dns = nsip[ns]; UNLOCK; h.qdcount = 1; h.rd = 1; DPRINTF("encoding header\n", h.rd); i = __encode_header(&h, packet, PACKETSZ); if (i < 0) goto fail; strncpy(lookup,name,MAXDNAME); BIGLOCK; if (variant < __searchdomains && strchr(lookup, '.') == NULL) { strncat(lookup,".", MAXDNAME); strncat(lookup,__searchdomain[variant], MAXDNAME); } BIGUNLOCK; DPRINTF("lookup name: %s\n", lookup); q.dotted = (char *)lookup; q.qtype = type; q.qclass = C_IN; /* CLASS_IN */ j = __encode_question(&q, packet+i, PACKETSZ-i); if (j < 0) goto fail; len = i + j; DPRINTF("On try %d, sending query to port %d of machine %s\n", retries, NAMESERVER_PORT, dns); #ifdef __UCLIBC_HAS_IPV6__ v6 = inet_pton(AF_INET6, dns, &sa6.sin6_addr) > 0; fd = socket(v6 ? AF_INET6 : AF_INET, SOCK_DGRAM, IPPROTO_UDP); #else fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); #endif if (fd < 0) { continue; } /* Connect to the UDP socket so that asyncronous errors are returned */ #ifdef __UCLIBC_HAS_IPV6__ if (v6) { sa6.sin6_family = AF_INET6; sa6.sin6_port = htons(NAMESERVER_PORT); /* sa6.sin6_addr is already here */ rc = connect(fd, (struct sockaddr *) &sa6, sizeof(sa6)); } else { #endif sa.sin_family = AF_INET; sa.sin_port = htons(NAMESERVER_PORT); sa.sin_addr.s_addr = inet_addr(dns); rc = connect(fd, (struct sockaddr *) &sa, sizeof(sa)); #ifdef __UCLIBC_HAS_IPV6__ } #endif if (rc < 0) { if (errno == ENETUNREACH) { /* routing error, presume not transient */ goto tryall; } else /* retry */ continue; } DPRINTF("Transmitting packet of length %d, id=%d, qr=%d\n", len, h.id, h.qr); send(fd, packet, len, 0); FD_ZERO(&fds); FD_SET(fd, &fds); tv.tv_sec = REPLY_TIMEOUT; tv.tv_usec = 0; if (select(fd + 1, &fds, NULL, NULL, &tv) <= 0) { DPRINTF("Timeout\n"); /* timed out, so retry send and receive, * to next nameserver on queue */ goto again; } i = recv(fd, packet, 512, 0); outpacketlen = i; if (i < HFIXEDSZ) { /* too short ! */ goto again; } __decode_header(packet, &h); DPRINTF("id = %d, qr = %d\n", h.id, h.qr); LOCK; if ((h.id != id) || (!h.qr)) { UNLOCK; /* unsolicited */ goto again; } UNLOCK; DPRINTF("Got response %s\n", "(i think)!"); DPRINTF("qrcount=%d,ancount=%d,nscount=%d,arcount=%d\n", h.qdcount, h.ancount, h.nscount, h.arcount); DPRINTF("opcode=%d,aa=%d,tc=%d,rd=%d,ra=%d,rcode=%d\n", h.opcode, h.aa, h.tc, h.rd, h.ra, h.rcode); if ((h.rcode) || (h.ancount < 1)) { /* negative result, not present */ goto again; } pos = HFIXEDSZ; for (j = 0; j < h.qdcount; j++) { DPRINTF("Skipping question %d at %d\n", j, pos); i = __length_question(packet, pos); DPRINTF("Length of question %d is %d\n", j, i); if (i < 0) goto again; pos += i; } DPRINTF("Decoding answer at pos %d\n", pos); for (j=0;j<h.ancount;j++) { i = __decode_answer(packet, pos, a); if (i<0) { DPRINTF("failed decode %d\n", i); goto again; } /* For all but T_SIG, accept first answer */ if (a->atype != T_SIG) break; DPRINTF("skipping T_SIG %d\n", i); free(a->dotted); pos += i; } DPRINTF("Answer name = |%s|\n", a->dotted); DPRINTF("Answer type = |%d|\n", a->atype); close(fd); if (outpacket) *outpacket = packet; else free(packet); free(lookup); return (outpacketlen); /* success! */ tryall: /* if there are other nameservers, give them a go, otherwise return with error */ { int sdomains; BIGLOCK; sdomains=__searchdomains; BIGUNLOCK; variant = 0; if (retries >= nscount*(sdomains+1)) goto fail; } again: /* if there are searchdomains, try them or fallback as passed */ { int sdomains; BIGLOCK; sdomains=__searchdomains; BIGUNLOCK; if (variant < sdomains) { /* next search */ variant++; } else { /* next server, first search */ LOCK; ns = (ns + 1) % nscount; UNLOCK; variant = 0; } } } fail: if (fd != -1) close(fd); if (lookup) free(lookup); if (packet) free(packet); return -1; }
int __decode_packet(unsigned char *data, struct resolv_header *h) { return __decode_header(data, h); }