~lefteris-nikoltsios/+junk/samba-lp1016895

« back to all changes in this revision

Viewing changes to source3/libaddns/dnssock.c

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2011-12-21 13:18:04 UTC
  • mfrom: (0.39.21 sid)
  • Revision ID: package-import@ubuntu.com-20111221131804-xtlr39wx6njehxxr
Tags: 2:3.6.1-3ubuntu1
* Merge from Debian testing.  Remaining changes:
  + debian/patches/VERSION.patch:
    - set SAMBA_VERSION_SUFFIX to Ubuntu.
  + debian/patches/error-trans.fix-276472:
    - Add the translation of Unix Error code -ENOTSUP to NT Error Code
    - NT_STATUS_NOT_SUPPORTED to prevent the Permission denied error.
  + debian/smb.conf:
    - add "(Samba, Ubuntu)" to server string.
    - comment out the default [homes] share, and add a comment about
      "valid users = %S" to show users how to restrict access to
      \\server\username to only username.
    - Set 'usershare allow guests', so that usershare admins are 
      allowed to create public shares in addition to authenticated
      ones.
    - add map to guest = Bad user, maps bad username to guest access.
  + debian/samba-common.config:
    - Do not change priority to high if dhclient3 is installed.
    - Use priority medium instead of high for the workgroup question.
  + debian/control:
    - Don't build against or suggest ctdb.
    - Add dependency on samba-common-bin to samba.
  + Add ufw integration:
    - Created debian/samba.ufw.profile
    - debian/rules, debian/samba.dirs, debian/samba.files: install
      profile
    - debian/control: have samba suggest ufw
  + Add apport hook:
    - Created debian/source_samba.py.
    - debian/rules, debian/samba.dirs, debian/samba-common-bin.files: install
  + Switch to upstart:
    - Add debian/samba.{nmbd,smbd}.upstart.
  + debian/samba.logrotate, debian/samba-common.dhcp, debian/samba.if-up:
    - Make them upstart compatible
  + debian/samba.postinst: 
    - Avoid scary pdbedit warnings on first import.
  + debian/samba-common.postinst: Add more informative error message for
    the case where smb.conf was manually deleted
  + debian/patches/fix-debuglevel-name-conflict.patch: don't use 'debug_level'
    as a global variable name in an NSS module 
  + Dropped:
    - debian/patches/error-trans.fix-276472
    - debian/patches/fix-debuglevel-name-conflict.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
  Linux DNS client library implementation
3
 
 
4
 
  Copyright (C) 2006 Krishna Ganugapati <krishnag@centeris.com>
5
 
  Copyright (C) 2006 Gerald Carter <jerry@samba.org>
6
 
 
7
 
     ** NOTE! The following LGPL license applies to the libaddns
8
 
     ** library. This does NOT imply that all of Samba is released
9
 
     ** under the LGPL
10
 
 
11
 
  This library is free software; you can redistribute it and/or
12
 
  modify it under the terms of the GNU Lesser General Public
13
 
  License as published by the Free Software Foundation; either
14
 
  version 2.1 of the License, or (at your option) any later version.
15
 
 
16
 
  This library is distributed in the hope that it will be useful,
17
 
  but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19
 
  Lesser General Public License for more details.
20
 
 
21
 
  You should have received a copy of the GNU Lesser General Public
22
 
  License along with this library; if not, see <http://www.gnu.org/licenses/>.
23
 
*/
24
 
 
25
 
#include "dns.h"
26
 
#include <sys/time.h>
27
 
#include <unistd.h>
28
 
 
29
 
static int destroy_dns_connection(struct dns_connection *conn)
30
 
{
31
 
        return close(conn->s);
32
 
}
33
 
 
34
 
/********************************************************************
35
 
********************************************************************/
36
 
 
37
 
static DNS_ERROR dns_tcp_open( const char *nameserver,
38
 
                               TALLOC_CTX *mem_ctx,
39
 
                               struct dns_connection **result )
40
 
{
41
 
        uint32_t ulAddress;
42
 
        struct hostent *pHost;
43
 
        struct sockaddr_in s_in;
44
 
        struct dns_connection *conn;
45
 
        int res;
46
 
 
47
 
        if (!(conn = talloc(mem_ctx, struct dns_connection))) {
48
 
                return ERROR_DNS_NO_MEMORY;
49
 
        }
50
 
 
51
 
        if ( (ulAddress = inet_addr( nameserver )) == INADDR_NONE ) {
52
 
                if ( (pHost = gethostbyname( nameserver )) == NULL ) {
53
 
                        TALLOC_FREE(conn);
54
 
                        return ERROR_DNS_INVALID_NAME_SERVER;
55
 
                }
56
 
                memcpy( &ulAddress, pHost->h_addr, pHost->h_length );
57
 
        }
58
 
 
59
 
        conn->s = socket( PF_INET, SOCK_STREAM, 0 );
60
 
        if (conn->s == -1) {
61
 
                TALLOC_FREE(conn);
62
 
                return ERROR_DNS_CONNECTION_FAILED;
63
 
        }
64
 
 
65
 
        talloc_set_destructor(conn, destroy_dns_connection);
66
 
 
67
 
        s_in.sin_family = AF_INET;
68
 
        s_in.sin_addr.s_addr = ulAddress;
69
 
        s_in.sin_port = htons( DNS_TCP_PORT );
70
 
 
71
 
        res = connect(conn->s, (struct sockaddr*)&s_in, sizeof( s_in ));
72
 
        if (res == -1) {
73
 
                TALLOC_FREE(conn);
74
 
                return ERROR_DNS_CONNECTION_FAILED;
75
 
        }
76
 
 
77
 
        conn->hType = DNS_TCP;
78
 
 
79
 
        *result = conn;
80
 
        return ERROR_DNS_SUCCESS;
81
 
}
82
 
 
83
 
/********************************************************************
84
 
********************************************************************/
85
 
 
86
 
static DNS_ERROR dns_udp_open( const char *nameserver,
87
 
                               TALLOC_CTX *mem_ctx,
88
 
                               struct dns_connection **result )
89
 
{
90
 
        unsigned long ulAddress;
91
 
        struct hostent *pHost;
92
 
        struct sockaddr_in RecvAddr;
93
 
        struct dns_connection *conn;
94
 
 
95
 
        if (!(conn = talloc(NULL, struct dns_connection))) {
96
 
                return ERROR_DNS_NO_MEMORY;
97
 
        }
98
 
 
99
 
        if ( (ulAddress = inet_addr( nameserver )) == INADDR_NONE ) {
100
 
                if ( (pHost = gethostbyname( nameserver )) == NULL ) {
101
 
                        TALLOC_FREE(conn);
102
 
                        return ERROR_DNS_INVALID_NAME_SERVER;
103
 
                }
104
 
                memcpy( &ulAddress, pHost->h_addr, pHost->h_length );
105
 
        }
106
 
        
107
 
        /* Create a socket for sending data */
108
 
 
109
 
        conn->s = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
110
 
        if (conn->s == -1) {
111
 
                TALLOC_FREE(conn);
112
 
                return ERROR_DNS_CONNECTION_FAILED;
113
 
        }
114
 
 
115
 
        talloc_set_destructor(conn, destroy_dns_connection);
116
 
 
117
 
        /* Set up the RecvAddr structure with the IP address of
118
 
           the receiver (in this example case "123.456.789.1")
119
 
           and the specified port number. */
120
 
 
121
 
        ZERO_STRUCT(RecvAddr);
122
 
        RecvAddr.sin_family = AF_INET;
123
 
        RecvAddr.sin_port = htons( DNS_UDP_PORT );
124
 
        RecvAddr.sin_addr.s_addr = ulAddress;
125
 
 
126
 
        conn->hType = DNS_UDP;
127
 
        memcpy( &conn->RecvAddr, &RecvAddr, sizeof( struct sockaddr_in ) );
128
 
 
129
 
        *result = conn;
130
 
        return ERROR_DNS_SUCCESS;
131
 
}
132
 
 
133
 
/********************************************************************
134
 
********************************************************************/
135
 
 
136
 
DNS_ERROR dns_open_connection( const char *nameserver, int32 dwType,
137
 
                    TALLOC_CTX *mem_ctx,
138
 
                    struct dns_connection **conn )
139
 
{
140
 
        switch ( dwType ) {
141
 
        case DNS_TCP:
142
 
                return dns_tcp_open( nameserver, mem_ctx, conn );
143
 
        case DNS_UDP:
144
 
                return dns_udp_open( nameserver, mem_ctx, conn );
145
 
        }
146
 
        
147
 
        return ERROR_DNS_INVALID_PARAMETER;
148
 
}
149
 
 
150
 
static DNS_ERROR write_all(int fd, uint8 *data, size_t len)
151
 
{
152
 
        size_t total = 0;
153
 
 
154
 
        while (total < len) {
155
 
 
156
 
                ssize_t ret = write(fd, data + total, len - total);
157
 
 
158
 
                if (ret <= 0) {
159
 
                        /*
160
 
                         * EOF or error
161
 
                         */
162
 
                        return ERROR_DNS_SOCKET_ERROR;
163
 
                }
164
 
 
165
 
                total += ret;
166
 
        }
167
 
 
168
 
        return ERROR_DNS_SUCCESS;
169
 
}
170
 
 
171
 
static DNS_ERROR dns_send_tcp(struct dns_connection *conn,
172
 
                              const struct dns_buffer *buf)
173
 
{
174
 
        uint16 len = htons(buf->offset);
175
 
        DNS_ERROR err;
176
 
 
177
 
        err = write_all(conn->s, (uint8 *)&len, sizeof(len));
178
 
        if (!ERR_DNS_IS_OK(err)) return err;
179
 
 
180
 
        return write_all(conn->s, buf->data, buf->offset);
181
 
}
182
 
 
183
 
static DNS_ERROR dns_send_udp(struct dns_connection *conn,
184
 
                              const struct dns_buffer *buf)
185
 
{
186
 
        ssize_t ret;
187
 
 
188
 
        ret = sendto(conn->s, buf->data, buf->offset, 0,
189
 
                     (struct sockaddr *)&conn->RecvAddr,
190
 
                     sizeof(conn->RecvAddr));
191
 
 
192
 
        if (ret != buf->offset) {
193
 
                return ERROR_DNS_SOCKET_ERROR;
194
 
        }
195
 
 
196
 
        return ERROR_DNS_SUCCESS;
197
 
}
198
 
 
199
 
DNS_ERROR dns_send(struct dns_connection *conn, const struct dns_buffer *buf)
200
 
{
201
 
        if (conn->hType == DNS_TCP) {
202
 
                return dns_send_tcp(conn, buf);
203
 
        }
204
 
 
205
 
        if (conn->hType == DNS_UDP) {
206
 
                return dns_send_udp(conn, buf);
207
 
        }
208
 
 
209
 
        return ERROR_DNS_INVALID_PARAMETER;
210
 
}
211
 
 
212
 
static DNS_ERROR read_all(int fd, uint8 *data, size_t len)
213
 
{
214
 
        size_t total = 0;
215
 
        fd_set rfds;
216
 
        struct timeval tv;
217
 
 
218
 
        while (total < len) {
219
 
                ssize_t ret;
220
 
                int fd_ready;
221
 
                
222
 
                if (fd < 0 || fd >= FD_SETSIZE) {
223
 
                        /* read timeout */
224
 
                        return ERROR_DNS_SOCKET_ERROR;
225
 
                }
226
 
 
227
 
                FD_ZERO( &rfds );
228
 
                FD_SET( fd, &rfds );
229
 
 
230
 
                /* 10 second timeout */
231
 
                tv.tv_sec = 10;
232
 
                tv.tv_usec = 0;
233
 
                
234
 
                fd_ready = select( fd+1, &rfds, NULL, NULL, &tv );
235
 
                if ( fd_ready == 0 ) {
236
 
                        /* read timeout */
237
 
                        return ERROR_DNS_SOCKET_ERROR;
238
 
                }
239
 
 
240
 
                ret = read(fd, data + total, len - total);
241
 
                if (ret <= 0) {
242
 
                        /* EOF or error */
243
 
                        return ERROR_DNS_SOCKET_ERROR;
244
 
                }
245
 
 
246
 
                total += ret;
247
 
        }
248
 
 
249
 
        return ERROR_DNS_SUCCESS;
250
 
}
251
 
 
252
 
static DNS_ERROR dns_receive_tcp(TALLOC_CTX *mem_ctx,
253
 
                                 struct dns_connection *conn,
254
 
                                 struct dns_buffer **presult)
255
 
{
256
 
        struct dns_buffer *buf;
257
 
        DNS_ERROR err;
258
 
        uint16 len;
259
 
 
260
 
        if (!(buf = TALLOC_ZERO_P(mem_ctx, struct dns_buffer))) {
261
 
                return ERROR_DNS_NO_MEMORY;
262
 
        }
263
 
 
264
 
        err = read_all(conn->s, (uint8 *)&len, sizeof(len));
265
 
        if (!ERR_DNS_IS_OK(err)) {
266
 
                return err;
267
 
        }
268
 
 
269
 
        buf->size = ntohs(len);
270
 
 
271
 
        if (buf->size) {
272
 
                if (!(buf->data = TALLOC_ARRAY(buf, uint8, buf->size))) {
273
 
                        TALLOC_FREE(buf);
274
 
                        return ERROR_DNS_NO_MEMORY;
275
 
                }
276
 
        } else {
277
 
                buf->data = NULL;
278
 
        }
279
 
 
280
 
        err = read_all(conn->s, buf->data, buf->size);
281
 
        if (!ERR_DNS_IS_OK(err)) {
282
 
                TALLOC_FREE(buf);
283
 
                return err;
284
 
        }
285
 
 
286
 
        *presult = buf;
287
 
        return ERROR_DNS_SUCCESS;
288
 
}
289
 
 
290
 
static DNS_ERROR dns_receive_udp(TALLOC_CTX *mem_ctx,
291
 
                                 struct dns_connection *conn,
292
 
                                 struct dns_buffer **presult)
293
 
{
294
 
        struct dns_buffer *buf;
295
 
        ssize_t received;
296
 
 
297
 
        if (!(buf = TALLOC_ZERO_P(mem_ctx, struct dns_buffer))) {
298
 
                return ERROR_DNS_NO_MEMORY;
299
 
        }
300
 
 
301
 
        /*
302
 
         * UDP based DNS can only be 512 bytes
303
 
         */
304
 
 
305
 
        if (!(buf->data = TALLOC_ARRAY(buf, uint8, 512))) {
306
 
                TALLOC_FREE(buf);
307
 
                return ERROR_DNS_NO_MEMORY;
308
 
        }
309
 
 
310
 
        received = recv(conn->s, (void *)buf->data, 512, 0);
311
 
 
312
 
        if (received == -1) {
313
 
                TALLOC_FREE(buf);
314
 
                return ERROR_DNS_SOCKET_ERROR;
315
 
        }
316
 
 
317
 
        if (received > 512) {
318
 
                TALLOC_FREE(buf);
319
 
                return ERROR_DNS_BAD_RESPONSE;
320
 
        }
321
 
 
322
 
        buf->size = received;
323
 
        buf->offset = 0;
324
 
 
325
 
        *presult = buf;
326
 
        return ERROR_DNS_SUCCESS;
327
 
}
328
 
 
329
 
DNS_ERROR dns_receive(TALLOC_CTX *mem_ctx, struct dns_connection *conn,
330
 
                      struct dns_buffer **presult)
331
 
{
332
 
        if (conn->hType == DNS_TCP) {
333
 
                return dns_receive_tcp(mem_ctx, conn, presult);
334
 
        }
335
 
 
336
 
        if (conn->hType == DNS_UDP) {
337
 
                return dns_receive_udp(mem_ctx, conn, presult);
338
 
        }
339
 
 
340
 
        return ERROR_DNS_INVALID_PARAMETER;
341
 
}
342
 
 
343
 
DNS_ERROR dns_transaction(TALLOC_CTX *mem_ctx, struct dns_connection *conn,
344
 
                          const struct dns_request *req,
345
 
                          struct dns_request **resp)
346
 
{
347
 
        struct dns_buffer *buf = NULL;
348
 
        DNS_ERROR err;
349
 
 
350
 
        err = dns_marshall_request(conn, req, &buf);
351
 
        if (!ERR_DNS_IS_OK(err)) goto error;
352
 
 
353
 
        err = dns_send(conn, buf);
354
 
        if (!ERR_DNS_IS_OK(err)) goto error;
355
 
        TALLOC_FREE(buf);
356
 
 
357
 
        err = dns_receive(mem_ctx, conn, &buf);
358
 
        if (!ERR_DNS_IS_OK(err)) goto error;
359
 
 
360
 
        err = dns_unmarshall_request(mem_ctx, buf, resp);
361
 
 
362
 
 error:
363
 
        TALLOC_FREE(buf);
364
 
        return err;
365
 
}
366
 
 
367
 
DNS_ERROR dns_update_transaction(TALLOC_CTX *mem_ctx,
368
 
                                 struct dns_connection *conn,
369
 
                                 struct dns_update_request *up_req,
370
 
                                 struct dns_update_request **up_resp)
371
 
{
372
 
        struct dns_request *resp;
373
 
        DNS_ERROR err;
374
 
 
375
 
        err = dns_transaction(mem_ctx, conn, dns_update2request(up_req),
376
 
                              &resp);
377
 
 
378
 
        if (!ERR_DNS_IS_OK(err)) return err;
379
 
 
380
 
        *up_resp = dns_request2update(resp);
381
 
        return ERROR_DNS_SUCCESS;
382
 
}