root/source3/winbindd/winbindd_wins.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. wins_lookup_open_socket_in
  2. lookup_byaddr_backend
  3. lookup_byname_backend
  4. winbindd_wins_byip
  5. winbindd_wins_byname

   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 
  26 #undef DBGC_CLASS
  27 #define DBGC_CLASS DBGC_WINBIND
  28 
  29 /* Use our own create socket code so we don't recurse.... */
  30 
  31 static int wins_lookup_open_socket_in(void)
     /* [<][>][^][v][top][bottom][index][help] */
  32 {
  33         struct sockaddr_in sock;
  34         int val=1;
  35         int res;
  36 
  37         memset((char *)&sock,'\0',sizeof(sock));
  38 
  39 #ifdef HAVE_SOCK_SIN_LEN
  40         sock.sin_len = sizeof(sock);
  41 #endif
  42         sock.sin_port = 0;
  43         sock.sin_family = AF_INET;
  44         sock.sin_addr.s_addr = interpret_addr("0.0.0.0");
  45         res = socket(AF_INET, SOCK_DGRAM, 0);
  46         if (res == -1)
  47                 return -1;
  48 
  49         if (setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&val,sizeof(val))) {
  50                 close(res);
  51                 return -1;
  52         }
  53 #ifdef SO_REUSEPORT
  54         if (setsockopt(res,SOL_SOCKET,SO_REUSEPORT,(char *)&val,sizeof(val))) {
  55                 close(res);
  56                 return -1;
  57         }
  58 #endif /* SO_REUSEPORT */
  59 
  60         /* now we've got a socket - we need to bind it */
  61 
  62         if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) < 0) {
  63                 close(res);
  64                 return(-1);
  65         }
  66 
  67         set_socket_options(res,"SO_BROADCAST");
  68 
  69         return res;
  70 }
  71 
  72 
  73 static NODE_STATUS_STRUCT *lookup_byaddr_backend(const char *addr, int *count)
     /* [<][>][^][v][top][bottom][index][help] */
  74 {
  75         int fd;
  76         struct sockaddr_storage ss;
  77         struct nmb_name nname;
  78         NODE_STATUS_STRUCT *status;
  79 
  80         fd = wins_lookup_open_socket_in();
  81         if (fd == -1)
  82                 return NULL;
  83 
  84         make_nmb_name(&nname, "*", 0);
  85         if (!interpret_string_addr(&ss, addr, AI_NUMERICHOST)) {
  86                 return NULL;
  87         }
  88         status = node_status_query(fd, &nname, &ss, count, NULL);
  89 
  90         close(fd);
  91         return status;
  92 }
  93 
  94 static struct sockaddr_storage *lookup_byname_backend(const char *name,
     /* [<][>][^][v][top][bottom][index][help] */
  95                                         int *count)
  96 {
  97         int fd;
  98         struct ip_service *ret = NULL;
  99         struct sockaddr_storage *return_ss = NULL;
 100         int j, i, flags = 0;
 101 
 102         *count = 0;
 103 
 104         /* always try with wins first */
 105         if (NT_STATUS_IS_OK(resolve_wins(name,0x20,&ret,count))) {
 106                 if ( *count == 0 )
 107                         return NULL;
 108                 if ( (return_ss = SMB_MALLOC_ARRAY(struct sockaddr_storage, *count)) == NULL ) {
 109                         free( ret );
 110                         return NULL;
 111                 }
 112 
 113                 /* copy the IP addresses */
 114                 for ( i=0; i<(*count); i++ )
 115                         return_ss[i] = ret[i].ss;
 116 
 117                 free( ret );
 118                 return return_ss;
 119         }
 120 
 121         fd = wins_lookup_open_socket_in();
 122         if (fd == -1) {
 123                 return NULL;
 124         }
 125 
 126         /* uggh, we have to broadcast to each interface in turn */
 127         for (j=iface_count() - 1;
 128              j >= 0;
 129              j--) {
 130                 const struct sockaddr_storage *bcast_ss = iface_n_bcast(j);
 131                 if (!bcast_ss) {
 132                         continue;
 133                 }
 134                 return_ss = name_query(fd,name,0x20,True,True,bcast_ss,count, &flags, NULL);
 135                 if (return_ss) {
 136                         break;
 137                 }
 138         }
 139 
 140         close(fd);
 141         return return_ss;
 142 }
 143 
 144 /* Get hostname from IP  */
 145 
 146 void winbindd_wins_byip(struct winbindd_cli_state *state)
     /* [<][>][^][v][top][bottom][index][help] */
 147 {
 148         fstring response;
 149         int i, count, maxlen, size;
 150         NODE_STATUS_STRUCT *status;
 151 
 152         /* Ensure null termination */
 153         state->request.data.winsreq[sizeof(state->request.data.winsreq)-1]='\0';
 154 
 155         DEBUG(3, ("[%5lu]: wins_byip %s\n", (unsigned long)state->pid,
 156                 state->request.data.winsreq));
 157 
 158         *response = '\0';
 159         maxlen = sizeof(response) - 1;
 160 
 161         if ((status = lookup_byaddr_backend(state->request.data.winsreq, &count))){
 162             size = strlen(state->request.data.winsreq);
 163             if (size > maxlen) {
 164                 SAFE_FREE(status);
 165                 request_error(state);
 166                 return;
 167             }
 168             fstrcat(response,state->request.data.winsreq);
 169             fstrcat(response,"\t");
 170             for (i = 0; i < count; i++) {
 171                 /* ignore group names */
 172                 if (status[i].flags & 0x80) continue;
 173                 if (status[i].type == 0x20) {
 174                         size = sizeof(status[i].name) + strlen(response);
 175                         if (size > maxlen) {
 176                             SAFE_FREE(status);
 177                             request_error(state);
 178                             return;
 179                         }
 180                         fstrcat(response, status[i].name);
 181                         fstrcat(response, " ");
 182                 }
 183             }
 184             /* make last character a newline */
 185             response[strlen(response)-1] = '\n';
 186             SAFE_FREE(status);
 187         }
 188         fstrcpy(state->response.data.winsresp,response);
 189         request_ok(state);
 190 }
 191 
 192 /* Get IP from hostname */
 193 
 194 void winbindd_wins_byname(struct winbindd_cli_state *state)
     /* [<][>][^][v][top][bottom][index][help] */
 195 {
 196         struct sockaddr_storage *ip_list = NULL;
 197         int i, count, maxlen, size;
 198         fstring response;
 199         char addr[INET6_ADDRSTRLEN];
 200 
 201         /* Ensure null termination */
 202         state->request.data.winsreq[sizeof(state->request.data.winsreq)-1]='\0';
 203 
 204         DEBUG(3, ("[%5lu]: wins_byname %s\n", (unsigned long)state->pid,
 205                 state->request.data.winsreq));
 206 
 207         *response = '\0';
 208         maxlen = sizeof(response) - 1;
 209 
 210         if ((ip_list = lookup_byname_backend(state->request.data.winsreq,&count))){
 211                 for (i = count; i ; i--) {
 212                         print_sockaddr(addr, sizeof(addr), &ip_list[i-1]);
 213                         size = strlen(addr);
 214                         if (size > maxlen) {
 215                                 SAFE_FREE(ip_list);
 216                                 request_error(state);
 217                                 return;
 218                         }
 219                         if (i != 0) {
 220                                 /* Clear out the newline character */
 221                                 /* But only if there is something in there,
 222                                 otherwise we clobber something in the stack */
 223                                 if (strlen(response)) {
 224                                         response[strlen(response)-1] = ' ';
 225                                 }
 226                         }
 227                         fstrcat(response,addr);
 228                         fstrcat(response,"\t");
 229                 }
 230                 size = strlen(state->request.data.winsreq) + strlen(response);
 231                 if (size > maxlen) {
 232                     SAFE_FREE(ip_list);
 233                     request_error(state);
 234                     return;
 235                 }
 236                 fstrcat(response,state->request.data.winsreq);
 237                 fstrcat(response,"\n");
 238                 SAFE_FREE(ip_list);
 239         } else {
 240                 request_error(state);
 241                 return;
 242         }
 243 
 244         fstrcpy(state->response.data.winsresp,response);
 245 
 246         request_ok(state);
 247 }

/* [<][>][^][v][top][bottom][index][help] */