Removed 'extern int DEBUGLEVEL' as it is now in the smb.h header.
[kai/samba.git] / source / nsswitch / wins.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 2.0
4    a WINS nsswitch module 
5    Copyright (C) Andrew Tridgell 1999
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20    
21 */
22
23 #define NO_SYSLOG
24
25 #include "includes.h"
26 #include <nss.h>
27
28 #ifndef INADDRSZ
29 #define INADDRSZ 4
30 #endif
31
32 /* Use our own create socket code so we don't recurse.... */
33
34 static int wins_lookup_open_socket_in(void)
35 {
36         struct sockaddr_in sock;
37         int val=1;
38         int res;
39
40         memset((char *)&sock,'\0',sizeof(sock));
41
42 #ifdef HAVE_SOCK_SIN_LEN
43         sock.sin_len = sizeof(sock);
44 #endif
45         sock.sin_port = 0;
46         sock.sin_family = AF_INET;
47         sock.sin_addr.s_addr = interpret_addr("0.0.0.0");
48         res = socket(AF_INET, SOCK_DGRAM, 0);
49         if (res == -1)
50                 return -1;
51
52         setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&val,sizeof(val));
53 #ifdef SO_REUSEPORT
54         setsockopt(res,SOL_SOCKET,SO_REUSEPORT,(char *)&val,sizeof(val));
55 #endif /* SO_REUSEPORT */
56
57         /* now we've got a socket - we need to bind it */
58
59         if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) < 0)
60                 return(-1);
61
62         return res;
63 }
64
65 struct in_addr *lookup_backend(const char *name, int *count)
66 {
67         int fd;
68         static int initialised;
69         struct in_addr *ret;
70         struct in_addr  p;
71         int j;
72
73         if (!initialised) {
74                 initialised = 1;
75                 DEBUGLEVEL = 0;
76                 TimeInit();
77                 setup_logging("nss_wins",True);
78                 lp_load(CONFIGFILE,True,False,False);
79                 load_interfaces();
80         }
81
82         *count = 0;
83
84         fd = wins_lookup_open_socket_in();
85         if (fd == -1)
86                 return NULL;
87
88         set_socket_options(fd,"SO_BROADCAST");
89
90 /* The next four lines commented out by JHT
91    and replaced with the four lines following */
92 /*      if( !zero_ip( wins_ip ) ) {
93  *              ret = name_query( fd, name, 0x20, False, True, wins_src_ip(), count );
94  *              goto out;
95  *      }
96  */
97         p = wins_srv_ip();
98         if( !zero_ip(p) ) {
99                 ret = name_query(fd,name,0x20,False,True, p, count);
100                 goto out;
101         }
102
103         if (lp_wins_support()) {
104                 /* we are our own WINS server */
105                 ret = name_query(fd,name,0x20,False,True, *interpret_addr2("127.0.0.1"), count);
106                 goto out;
107         }
108
109         /* uggh, we have to broadcast to each interface in turn */
110         for (j=iface_count() - 1;
111              j >= 0;
112              j--) {
113                 struct in_addr *bcast = iface_n_bcast(j);
114                 ret = name_query(fd,name,0x20,True,True,*bcast,count);
115                 if (ret) break;
116         }
117
118  out:
119
120         close(fd);
121         return ret;
122 }
123
124
125 /****************************************************************************
126 gethostbyname() - we ignore any domain portion of the name and only
127 handle names that are at most 15 characters long
128   **************************************************************************/
129 enum nss_status 
130 _nss_wins_gethostbyname_r(const char *name, struct hostent *he,
131                           char *buffer, size_t buflen, int *errnop,
132                           int *h_errnop)
133 {
134         char **host_addresses;
135         struct in_addr *ip_list;
136         int i, count;
137         size_t namelen = strlen(name) + 1;
138
139         memset(he, '\0', sizeof(*he));
140
141         ip_list = lookup_backend(name, &count);
142         if (!ip_list) {
143                 return NSS_STATUS_NOTFOUND;
144         }
145
146         if (buflen < namelen + (2*count+1)*INADDRSZ) {
147                 /* no ENOMEM error type?! */
148                 return NSS_STATUS_NOTFOUND;
149         }
150
151
152         host_addresses = (char **)buffer;
153         he->h_addr_list = host_addresses;
154         host_addresses[count] = NULL;
155         buffer += (count + 1) * INADDRSZ;
156         buflen += (count + 1) * INADDRSZ;
157         he->h_addrtype = AF_INET;
158         he->h_length = INADDRSZ;
159
160         for (i=0;i<count;i++) {
161                 memcpy(buffer, &ip_list[i].s_addr, INADDRSZ);
162                 *host_addresses = buffer;
163                 buffer += INADDRSZ;
164                 buflen -= INADDRSZ;
165                 host_addresses++;
166         }
167
168         SAFE_FREE(ip_list);
169
170         memcpy(buffer, name, namelen);
171         he->h_name = buffer;
172
173         return NSS_STATUS_SUCCESS;
174 }