Initial import
[samba] / source / utils / net_lookup.c
1 /* 
2    Samba Unix/Linux SMB client library 
3    net lookup command
4    Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20 #include "includes.h"
21 #include "utils/net.h"
22
23 int net_lookup_usage(int argc, const char **argv)
24 {
25         d_printf(
26 "  net lookup [host] HOSTNAME[#<type>]\n\tgives IP for a hostname\n\n"
27 "  net lookup ldap [domain]\n\tgives IP of domain's ldap server\n\n"
28 "  net lookup kdc [realm]\n\tgives IP of realm's kerberos KDC\n\n"
29 "  net lookup dc [domain]\n\tgives IP of domains Domain Controllers\n\n"
30 "  net lookup master [domain|wg]\n\tgive IP of master browser\n\n"
31 );
32         return -1;
33 }
34
35 /* lookup a hostname giving an IP */
36 static int net_lookup_host(int argc, const char **argv)
37 {
38         struct in_addr ip;
39         int name_type = 0x20;
40         const char *name = argv[0];
41         char *p;
42
43         if (argc == 0) 
44                 return net_lookup_usage(argc, argv);
45
46         p = strchr_m(name,'#');
47         if (p) {
48                 *p = '\0';
49                 sscanf(++p,"%x",&name_type);
50         }
51         
52         if (!resolve_name(name, &ip, name_type)) {
53                 /* we deliberately use DEBUG() here to send it to stderr 
54                    so scripts aren't mucked up */
55                 DEBUG(0,("Didn't find %s#%02x\n", name, name_type));
56                 return -1;
57         }
58
59         d_printf("%s\n", inet_ntoa(ip));
60         return 0;
61 }
62
63 #ifdef HAVE_LDAP
64 static void print_ldap_srvlist(char *srvlist)
65 {
66         char *cur, *next;
67         struct in_addr ip;
68         BOOL printit;
69
70         cur = srvlist;
71         do {
72                 next = strchr(cur,':');
73                 if (next) *next++='\0';
74                 printit = resolve_name(cur, &ip, 0x20);
75                 cur=next;
76                 next=cur ? strchr(cur,' ') :NULL;
77                 if (next)
78                         *next++='\0';
79                 if (printit)
80                         d_printf("%s:%s\n", inet_ntoa(ip), cur?cur:"");
81                 cur = next;
82         } while (next);
83 }
84 #endif
85
86 static int net_lookup_ldap(int argc, const char **argv)
87 {
88 #ifdef HAVE_ADS
89         char *srvlist;
90         const char *domain;
91         int rc;
92         struct in_addr addr;
93         struct hostent *hostent;
94
95         if (argc > 0)
96                 domain = argv[0];
97         else
98                 domain = opt_target_workgroup;
99
100         DEBUG(9, ("Lookup up ldap for domain %s\n", domain));
101         rc = ldap_domain2hostlist(domain, &srvlist);
102         if ((rc == LDAP_SUCCESS) && srvlist) {
103                 print_ldap_srvlist(srvlist);
104                 return 0;
105         }
106
107         DEBUG(9, ("Looking up DC for domain %s\n", domain));
108         if (!get_pdc_ip(domain, &addr))
109                 return -1;
110
111         hostent = gethostbyaddr((char *) &addr.s_addr, sizeof(addr.s_addr),
112                                 AF_INET);
113         if (!hostent)
114                 return -1;
115
116         DEBUG(9, ("Found DC with DNS name %s\n", hostent->h_name));
117         domain = strchr(hostent->h_name, '.');
118         if (!domain)
119                 return -1;
120         domain++;
121
122         DEBUG(9, ("Looking up ldap for domain %s\n", domain));
123         rc = ldap_domain2hostlist(domain, &srvlist);
124         if ((rc == LDAP_SUCCESS) && srvlist) {
125                 print_ldap_srvlist(srvlist);
126                 return 0;
127         }
128         return -1;
129 #endif
130         DEBUG(1,("No ADS support\n"));
131         return -1;
132 }
133
134 static int net_lookup_dc(int argc, const char **argv)
135 {
136         struct ip_service *ip_list;
137         struct in_addr addr;
138         char *pdc_str = NULL;
139         const char *domain=opt_target_workgroup;
140         int count, i;
141
142         if (argc > 0)
143                 domain=argv[0];
144
145         /* first get PDC */
146         if (!get_pdc_ip(domain, &addr))
147                 return -1;
148
149         asprintf(&pdc_str, "%s", inet_ntoa(addr));
150         d_printf("%s\n", pdc_str);
151
152         if (!get_sorted_dc_list(domain, &ip_list, &count, False)) {
153                 SAFE_FREE(pdc_str);
154                 return 0;
155         }
156         for (i=0;i<count;i++) {
157                 char *dc_str = inet_ntoa(ip_list[i].ip);
158                 if (!strequal(pdc_str, dc_str))
159                         d_printf("%s\n", dc_str);
160         }
161         SAFE_FREE(pdc_str);
162         return 0;
163 }
164
165 static int net_lookup_master(int argc, const char **argv)
166 {
167         struct in_addr master_ip;
168         const char *domain=opt_target_workgroup;
169
170         if (argc > 0)
171                 domain=argv[0];
172
173         if (!find_master_ip(domain, &master_ip))
174                 return -1;
175         d_printf("%s\n", inet_ntoa(master_ip));
176         return 0;
177 }
178
179 static int net_lookup_kdc(int argc, const char **argv)
180 {
181 #ifdef HAVE_KRB5
182         krb5_error_code rc;
183         krb5_context ctx;
184         struct sockaddr_in *addrs;
185         int num_kdcs,i;
186         krb5_data realm;
187         char **realms;
188
189         initialize_krb5_error_table();
190         rc = krb5_init_context(&ctx);
191         if (rc) {
192                 DEBUG(1,("krb5_init_context failed (%s)\n", 
193                          error_message(rc)));
194                 return -1;
195         }
196
197         if (argc>0) {
198                 realm.data = CONST_DISCARD(krb5_pointer, argv[0]);
199                 realm.length = strlen(argv[0]);
200         } else if (lp_realm() && *lp_realm()) {
201                 realm.data = (krb5_pointer) lp_realm();
202                 realm.length = strlen(realm.data);
203         } else {
204                 rc = krb5_get_host_realm(ctx, NULL, &realms);
205                 if (rc) {
206                         DEBUG(1,("krb5_gethost_realm failed (%s)\n",
207                                  error_message(rc)));
208                         return -1;
209                 }
210                 realm.data = (krb5_pointer) *realms;
211                 realm.length = strlen(realm.data);
212         }
213
214         rc = krb5_locate_kdc(ctx, &realm, (struct sockaddr **)(void *)&addrs, &num_kdcs, 0);
215         if (rc) {
216                 DEBUG(1, ("krb5_locate_kdc failed (%s)\n", error_message(rc)));
217                 return -1;
218         }
219         for (i=0;i<num_kdcs;i++)
220                 if (addrs[i].sin_family == AF_INET) 
221                         d_printf("%s:%hd\n", inet_ntoa(addrs[i].sin_addr),
222                                  ntohs(addrs[i].sin_port));
223         return 0;
224
225 #endif  
226         DEBUG(1, ("No kerberos support\n"));
227         return -1;
228 }
229
230
231 /* lookup hosts or IP addresses using internal samba lookup fns */
232 int net_lookup(int argc, const char **argv)
233 {
234         int i;
235
236         struct functable table[] = {
237                 {"HOST", net_lookup_host},
238                 {"LDAP", net_lookup_ldap},
239                 {"DC", net_lookup_dc},
240                 {"MASTER", net_lookup_master},
241                 {"KDC", net_lookup_kdc},
242                 {NULL, NULL}
243         };
244
245         if (argc < 1) {
246                 d_printf("\nUsage: \n");
247                 return net_lookup_usage(argc, argv);
248         }
249         for (i=0; table[i].funcname; i++) {
250                 if (StrCaseCmp(argv[0], table[i].funcname) == 0)
251                         return table[i].fn(argc-1, argv+1);
252         }
253
254         /* Default to lookup a hostname so 'net lookup foo#1b' can be 
255            used instead of 'net lookup host foo#1b'.  The host syntax
256            is a bit confusing as non #00 names can't really be 
257            considered hosts as such. */
258
259         return net_lookup_host(argc, argv);
260 }