inet_gethost.c

来自「OTP是开放电信平台的简称」· C语言 代码 · 共 2,324 行 · 第 1/4 页

C
2,324
字号
	} else {	    fatal("Unexpected end of file on main input, errno = %d",errno);	}    }    if (siz > *buff_size) {	if (buff_size == 0) {	    *buff = ALLOC((*buff_size = siz));	} else {	    *buff = REALLOC(*buff, (*buff_size = siz));	}    }    if (read_exact(0,*buff, siz) != siz) {	fatal("Unexpected end of file on main input, errno = %d",errno);    }    if (siz < 5) {	fatal("Unexpected message on main input, message size %d less "	      "than minimum.");    }    return siz;}#endif /* !WIN32 */static OpType get_op(AddrByte *buff){    return (OpType) buff[4];}static AddrByte *get_op_addr(AddrByte *buff){    return  buff + 4;}static SerialType get_serial(AddrByte *buff){    return get_int32(buff);}static ProtoType get_proto(AddrByte *buff){    return (ProtoType) buff[5];}static CtlType get_ctl(AddrByte *buff){    return (CtlType) buff[5];}static AddrByte *get_data(AddrByte *buff){    return buff + 6;}static int get_debug_level(AddrByte *buff){    return get_int32(buff + 6);}#ifdef WIN32static int send_mes_to_worker(QueItem *m, Worker *pw) {    if (!enque_mesq(pw->writeto, m)) {	warning("Unable to send to child process.");	return -1;    }    return 0;}#elsestatic int send_request_to_worker(AddrByte *pr, int rsize, Worker *pw)    {    AddrByte hdr[PACKET_BYTES];    PUT_PACKET_BYTES(hdr, rsize);    if (write_exact(pw->writeto, hdr, PACKET_BYTES) < 0) { 	warning("Unable to write to child process.");	return -1;    }    if (write_exact(pw->writeto, (AddrByte *) pr, rsize) < 0) { 	warning("Unable to write to child process.");	return -1;    }    return 0;}#endif /* !WIN32 */#ifdef WIN32static int relay_reply(Worker *pw){    QueItem *m;    if (!deque_mesq(pw->readfrom,&m)) {	return 0;    }    if (!enque_mesq(to_erlang,m)) {	FREE(m);	return 0;    }    return 1;}static int ignore_reply(Worker *pw) {    QueItem *m;    if (!deque_mesq(pw->readfrom,&m)) {	return 0;    }    FREE(m);    return 1;}#else/* Static buffers used by the next three functions */static AddrByte *relay_buff = NULL; static int relay_buff_size = 0;static int fillin_reply(Worker *pw){    int length;    if (READ_PACKET_BYTES(pw->readfrom, &length) != PACKET_BYTES) {	warning("Malformed reply (header) from worker process %d.", 		pw->pid);	return -1;    }        if (relay_buff_size < (length + PACKET_BYTES)) { 	if (!relay_buff_size) {	    relay_buff = 		ALLOC((relay_buff_size = (length + PACKET_BYTES)));	} else {	    relay_buff = 		REALLOC(relay_buff,			(relay_buff_size = (length + PACKET_BYTES)));	}    }    PUT_PACKET_BYTES(relay_buff, length);    if (read_exact(pw->readfrom, relay_buff + PACKET_BYTES, length) != 	length) {	warning("Malformed reply (data) from worker process %d.", pw->pid);	return -1;    }    return length;}static int relay_reply(Worker *pw){    int length = fillin_reply(pw); /* Filled into the "global" buffer */    int res;    if (length < 0) {	return -1;    }    if ((res = write_exact(1, relay_buff, length + PACKET_BYTES)) < 0) {	fatal("Cannot write reply to erlang process, errno = %d.", errno);    } else if (res == 0) {	DEBUGF(1,("Erlang has closed write pipe."));	return 0;    }    return length;}static int ignore_reply(Worker *pw){    return fillin_reply(pw);}#endif /* !WIN32 *//* * Domain name "parsing" and worker specific queing */static void domaincopy(AddrByte *out, AddrByte *in){    AddrByte *ptr = out;     *ptr++ = *in++;    *ptr++ = *in++;    switch(*out) {    case OP_GETHOSTBYNAME:	while(*in != '\0' && *in != '.')	    ++in;	strncpy((char*)ptr, (char*)in, DOMAINNAME_MAX-2);	ptr[DOMAINNAME_MAX-3] = '\0';	DEBUGF(4,("Saved domainname %s.", ptr));	return;    case OP_GETHOSTBYADDR:	memcpy(ptr,in, ((out[1] == PROTO_IPV4) ? UNIT_IPV4 : UNIT_IPV6) - 1);	DEBUGF(4, ("Saved domain address: %s.", 		   format_address(((out[1] == PROTO_IPV4) ? 				   UNIT_IPV4 : UNIT_IPV6) - 1,ptr)));	return;    default:	fatal("Trying to copy buffer not containing valid domain, [%d,%d].",	      (int) out[0], (int) out[1]);    }}static int domaineq(AddrByte *d1, AddrByte *d2){    if (d1[0] != d2[0] || d1[1] != d2[1]) {	return 0;    }    switch (d1[0]) {    case OP_GETHOSTBYNAME:	return !strcmp((char*)d1+2,(char*)d2+2);    case OP_GETHOSTBYADDR:	return !memcmp(d1+2,d2+2, ((d1[1] == PROTO_IPV4) 				   ? UNIT_IPV4 : UNIT_IPV6) - 1);    default:	fatal("Trying to compare buffers not containing valid domain, "	      "[%d,%d].",	      (int) d1[0], (int) d1[1]);	return -1; /* Lint... */    }}	    static int get_domainname(AddrByte *inbuff, int insize, AddrByte *domainbuff){    OpType op = get_op(inbuff);    ProtoType proto;    int i;    AddrByte *data;    data = get_data(inbuff);    switch (op) {    case OP_GETHOSTBYNAME:	data = get_data(inbuff);	for (i = (data - inbuff); i < insize && inbuff[i] != '\0'; ++i)	    ;	if (i < insize) {	    domaincopy(domainbuff, get_op_addr(inbuff)); 	    return 0;	}	DEBUGF(3, ("Could not pick valid domainname in "		   "gethostbyname operation")); 	return -1;    case OP_GETHOSTBYADDR:	proto = get_proto(inbuff);	i = insize - (data - inbuff); 	if ((proto == PROTO_IPV4 && i == UNIT_IPV4) || 	    (proto == PROTO_IPV6 && i == UNIT_IPV6)) { 	    /* An address buffer */	    domaincopy(domainbuff, get_op_addr(inbuff));	    return 0;	}	DEBUGF(3, ("Could not pick valid domainname in gethostbyaddr "		   "operation")); 	return -1;    default:	DEBUGF(2, ("Could not pick valid domainname because of "		   "invalid opcode %d.", (int) op)); 	return -1;    }}/* * Worker subprocesses with utilities */#ifdef WIN32static int create_worker(Worker *pworker, int save_que){    MesQ **thread_data = ALLOC(2*sizeof(MesQ *));    DWORD tid;    if (!create_mesq(thread_data)) {	fatal("Could not create, pipes for subprocess, errno = %d",		GetLastError());    }    if (!create_mesq(thread_data + 1)) {	fatal("Could not create, pipes for subprocess, errno = %d",		GetLastError());    }    /* Save those before the thread starts */    pworker->writeto = thread_data[0];    pworker->readfrom = thread_data[1];    if (((HANDLE) _beginthreadex(NULL, 0, worker_loop, thread_data, 0, &tid))	== NULL) {	fatal("Could not create thread errno = %d",	      GetLastError());    }    pworker->pid = tid;    pworker->state = WORKER_FREE;    pworker->serial = INVALID_SERIAL;    if (!save_que) {	pworker->que_first = pworker->que_last = NULL;	pworker->que_size = 0;    }    DEBUGF(3,("Created worker[%ld] with fd %d", 	      (long) pworker->pid, (int) pworker->readfrom));    return 0;}#elsestatic int create_worker(Worker *pworker, int save_que){    int p0[2], p1[2];    pid_t child;    if (pipe(p0)) {	warning("Could not create, pipes for subprocess, errno = %d",		errno);	return -1;    }    if (pipe(p1)) {	warning("Could not create, pipes for subprocess, errno = %d",		errno);	close(p0[0]);	close(p0[1]);	return -1;    }    if ((child = fork()) < 0) { /* failure */	warning("Could not fork(), errno = %d",		errno);	close(p0[0]);	close(p0[1]);	close(p1[0]);	close(p1[1]);	return -1;    } else if (child > 0) { /* parent */	close(p0[1]);	close(p1[0]);	pworker->writeto = p1[1];	pworker->readfrom = p0[0];	pworker->pid = child;	pworker->state = WORKER_FREE;	pworker->serial = INVALID_SERIAL;	if (!save_que) {	    pworker->que_first = pworker->que_last = NULL;	    pworker->que_size = 0;	}	DEBUGF(3,("Created worker[%ld] with fd %d", 		  (long) pworker->pid, (int) pworker->readfrom));	return 0;    } else { /* child */	close(p1[1]);	close(p0[0]);	close_all_worker_fds();	/* Make "fatal" not find any children */	num_busy_workers = num_free_workers = num_stalled_workers = 0;	if((dup2(p1[0],0) < 0) || (dup2(p0[1],1) < 0)) {	    fatal("Worker could not dup2(), errno = %d",		  errno);	    return -1; /* lint... */	}	close(p1[0]);	close(p0[1]);	signal(SIGCHLD, SIG_IGN); 	return worker_loop();    }}static void close_all_worker_fds(void) {    int w,i;    Worker *workers[3] = {free_workers, busy_workers, stalled_workers};    int wsizes[3] = {num_free_workers, num_busy_workers,		      num_stalled_workers};    for (w = 0; w < 3; ++w) {	for (i = 0; i < wsizes[w]; ++i) {	    if (workers[w][i].state != WORKER_EMPTY) {		close(workers[w][i].readfrom);		close(workers[w][i].writeto);	    }	}    }}#endif /* !WIN32 */#ifdef WIN32DWORD WINAPI worker_loop(void *v)#elsestatic int worker_loop(void)#endif{    struct hostent *he;    AddrByte *req = NULL;    size_t req_size = 0;    int this_size;    AddrByte *reply = NULL;    size_t reply_size = 0;    size_t data_size;    int error_num;    SerialType serial;    OpType op;    ProtoType proto;    AddrByte *data;    int free_he;#ifdef WIN32    QueItem *m = NULL;    MesQ *readfrom = ((MesQ **) v)[0];    MesQ *writeto = ((MesQ **) v)[1];    FREE(v);#endif    for(;;) {#ifdef WIN32	WaitForSingleObject(event_mesq(readfrom),INFINITE);	DEBUGF(4,("Worker got data on message que."));	if(!deque_mesq(readfrom,&m)) {	    goto fail;	}	this_size = m->req_size;	req = m->request;#else		if (READ_PACKET_BYTES(0,&this_size) != PACKET_BYTES) {	    DEBUGF(2,("Worker got error/EOF while reading size, exiting."));	    exit(0);	}	if (this_size > req_size) {	    if (req == NULL) {		req = ALLOC((req_size = this_size));	    } else {		req = REALLOC(req, (req_size = this_size));	    }	}	if (read_exact(0, req, (size_t) this_size) != this_size) {	    DEBUGF(1,("Worker got EOF while reading data, exiting."));	    exit(0);	}#endif	/* Decode the request... */	serial = get_serial(req);	if (OP_CONTROL == (op = get_op(req))) {	    CtlType ctl;	    if (serial != INVALID_SERIAL) {		DEBUGF(1, ("Worker got invalid serial: %d.", serial));		exit(0);	    }	    switch (ctl = get_ctl(req)) {	    case SETOPT_DEBUG_LEVEL:		debug_level = get_debug_level(req);		DEBUGF(debug_level, 		       ("Worker debug_level = %d.", debug_level));		break;	    }	    continue;	}	proto = get_proto(req);	data = get_data(req);	DEBUGF(4,("Worker got request, op = %d, proto = %d, data = %s.",		  op,proto,data));	/* Got a request, lets go... */	free_he = 0;	switch (op) {	case OP_GETHOSTBYNAME:	    if (proto != PROTO_IPV4) {#if defined(HAVE_GETIPNODEBYNAME) && !defined(WIN32) /* IP V6 support */		if (proto == PROTO_IPV6) {		    he = getipnodebyname(data, AF_INET6, AI_DEFAULT,					 &error_num);		    free_he = 1;		    error_num = map_netdb_error(error_num);		} else {		    /* Not supported... */		    he = NULL;		    error_num = ERRCODE_NOTSUP;		}		#else		/* Not supported... */		he = NULL;		error_num = ERRCODE_NOTSUP;#endif	    } else {		DEBUGF(4,("Starting gethostbyname(%s)",data));		he = gethostbyname((char*)data);		error_num = he ? 0 : map_netdb_error(h_errno);		if (error_num) {		    DEBUGF(4,("gethostbyname(%s) gave error: %d", 			      data, error_num));		} else {		    DEBUGF(4,("gethostbyname(%s) gave success",			      data));		}	    }	    if (!he) {		data_size = build_error_reply(serial, error_num, 					      &reply, &reply_size);	    } else {		data_size = build_reply(serial, he, &reply, &reply_size);#if defined(HAVE_GETIPNODEBYNAME) && !defined(WIN32) /* IP V6 support */		if (free_he) {		    freehostent(he);		}#endif	    }	    break;	case OP_GETHOSTBYADDR:	    if (proto != PROTO_IPV4) {#if defined(HAVE_GETIPNODEBYADDR) && !defined(WIN32) /* IP V6 support */		if (proto == PROTO_IPV6) {		    struct in6_addr ia;		    memcpy(ia.s6_addr, data, 16);		    he = getipnodebyaddr(&ia, 16, AF_INET6, &error_num);		    free_he = 1;		    error_num = map_netdb_error(error_num);		} else {		    /* Not supported... */		    he = NULL;		    error_num = ERRCODE_NOTSUP;		}		#else		/* Not supported... */		he = NULL;		error_num = ERRCODE_NOTSUP;#endif	    } else {		struct in_addr ia;		memcpy(&ia.s_addr, data, 4); /* Alignment required... */		he = gethostbyaddr((const char *) &ia, 4, AF_INET);		error_num = map_netdb_error(h_errno);	    }	    if (!he) {		data_size = build_error_reply(serial, error_num, 					      &reply, &reply_size);	    } else {		data_size = build_reply(serial, he, &reply, &reply_size);#if defined(HAVE_GETIPNODEBYADDR) && !defined(WIN32) /* IP V6 support */		if (free_he) {		    freehostent(he);		}#endif	    }	    break;	default:	    data_size = build_error_reply(serial, ERRCODE_NOTSUP, 					  &reply, &reply_size);	    break;	}#ifdef WIN32	m = REALLOC(m, sizeof(QueItem) - 1 + data_size - PACKET_BYTES);	m->next = NULL;	m->req_size = data_size - PACKET_BYTES;	memcpy(m->request,reply + PACKET_BYTES,data_size - PACKET_BYTES);	if (!enque_mesq(writeto,m)) {	    goto fail;	}	m = NULL;#else	write(1, reply, data_size); /* No signals expected */#endif    }#ifdef WIN32 fail:    if (m != NULL) {	FREE(m);    }    close_mesq(readfrom);    close_mesq(writeto);    if (reply) {	FREE(reply);    }    return 1;#endif}static int map_netdb_error(int netdb_code){    switch (netdb_code) {#ifdef HOST_NOT_FOUND    case HOST_NOT_FOUND:	return ERRCODE_HOST_NOT_FOUND;#endif#ifdef TRY_AGAIN    case TRY_AGAIN:	return ERRCODE_TRY_AGAIN;#endif#ifdef NO_RECOVERY    case NO_RECOVERY:	return ERRCODE_NO_RECOVERY;#endif#if defined(NO_DATA) || defined(NO_ADDRESS)#ifdef NO_DATA    case NO_DATA:#endif#ifdef NO_ADDRESS#if !defined(NO_DATA) || (NO_DATA != NO_ADDRESS)	

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?