00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "includes.h"
00023 #ifdef HAVE_NS_API_H
00024 #undef VOLATILE
00025
00026 #include <ns_daemon.h>
00027 #endif
00028
00029 #ifndef INADDRSZ
00030 #define INADDRSZ 4
00031 #endif
00032
00033 static int initialised;
00034
00035 extern BOOL AllowDebugChange;
00036
00037 NSS_STATUS _nss_wins_gethostbyname_r(const char *hostname, struct hostent *he,
00038 char *buffer, size_t buflen, int *h_errnop);
00039 NSS_STATUS _nss_wins_gethostbyname2_r(const char *name, int af, struct hostent *he,
00040 char *buffer, size_t buflen, int *h_errnop);
00041
00042
00043
00044 static int wins_lookup_open_socket_in(void)
00045 {
00046 struct sockaddr_in sock;
00047 int val=1;
00048 int res;
00049
00050 memset((char *)&sock,'\0',sizeof(sock));
00051
00052 #ifdef HAVE_SOCK_SIN_LEN
00053 sock.sin_len = sizeof(sock);
00054 #endif
00055 sock.sin_port = 0;
00056 sock.sin_family = AF_INET;
00057 sock.sin_addr.s_addr = interpret_addr("0.0.0.0");
00058 res = socket(AF_INET, SOCK_DGRAM, 0);
00059 if (res == -1)
00060 return -1;
00061
00062 setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&val,sizeof(val));
00063 #ifdef SO_REUSEPORT
00064 setsockopt(res,SOL_SOCKET,SO_REUSEPORT,(char *)&val,sizeof(val));
00065 #endif
00066
00067
00068
00069 if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) < 0) {
00070 close(res);
00071 return(-1);
00072 }
00073
00074 set_socket_options(res,"SO_BROADCAST");
00075
00076 return res;
00077 }
00078
00079
00080 static void nss_wins_init(void)
00081 {
00082 initialised = 1;
00083 DEBUGLEVEL = 0;
00084 AllowDebugChange = False;
00085
00086 TimeInit();
00087 setup_logging("nss_wins",False);
00088 load_case_tables();
00089 lp_load(dyn_CONFIGFILE,True,False,False,True);
00090 load_interfaces();
00091 }
00092
00093 static struct in_addr *lookup_byname_backend(const char *name, int *count)
00094 {
00095 int fd = -1;
00096 struct ip_service *address = NULL;
00097 struct in_addr *ret = NULL;
00098 int j, flags = 0;
00099
00100 if (!initialised) {
00101 nss_wins_init();
00102 }
00103
00104 *count = 0;
00105
00106
00107 if (resolve_wins(name,0x00,&address,count)) {
00108 if ( (ret = SMB_MALLOC_P(struct in_addr)) == NULL ) {
00109 free( address );
00110 return NULL;
00111 }
00112 *ret = address[0].ip;
00113 free( address );
00114 return ret;
00115 }
00116
00117 fd = wins_lookup_open_socket_in();
00118 if (fd == -1) {
00119 return NULL;
00120 }
00121
00122
00123 for (j=iface_count() - 1;j >= 0;j--) {
00124 struct in_addr *bcast = iface_n_bcast(j);
00125 ret = name_query(fd,name,0x00,True,True,*bcast,count, &flags, NULL);
00126 if (ret) break;
00127 }
00128
00129 close(fd);
00130 return ret;
00131 }
00132
00133 #ifdef HAVE_NS_API_H
00134
00135 static NODE_STATUS_STRUCT *lookup_byaddr_backend(char *addr, int *count)
00136 {
00137 int fd;
00138 struct in_addr ip;
00139 struct nmb_name nname;
00140 NODE_STATUS_STRUCT *status;
00141
00142 if (!initialised) {
00143 nss_wins_init();
00144 }
00145
00146 fd = wins_lookup_open_socket_in();
00147 if (fd == -1)
00148 return NULL;
00149
00150 make_nmb_name(&nname, "*", 0);
00151 ip = *interpret_addr2(addr);
00152 status = node_status_query(fd,&nname,ip, count, NULL);
00153
00154 close(fd);
00155 return status;
00156 }
00157
00158
00159
00160 int init(void)
00161 {
00162 nsd_logprintf(NSD_LOG_MIN, "entering init (wins)\n");
00163 nss_wins_init();
00164 return NSD_OK;
00165 }
00166
00167 int lookup(nsd_file_t *rq)
00168 {
00169 char *map;
00170 char *key;
00171 char *addr;
00172 struct in_addr *ip_list;
00173 NODE_STATUS_STRUCT *status;
00174 int i, count, len, size;
00175 char response[1024];
00176 BOOL found = False;
00177
00178 nsd_logprintf(NSD_LOG_MIN, "entering lookup (wins)\n");
00179 if (! rq)
00180 return NSD_ERROR;
00181
00182 map = nsd_attr_fetch_string(rq->f_attrs, "table", (char*)0);
00183 if (! map) {
00184 rq->f_status = NS_FATAL;
00185 return NSD_ERROR;
00186 }
00187
00188 key = nsd_attr_fetch_string(rq->f_attrs, "key", (char*)0);
00189 if (! key || ! *key) {
00190 rq->f_status = NS_FATAL;
00191 return NSD_ERROR;
00192 }
00193
00194 response[0] = '\0';
00195 len = sizeof(response) - 2;
00196
00197
00198
00199
00200
00201 if (StrCaseCmp(map,"hosts.byaddr") == 0) {
00202 if ( status = lookup_byaddr_backend(key, &count)) {
00203 size = strlen(key) + 1;
00204 if (size > len) {
00205 free(status);
00206 return NSD_ERROR;
00207 }
00208 len -= size;
00209 strncat(response,key,size);
00210 strncat(response,"\t",1);
00211 for (i = 0; i < count; i++) {
00212
00213 if (status[i].flags & 0x80) continue;
00214 if (status[i].type == 0x20) {
00215 size = sizeof(status[i].name) + 1;
00216 if (size > len) {
00217 free(status);
00218 return NSD_ERROR;
00219 }
00220 len -= size;
00221 strncat(response, status[i].name, size);
00222 strncat(response, " ", 1);
00223 found = True;
00224 }
00225 }
00226 response[strlen(response)-1] = '\n';
00227 free(status);
00228 }
00229 } else if (StrCaseCmp(map,"hosts.byname") == 0) {
00230 if (ip_list = lookup_byname_backend(key, &count)) {
00231 for (i = count; i ; i--) {
00232 addr = inet_ntoa(ip_list[i-1]);
00233 size = strlen(addr) + 1;
00234 if (size > len) {
00235 free(ip_list);
00236 return NSD_ERROR;
00237 }
00238 len -= size;
00239 if (i != 0)
00240 response[strlen(response)-1] = ' ';
00241 strncat(response,addr,size);
00242 strncat(response,"\t",1);
00243 }
00244 size = strlen(key) + 1;
00245 if (size > len) {
00246 free(ip_list);
00247 return NSD_ERROR;
00248 }
00249 strncat(response,key,size);
00250 strncat(response,"\n",1);
00251 found = True;
00252 free(ip_list);
00253 }
00254 }
00255
00256 if (found) {
00257 nsd_logprintf(NSD_LOG_LOW, "lookup (wins %s) %s\n",map,response);
00258 nsd_set_result(rq,NS_SUCCESS,response,strlen(response),VOLATILE);
00259 return NSD_OK;
00260 }
00261 nsd_logprintf(NSD_LOG_LOW, "lookup (wins) not found\n");
00262 rq->f_status = NS_NOTFOUND;
00263 return NSD_NEXT;
00264 }
00265
00266 #else
00267
00268
00269
00270
00271
00272 static char *get_static(char **buffer, size_t *buflen, int len)
00273 {
00274 char *result;
00275
00276
00277
00278
00279 if ((buffer == NULL) || (buflen == NULL) || (*buflen < len)) {
00280 return NULL;
00281 }
00282
00283
00284
00285 result = *buffer;
00286 *buffer += len;
00287 *buflen -= len;
00288
00289 return result;
00290 }
00291
00292
00293
00294
00295
00296 NSS_STATUS
00297 _nss_wins_gethostbyname_r(const char *hostname, struct hostent *he,
00298 char *buffer, size_t buflen, int *h_errnop)
00299 {
00300 struct in_addr *ip_list;
00301 int i, count;
00302 fstring name;
00303 size_t namelen;
00304
00305 memset(he, '\0', sizeof(*he));
00306 fstrcpy(name, hostname);
00307
00308
00309
00310 ip_list = lookup_byname_backend(name, &count);
00311
00312 if (!ip_list)
00313 return NSS_STATUS_NOTFOUND;
00314
00315
00316
00317 namelen = strlen(name) + 1;
00318
00319 if ((he->h_name = get_static(&buffer, &buflen, namelen)) == NULL)
00320 return NSS_STATUS_TRYAGAIN;
00321
00322 memcpy(he->h_name, name, namelen);
00323
00324
00325
00326 if ((i = (unsigned long)(buffer) % sizeof(char*)) != 0)
00327 i = sizeof(char*) - i;
00328
00329 if (get_static(&buffer, &buflen, i) == NULL)
00330 return NSS_STATUS_TRYAGAIN;
00331
00332 if ((he->h_addr_list = (char **)get_static(
00333 &buffer, &buflen, (count + 1) * sizeof(char *))) == NULL)
00334 return NSS_STATUS_TRYAGAIN;
00335
00336 for (i = 0; i < count; i++) {
00337 if ((he->h_addr_list[i] = get_static(&buffer, &buflen,
00338 INADDRSZ)) == NULL)
00339 return NSS_STATUS_TRYAGAIN;
00340 memcpy(he->h_addr_list[i], &ip_list[i], INADDRSZ);
00341 }
00342
00343 he->h_addr_list[count] = NULL;
00344
00345 if (ip_list)
00346 free(ip_list);
00347
00348
00349
00350 he->h_addrtype = AF_INET;
00351 he->h_length = INADDRSZ;
00352
00353
00354
00355 if ((i = (unsigned long)(buffer) % sizeof(char*)) != 0)
00356 i = sizeof(char*) - i;
00357
00358 if (get_static(&buffer, &buflen, i) == NULL)
00359 return NSS_STATUS_TRYAGAIN;
00360
00361 if ((he->h_aliases = (char **)get_static(
00362 &buffer, &buflen, sizeof(char *))) == NULL)
00363 return NSS_STATUS_TRYAGAIN;
00364
00365 he->h_aliases[0] = NULL;
00366
00367 return NSS_STATUS_SUCCESS;
00368 }
00369
00370
00371 NSS_STATUS
00372 _nss_wins_gethostbyname2_r(const char *name, int af, struct hostent *he,
00373 char *buffer, size_t buflen, int *h_errnop)
00374 {
00375 if(af!=AF_INET) {
00376 *h_errnop = NO_DATA;
00377 return NSS_STATUS_UNAVAIL;
00378 }
00379
00380 return _nss_wins_gethostbyname_r(
00381 name, he, buffer, buflen, h_errnop);
00382 }
00383 #endif