a468b0f8b3dc8cbb41cfb3f5b04d133ed83e0b25
[kai/samba.git] / source3 / winbindd / winbindd_wins.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Winbind daemon - WINS related functions
5
6    Copyright (C) Andrew Tridgell 1999
7    Copyright (C) Herb Lewis 2002
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "winbindd.h"
25 #include "libsmb/nmblib.h"
26
27 #undef DBGC_CLASS
28 #define DBGC_CLASS DBGC_WINBIND
29
30 static struct sockaddr_storage *lookup_byname_backend(TALLOC_CTX *mem_ctx,
31                                                       const char *name,
32                                                       int *count)
33 {
34         struct ip_service *ret = NULL;
35         struct sockaddr_storage *return_ss = NULL;
36         int j, i;
37         NTSTATUS status;
38
39         *count = 0;
40
41         /* always try with wins first */
42         if (NT_STATUS_IS_OK(resolve_wins(name,0x20,&ret,count))) {
43                 if ( *count == 0 )
44                         return NULL;
45                 return_ss = TALLOC_ARRAY(mem_ctx, struct sockaddr_storage,
46                                          *count);
47                 if (return_ss == NULL ) {
48                         free( ret );
49                         return NULL;
50                 }
51
52                 /* copy the IP addresses */
53                 for ( i=0; i<(*count); i++ )
54                         return_ss[i] = ret[i].ss;
55
56                 free( ret );
57                 return return_ss;
58         }
59
60         /* uggh, we have to broadcast to each interface in turn */
61         for (j=iface_count() - 1;
62              j >= 0;
63              j--) {
64                 const struct sockaddr_storage *bcast_ss = iface_n_bcast(j);
65                 if (!bcast_ss) {
66                         continue;
67                 }
68                 status = name_query(name, 0x20, True, True,bcast_ss,
69                                     mem_ctx, &return_ss, count, NULL);
70                 if (NT_STATUS_IS_OK(status)) {
71                         break;
72                 }
73         }
74
75         return return_ss;
76 }
77
78 /* Get IP from hostname */
79
80 void winbindd_wins_byname(struct winbindd_cli_state *state)
81 {
82         struct sockaddr_storage *ip_list = NULL;
83         int i, count, maxlen, size;
84         fstring response;
85         char addr[INET6_ADDRSTRLEN];
86
87         /* Ensure null termination */
88         state->request->data.winsreq[sizeof(state->request->data.winsreq)-1]='\0';
89
90         DEBUG(3, ("[%5lu]: wins_byname %s\n", (unsigned long)state->pid,
91                 state->request->data.winsreq));
92
93         *response = '\0';
94         maxlen = sizeof(response) - 1;
95
96         ip_list = lookup_byname_backend(
97                 state->mem_ctx, state->request->data.winsreq, &count);
98         if (ip_list != NULL){
99                 for (i = count; i ; i--) {
100                         print_sockaddr(addr, sizeof(addr), &ip_list[i-1]);
101                         size = strlen(addr);
102                         if (size > maxlen) {
103                                 TALLOC_FREE(ip_list);
104                                 request_error(state);
105                                 return;
106                         }
107                         if (i != 0) {
108                                 /* Clear out the newline character */
109                                 /* But only if there is something in there,
110                                 otherwise we clobber something in the stack */
111                                 if (strlen(response)) {
112                                         response[strlen(response)-1] = ' ';
113                                 }
114                         }
115                         strlcat(response,addr,sizeof(response));
116                         strlcat(response,"\t",sizeof(response));
117                 }
118                 size = strlen(state->request->data.winsreq) + strlen(response);
119                 if (size > maxlen) {
120                     TALLOC_FREE(ip_list);
121                     request_error(state);
122                     return;
123                 }
124                 strlcat(response,state->request->data.winsreq,sizeof(response));
125                 strlcat(response,"\n",sizeof(response));
126                 TALLOC_FREE(ip_list);
127         } else {
128                 request_error(state);
129                 return;
130         }
131
132         strlcpy(state->response->data.winsresp,
133                 response,
134                 sizeof(state->response->data.winsresp));
135
136         request_ok(state);
137 }