📄 domain.c
字号:
/**************************************************************************** Copyright (c) 1999,2000 WU-FTPD Development Group. All rights reserved. Portions Copyright (c) 1980, 1985, 1988, 1989, 1990, 1991, 1993, 1994 The Regents of the University of California. Portions Copyright (c) 1993, 1994 Washington University in Saint Louis. Portions Copyright (c) 1996, 1998 Berkeley Software Design, Inc. Portions Copyright (c) 1989 Massachusetts Institute of Technology. Portions Copyright (c) 1998 Sendmail, Inc. Portions Copyright (c) 1983, 1995, 1996, 1997 Eric P. Allman. Portions Copyright (c) 1997 by Stan Barber. Portions Copyright (c) 1997 by Kent Landfield. Portions Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc. Use and distribution of this software and its source code are governed by the terms and conditions of the WU-FTPD Software License ("LICENSE"). If you did not receive a copy of the license, it may be obtained online at http://www.wu-ftpd.org/license.html. $Id: domain.c,v 1.11 2000/07/01 18:17:38 wuftpd Exp $ ****************************************************************************//* * domain.c - DNS functions for WU-FTPD using res_* * * INITIAL AUTHOR - * Nikos Mouat <nikm@cyberflunk.com> */#include "config.h"#include <stdlib.h>#include "proto.h"#ifdef HAVE_LIBRESOLV#include <sys/types.h>#include <sys/param.h>#include <stdio.h>#include <string.h>#include <netdb.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#ifndef NO_DNS#include <arpa/nameser.h>#include <resolv.h>#ifndef INT16SZ#define INT16SZ sizeof(u_short)#endif /* !INT16SZ */#ifndef INT32SZ#define INT32SZ sizeof(u_long)#endif /* !INT32SZ */#ifndef INADDRSZ#define INADDRSZ sizeof(struct in_addr)#endif /* !INADDRSZ */#ifndef HFIXEDSZ#define HFIXEDSZ sizeof(HEADER)#endif /* !HFIXEDSZ */#endif /* !NO_DNS */#include "extensions.h"/* these should go in a new ftpd.h perhaps? config.h doesn't seem appropriate *//* and there does not appear to be a global include file */#ifndef TRUE#define TRUE 1#endif#ifndef FALSE#define FALSE !TRUE#endifstruct t_resolver_options { char *token; int value;} resolver_options[] = {#ifdef RES_DEBUG { "debug", RES_DEBUG },#endif#ifdef RES_AAONLY { "aaonly", RES_AAONLY },#endif#ifdef RES_USEVC { "usevc", RES_USEVC },#endif#ifdef RES_STAYOPEN { "stayopen", RES_STAYOPEN },#endif#ifdef RES_PRIMARY { "primary", RES_PRIMARY },#endif#ifdef RES_IGNTC { "igntc", RES_IGNTC },#endif#ifdef RES_RECURSE { "recurse", RES_RECURSE },#endif#ifdef RES_DEFNAMES { "defnames", RES_DEFNAMES },#endif#ifdef RES_DNSRCH { "dnsrch", RES_DNSRCH },#endif#ifdef RES_INSECURE1 { "insecure1", RES_INSECURE1 },#endif#ifdef RES_INSECURE2 { "insecure2", RES_INSECURE2 },#endif#ifdef RES_NOALIASES { "noaliases", RES_NOALIASES },#endif#ifdef RES_USE_INET6 { "use_inet6", RES_USE_INET6 },#endif#ifdef RES_ROTATE { "rotate", RES_ROTATE },#endif#ifdef RES_NOCHECKNAME { "nocheckname", RES_NOCHECKNAME },#endif#ifdef RES_KEEPSIG { "keepsig", RES_KEEPSIG },#endif#ifdef RES_DEFAULT { "default", RES_DEFAULT },#endif { NULL, 0 }};/* globals */int resolver_initialized = FALSE;char *remote_hostname = NULL;char *remote_address = NULL;int has_reverse_dns = FALSE;int has_matching_dns = FALSE;/* Prototypes */int check_matching_dns(void);int lookup_ip(char *ip, char **fqdn);int check_name_for_ip(char *name, char *ip);int initialize_dns(struct sockaddr_in *remote_socket);int check_reverse_dns(void);/* types for res_* answers */#ifndef NO_DNStypedef union { HEADER qb1; u_char qb2[PACKETSZ];} querybuf;#endif/**************************************************************************** * lookup_name() * This routine takes a FQDN and tries to find a valid IP address. * If a CNAME is returned, it looks further on in the reply for an * A record. It will return as soon as it finds an A record, so hosts * with multiple A records will have the first A record returned. ***************************************************************************/int lookup_name(char *name, char **ip){#ifndef NO_DNS u_char *msg_end, *msg_ptr;#ifdef USE_RES_SEND querybuf question, answer;#else querybuf answer;#endif int rc, num_answers, num_query, q_type, q_class, q_ttl, q_len; char query_name[MAXDNAME + 1]; struct in_addr inaddr; char *result; /* res_mkquery+res_send seem to function identically to res_query, so I'm */ /* using res_query. If there's some advantage to using res_mkquery that I */ /* don't know about (which wouldn't surprise me :) then you can just */ /* define USE_RES_SEND and it will use that method */#ifdef USE_RES_SEND rc = res_mkquery(QUERY, name, C_IN, T_A, NULL, 0, NULL, question.qb2, sizeof(querybuf)); if (rc < 0) { return FALSE; } rc = res_send(question.qb2, rc, answer.qb2, sizeof(querybuf));#else rc = res_query(name, C_IN, T_A, answer.qb2, sizeof(querybuf));#endif if (rc < 0) { return FALSE; } msg_end = (u_char *) & answer + rc; num_answers = ntohs(answer.qb1.ancount); num_query = ntohs(answer.qb1.qdcount); if (num_answers < 1) { /* No answers mean that this hostname doesn't exist.. */ return FALSE; } msg_ptr = answer.qb2 + HFIXEDSZ; /* skip over the query */ for (; (num_query > 0) && (msg_ptr < msg_end); num_query--) { msg_ptr += dn_skipname(msg_ptr, msg_end) + QFIXEDSZ; } for (; (num_answers > 0) && (msg_ptr < msg_end); num_answers--) { rc = dn_expand(answer.qb2, msg_end, msg_ptr, (void *) query_name, MAXDNAME); msg_ptr += rc; q_type = _getshort(msg_ptr); msg_ptr += INT16SZ; q_class = _getshort(msg_ptr); msg_ptr += INT16SZ; q_ttl = _getlong(msg_ptr); msg_ptr += INT32SZ; q_len = _getshort(msg_ptr); msg_ptr += INT16SZ; /* look at the type of response that we recieved. If it's a CNAME then */ /* we need to find out what the CNAME's IP is. */ switch (q_type) { case T_CNAME: /* Got a CNAME - hope that there are other answers with the A */ msg_ptr += q_len; break; case T_A: bcopy(msg_ptr, (char *) &inaddr, INADDRSZ); msg_ptr += q_len; result = inet_ntoa(inaddr); *ip = (char *) malloc(strlen(result) + 1); if (*ip == NULL) return FALSE; strcpy(*ip, result); return TRUE; default: /* what the ?? - we don't expect this response type */ return FALSE; } } /* oh dear, there was no A's in the response */#endif /* !NO_DNS */ return FALSE;}/**************************************************************************** * lookup_ip() * This routine takes an IP address in the format a.b.c.d and returns the * hostname. ***************************************************************************/int lookup_ip(char *ip, char **fqdn){#ifndef NO_DNS u_char *msg_end, *msg_ptr;#ifdef USE_RES_SEND querybuf question, answer;#else querybuf answer;#endif int rc, num_answers, num_query, q_type, q_class, q_ttl, q_len; char query_name[MAXDNAME + 1]; char in_addr[MAXDNAME + 1]; unsigned int a, b, c, d; a = b = c = d = 0; sscanf(ip, "%u.%u.%u.%u", &a, &b, &c, &d); sprintf(in_addr, "%u.%u.%u.%u.in-addr.arpa", d, c, b, a);#ifdef USE_RES_SEND rc = res_mkquery(QUERY, in_addr, C_IN, T_PTR, NULL, 0, NULL, question.qb2, sizeof(querybuf)); if (rc < 0) { return FALSE; } rc = res_send(question.qb2, rc, answer.qb2, sizeof(querybuf));#else rc = res_query(in_addr, C_IN, T_PTR, answer.qb2, sizeof(querybuf));#endif if (rc < 0) { return FALSE; } msg_end = (u_char *) & answer + rc; num_answers = ntohs(answer.qb1.ancount); num_query = ntohs(answer.qb1.qdcount); if (num_answers < 1) { /* No answers mean that this hostname doesn't exist.. */ return FALSE; } msg_ptr = answer.qb2 + HFIXEDSZ; /* skip over the query */ for (; (num_query > 0) && (msg_ptr < msg_end); num_query--) { msg_ptr += dn_skipname(msg_ptr, msg_end) + QFIXEDSZ; } for (; num_answers > 0 && (msg_ptr < msg_end); num_answers--) { rc = dn_expand(answer.qb2, msg_end, msg_ptr, (void *) query_name, MAXDNAME); /* increment our pointer */ msg_ptr += rc; /* read off the various answer information */ q_type = _getshort(msg_ptr); msg_ptr += INT16SZ; q_class = _getshort(msg_ptr); msg_ptr += INT16SZ; q_ttl = _getlong(msg_ptr); msg_ptr += INT32SZ; q_len = _getshort(msg_ptr); msg_ptr += INT16SZ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -