summaryrefslogtreecommitdiffstats
path: root/lib/base/dnsdmain.cpp
blob: 52446aeba58bb57fe34f9525db1cd81bf1ff28f4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/** BEGIN COPYRIGHT BLOCK
 * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
 * Copyright (C) 2005 Red Hat, Inc.
 * All rights reserved.
 * END COPYRIGHT BLOCK **/
/*
 * dnsdmain.c: DNS domain guessing stuff moved out of dns.c because of the
 * string ball problems
 */


#include "netsite.h"
#include <string.h>
#include <stdio.h>
#ifdef XP_UNIX
#include <unistd.h>
#endif
#include <ctype.h>
#include "util.h"

/* Under NT, this is taken care of by net.h including winsock.h */
#ifdef XP_UNIX
#include <netdb.h>  /* struct hostent */
#endif
extern "C" {
#include <nspr.h>
}



/* This is contained in resolv.h on most systems. */
#define _PATH_RESCONF "/etc/resolv.conf"

#ifdef XP_UNIX
NSPR_BEGIN_EXTERN_C
#ifdef Linux
extern int getdomainname(char *, size_t);
#else 
extern int getdomainname(char *, int);
#endif /* Linux */
#if defined(HPUX) || defined (UnixWare) || defined(Linux) || defined(IRIX6_5)
extern int gethostname (char *name, size_t namelen);
#else
#ifndef AIX
extern int gethostname (char *name, int namelen);
#endif
#endif
NSPR_END_EXTERN_C
#endif


/* ---------------------------- dns_guess_domain -------------------------- */


extern "C" NSAPI_PUBLIC char *dns_guess_domain(char * hname)
{
    FILE *f;
    char * cp;
    int hnlen;
    char line[256];
    static int dnlen = 0;
    static char * domain = 0;
    PRHostEnt   hent;
    char        buf[PR_NETDB_BUF_SIZE];
    PRStatus    err;

    /* Sanity check */
    if (strchr(hname, '.')) {
	return STRDUP(hname);
    }

    if (dnlen == 0) {

	/* First try a little trick that seems to often work... */

	/*
	 * Get the local host name, even it doesn't come back
	 * fully qualified.
	 */
	line[0] = 0;
	gethostname(line, sizeof(line));
	if (line[0] != 0) {
	  /* Is it fully qualified? */
	  domain = strchr(line, '.');
	  if (domain == 0) {
	    /* No, try gethostbyname() */
	    err = PR_GetHostByName(line,
				      buf,
				      PR_NETDB_BUF_SIZE,
				      &hent);
	    if (err == PR_SUCCESS) {
	      /* See if h_name is fully-qualified */
	      if (hent.h_name) 	domain = strchr(hent.h_name, '.');

	      /* Otherwise look for a fully qualified alias */
	      if ((domain == 0) &&
		  (hent.h_aliases && hent.h_aliases[0])) {
		char **p;
		for (p = hent.h_aliases; *p; ++p) {
		  domain = strchr(*p, '.');
		  if (domain) break;
		}
	      }
	    }
	  }
	}

	/* Still no luck? */
	if (domain == 0) {

	    f = fopen(_PATH_RESCONF, "r");

	    /* See if there's a domain entry in their resolver configuration */
	    if(f) {
		while(fgets(line, sizeof(line), f)) {
		    if(!strncasecmp(line, "domain ", 7)) {
			for (cp = &line[7]; *cp && isspace(*cp); ++cp) ;
			if (*cp) {
			    domain = cp;
			    for (; *cp && !isspace(*cp); ++cp) ;
			    *cp = 0;
			}
			break;
		    }
		}
		fclose(f);
	    }
	}

#ifndef NO_DOMAINNAME
	if (domain == 0) {
	    /* No domain found. Try getdomainname. */
	    getdomainname(line, sizeof(line));
	    if (line[0] != 0) domain = &line[0];
	}
#endif

	if (domain != 0) {
	    if (domain[0] == '.') ++domain;
	    domain = STRDUP(domain);
	    dnlen = strlen(domain);
	}
	else dnlen = -1;
    }

    if (domain != 0) {
	hnlen = strlen(hname);
	if ((hnlen + dnlen + 2) <= sizeof(line)) {
	    strcpy(line, hname);
	    line[hnlen] = '.';
	    strcpy(&line[hnlen+1], domain);
	    return STRDUP(line);
	}
    }

    return 0;
}