~ubuntu-branches/ubuntu/vivid/samba/vivid

« back to all changes in this revision

Viewing changes to lib/addns/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 "replace.h"
 
26
#include "dns.h"
 
27
#include <sys/time.h>
 
28
#include <unistd.h>
 
29
#include "system/select.h"
 
30
 
 
31
static int destroy_dns_connection(struct dns_connection *conn)
 
32
{
 
33
        return close(conn->s);
 
34
}
 
35
 
 
36
/********************************************************************
 
37
********************************************************************/
 
38
 
 
39
static DNS_ERROR dns_tcp_open( const char *nameserver,
 
40
                               TALLOC_CTX *mem_ctx,
 
41
                               struct dns_connection **result )
 
42
{
 
43
        uint32_t ulAddress;
 
44
        struct hostent *pHost;
 
45
        struct sockaddr_in s_in;
 
46
        struct dns_connection *conn;
 
47
        int res;
 
48
 
 
49
        if (!(conn = talloc(mem_ctx, struct dns_connection))) {
 
50
                return ERROR_DNS_NO_MEMORY;
 
51
        }
 
52
 
 
53
        if ( (ulAddress = inet_addr( nameserver )) == INADDR_NONE ) {
 
54
                if ( (pHost = gethostbyname( nameserver )) == NULL ) {
 
55
                        TALLOC_FREE(conn);
 
56
                        return ERROR_DNS_INVALID_NAME_SERVER;
 
57
                }
 
58
                memcpy( &ulAddress, pHost->h_addr, pHost->h_length );
 
59
        }
 
60
 
 
61
        conn->s = socket( PF_INET, SOCK_STREAM, 0 );
 
62
        if (conn->s == -1) {
 
63
                TALLOC_FREE(conn);
 
64
                return ERROR_DNS_CONNECTION_FAILED;
 
65
        }
 
66
 
 
67
        talloc_set_destructor(conn, destroy_dns_connection);
 
68
 
 
69
        s_in.sin_family = AF_INET;
 
70
        s_in.sin_addr.s_addr = ulAddress;
 
71
        s_in.sin_port = htons( DNS_TCP_PORT );
 
72
 
 
73
        res = connect(conn->s, (struct sockaddr*)&s_in, sizeof( s_in ));
 
74
        if (res == -1) {
 
75
                TALLOC_FREE(conn);
 
76
                return ERROR_DNS_CONNECTION_FAILED;
 
77
        }
 
78
 
 
79
        conn->hType = DNS_TCP;
 
80
 
 
81
        *result = conn;
 
82
        return ERROR_DNS_SUCCESS;
 
83
}
 
84
 
 
85
/********************************************************************
 
86
********************************************************************/
 
87
 
 
88
static DNS_ERROR dns_udp_open( const char *nameserver,
 
89
                               TALLOC_CTX *mem_ctx,
 
90
                               struct dns_connection **result )
 
91
{
 
92
        unsigned long ulAddress;
 
93
        struct hostent *pHost;
 
94
        struct sockaddr_in RecvAddr;
 
95
        struct dns_connection *conn;
 
96
 
 
97
        if (!(conn = talloc(NULL, struct dns_connection))) {
 
98
                return ERROR_DNS_NO_MEMORY;
 
99
        }
 
100
 
 
101
        if ( (ulAddress = inet_addr( nameserver )) == INADDR_NONE ) {
 
102
                if ( (pHost = gethostbyname( nameserver )) == NULL ) {
 
103
                        TALLOC_FREE(conn);
 
104
                        return ERROR_DNS_INVALID_NAME_SERVER;
 
105
                }
 
106
                memcpy( &ulAddress, pHost->h_addr, pHost->h_length );
 
107
        }
 
108
 
 
109
        /* Create a socket for sending data */
 
110
 
 
111
        conn->s = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
 
112
        if (conn->s == -1) {
 
113
                TALLOC_FREE(conn);
 
114
                return ERROR_DNS_CONNECTION_FAILED;
 
115
        }
 
116
 
 
117
        talloc_set_destructor(conn, destroy_dns_connection);
 
118
 
 
119
        /* Set up the RecvAddr structure with the IP address of
 
120
           the receiver (in this example case "123.456.789.1")
 
121
           and the specified port number. */
 
122
 
 
123
        ZERO_STRUCT(RecvAddr);
 
124
        RecvAddr.sin_family = AF_INET;
 
125
        RecvAddr.sin_port = htons( DNS_UDP_PORT );
 
126
        RecvAddr.sin_addr.s_addr = ulAddress;
 
127
 
 
128
        conn->hType = DNS_UDP;
 
129
        memcpy( &conn->RecvAddr, &RecvAddr, sizeof( struct sockaddr_in ) );
 
130
 
 
131
        *result = conn;
 
132
        return ERROR_DNS_SUCCESS;
 
133
}
 
134
 
 
135
/********************************************************************
 
136
********************************************************************/
 
137
 
 
138
DNS_ERROR dns_open_connection( const char *nameserver, int32 dwType,
 
139
                    TALLOC_CTX *mem_ctx,
 
140
                    struct dns_connection **conn )
 
141
{
 
142
        switch ( dwType ) {
 
143
        case DNS_TCP:
 
144
                return dns_tcp_open( nameserver, mem_ctx, conn );
 
145
        case DNS_UDP:
 
146
                return dns_udp_open( nameserver, mem_ctx, conn );
 
147
        }
 
148
 
 
149
        return ERROR_DNS_INVALID_PARAMETER;
 
150
}
 
151
 
 
152
static DNS_ERROR write_all(int fd, uint8 *data, size_t len)
 
153
{
 
154
        size_t total = 0;
 
155
 
 
156
        while (total < len) {
 
157
 
 
158
                ssize_t ret = write(fd, data + total, len - total);
 
159
 
 
160
                if (ret <= 0) {
 
161
                        /*
 
162
                         * EOF or error
 
163
                         */
 
164
                        return ERROR_DNS_SOCKET_ERROR;
 
165
                }
 
166
 
 
167
                total += ret;
 
168
        }
 
169
 
 
170
        return ERROR_DNS_SUCCESS;
 
171
}
 
172
 
 
173
static DNS_ERROR dns_send_tcp(struct dns_connection *conn,
 
174
                              const struct dns_buffer *buf)
 
175
{
 
176
        uint16 len = htons(buf->offset);
 
177
        DNS_ERROR err;
 
178
 
 
179
        err = write_all(conn->s, (uint8 *)&len, sizeof(len));
 
180
        if (!ERR_DNS_IS_OK(err)) return err;
 
181
 
 
182
        return write_all(conn->s, buf->data, buf->offset);
 
183
}
 
184
 
 
185
static DNS_ERROR dns_send_udp(struct dns_connection *conn,
 
186
                              const struct dns_buffer *buf)
 
187
{
 
188
        ssize_t ret;
 
189
 
 
190
        ret = sendto(conn->s, buf->data, buf->offset, 0,
 
191
                     (struct sockaddr *)&conn->RecvAddr,
 
192
                     sizeof(conn->RecvAddr));
 
193
 
 
194
        if (ret != buf->offset) {
 
195
                return ERROR_DNS_SOCKET_ERROR;
 
196
        }
 
197
 
 
198
        return ERROR_DNS_SUCCESS;
 
199
}
 
200
 
 
201
DNS_ERROR dns_send(struct dns_connection *conn, const struct dns_buffer *buf)
 
202
{
 
203
        if (conn->hType == DNS_TCP) {
 
204
                return dns_send_tcp(conn, buf);
 
205
        }
 
206
 
 
207
        if (conn->hType == DNS_UDP) {
 
208
                return dns_send_udp(conn, buf);
 
209
        }
 
210
 
 
211
        return ERROR_DNS_INVALID_PARAMETER;
 
212
}
 
213
 
 
214
static DNS_ERROR read_all(int fd, uint8 *data, size_t len)
 
215
{
 
216
        size_t total = 0;
 
217
 
 
218
        while (total < len) {
 
219
                struct pollfd pfd;
 
220
                ssize_t ret;
 
221
                int fd_ready;
 
222
 
 
223
                ZERO_STRUCT(pfd);
 
224
                pfd.fd = fd;
 
225
                pfd.events = POLLIN|POLLHUP;
 
226
 
 
227
                fd_ready = poll(&pfd, 1, 10000);
 
228
                if ( fd_ready == 0 ) {
 
229
                        /* read timeout */
 
230
                        return ERROR_DNS_SOCKET_ERROR;
 
231
                }
 
232
 
 
233
                ret = read(fd, data + total, len - total);
 
234
                if (ret <= 0) {
 
235
                        /* EOF or error */
 
236
                        return ERROR_DNS_SOCKET_ERROR;
 
237
                }
 
238
 
 
239
                total += ret;
 
240
        }
 
241
 
 
242
        return ERROR_DNS_SUCCESS;
 
243
}
 
244
 
 
245
static DNS_ERROR dns_receive_tcp(TALLOC_CTX *mem_ctx,
 
246
                                 struct dns_connection *conn,
 
247
                                 struct dns_buffer **presult)
 
248
{
 
249
        struct dns_buffer *buf;
 
250
        DNS_ERROR err;
 
251
        uint16 len;
 
252
 
 
253
        if (!(buf = TALLOC_ZERO_P(mem_ctx, struct dns_buffer))) {
 
254
                return ERROR_DNS_NO_MEMORY;
 
255
        }
 
256
 
 
257
        err = read_all(conn->s, (uint8 *)&len, sizeof(len));
 
258
        if (!ERR_DNS_IS_OK(err)) {
 
259
                return err;
 
260
        }
 
261
 
 
262
        buf->size = ntohs(len);
 
263
 
 
264
        if (buf->size) {
 
265
                if (!(buf->data = TALLOC_ARRAY(buf, uint8, buf->size))) {
 
266
                        TALLOC_FREE(buf);
 
267
                        return ERROR_DNS_NO_MEMORY;
 
268
                }
 
269
        } else {
 
270
                buf->data = NULL;
 
271
        }
 
272
 
 
273
        err = read_all(conn->s, buf->data, buf->size);
 
274
        if (!ERR_DNS_IS_OK(err)) {
 
275
                TALLOC_FREE(buf);
 
276
                return err;
 
277
        }
 
278
 
 
279
        *presult = buf;
 
280
        return ERROR_DNS_SUCCESS;
 
281
}
 
282
 
 
283
static DNS_ERROR dns_receive_udp(TALLOC_CTX *mem_ctx,
 
284
                                 struct dns_connection *conn,
 
285
                                 struct dns_buffer **presult)
 
286
{
 
287
        struct dns_buffer *buf;
 
288
        ssize_t received;
 
289
 
 
290
        if (!(buf = TALLOC_ZERO_P(mem_ctx, struct dns_buffer))) {
 
291
                return ERROR_DNS_NO_MEMORY;
 
292
        }
 
293
 
 
294
        /*
 
295
         * UDP based DNS can only be 512 bytes
 
296
         */
 
297
 
 
298
        if (!(buf->data = TALLOC_ARRAY(buf, uint8, 512))) {
 
299
                TALLOC_FREE(buf);
 
300
                return ERROR_DNS_NO_MEMORY;
 
301
        }
 
302
 
 
303
        received = recv(conn->s, (void *)buf->data, 512, 0);
 
304
 
 
305
        if (received == -1) {
 
306
                TALLOC_FREE(buf);
 
307
                return ERROR_DNS_SOCKET_ERROR;
 
308
        }
 
309
 
 
310
        if (received > 512) {
 
311
                TALLOC_FREE(buf);
 
312
                return ERROR_DNS_BAD_RESPONSE;
 
313
        }
 
314
 
 
315
        buf->size = received;
 
316
        buf->offset = 0;
 
317
 
 
318
        *presult = buf;
 
319
        return ERROR_DNS_SUCCESS;
 
320
}
 
321
 
 
322
DNS_ERROR dns_receive(TALLOC_CTX *mem_ctx, struct dns_connection *conn,
 
323
                      struct dns_buffer **presult)
 
324
{
 
325
        if (conn->hType == DNS_TCP) {
 
326
                return dns_receive_tcp(mem_ctx, conn, presult);
 
327
        }
 
328
 
 
329
        if (conn->hType == DNS_UDP) {
 
330
                return dns_receive_udp(mem_ctx, conn, presult);
 
331
        }
 
332
 
 
333
        return ERROR_DNS_INVALID_PARAMETER;
 
334
}
 
335
 
 
336
DNS_ERROR dns_transaction(TALLOC_CTX *mem_ctx, struct dns_connection *conn,
 
337
                          const struct dns_request *req,
 
338
                          struct dns_request **resp)
 
339
{
 
340
        struct dns_buffer *buf = NULL;
 
341
        DNS_ERROR err;
 
342
 
 
343
        err = dns_marshall_request(conn, req, &buf);
 
344
        if (!ERR_DNS_IS_OK(err)) goto error;
 
345
 
 
346
        err = dns_send(conn, buf);
 
347
        if (!ERR_DNS_IS_OK(err)) goto error;
 
348
        TALLOC_FREE(buf);
 
349
 
 
350
        err = dns_receive(mem_ctx, conn, &buf);
 
351
        if (!ERR_DNS_IS_OK(err)) goto error;
 
352
 
 
353
        err = dns_unmarshall_request(mem_ctx, buf, resp);
 
354
 
 
355
 error:
 
356
        TALLOC_FREE(buf);
 
357
        return err;
 
358
}
 
359
 
 
360
DNS_ERROR dns_update_transaction(TALLOC_CTX *mem_ctx,
 
361
                                 struct dns_connection *conn,
 
362
                                 struct dns_update_request *up_req,
 
363
                                 struct dns_update_request **up_resp)
 
364
{
 
365
        struct dns_request *resp;
 
366
        DNS_ERROR err;
 
367
 
 
368
        err = dns_transaction(mem_ctx, conn, dns_update2request(up_req),
 
369
                              &resp);
 
370
 
 
371
        if (!ERR_DNS_IS_OK(err)) return err;
 
372
 
 
373
        *up_resp = dns_request2update(resp);
 
374
        return ERROR_DNS_SUCCESS;
 
375
}