~clint-fewbar/ubuntu/precise/squid3/ignore-sighup-early

« back to all changes in this revision

Viewing changes to helpers/ntlm_auth/smb_lm/smbval/rfcnb-io.c

  • Committer: Bazaar Package Importer
  • Author(s): Luigi Gangitano
  • Date: 2010-05-04 11:15:49 UTC
  • mfrom: (1.3.1 upstream)
  • mto: (20.3.1 squeeze) (21.2.1 sid)
  • mto: This revision was merged to the branch mainline in revision 21.
  • Revision ID: james.westby@ubuntu.com-20100504111549-1apjh2g5sndki4te
Tags: upstream-3.1.3
ImportĀ upstreamĀ versionĀ 3.1.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* UNIX RFCNB (RFC1001/RFC1002) NEtBIOS implementation
 
2
 *
 
3
 * Version 1.0
 
4
 * RFCNB IO Routines ...
 
5
 *
 
6
 * Copyright (C) Richard Sharpe 1996
 
7
 *
 
8
 */
 
9
 
 
10
/*
 
11
 * This program is free software; you can redistribute it and/or modify
 
12
 * it under the terms of the GNU General Public License as published by
 
13
 * the Free Software Foundation; either version 2 of the License, or
 
14
 * (at your option) any later version.
 
15
 *
 
16
 * This program 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
 
19
 * GNU General Public License for more details.
 
20
 *
 
21
 * You should have received a copy of the GNU General Public License
 
22
 * along with this program; if not, write to the Free Software
 
23
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
24
 */
 
25
/* #include <features.h> */
 
26
#include "config.h"
 
27
#include "std-includes.h"
 
28
#include "rfcnb-priv.h"
 
29
#include "rfcnb-util.h"
 
30
#include "rfcnb-io.h"
 
31
#include <sys/uio.h>
 
32
#include <sys/signal.h>
 
33
#include <string.h>
 
34
 
 
35
/* local functions */
 
36
void rfcnb_alarm(int sig);
 
37
int RFCNB_Set_Timeout(int seconds);
 
38
int RFCNB_Discard_Rest(struct RFCNB_Con *con, int len);
 
39
 
 
40
/* local globals */
 
41
 
 
42
int RFCNB_Timeout = 0;          /**< Timeout in seconds ... */
 
43
 
 
44
void
 
45
rfcnb_alarm(int sig)
 
46
{
 
47
    fprintf(stderr, "IO Timed out ...\n");
 
48
}
 
49
 
 
50
/** Set timeout value and setup signal handling */
 
51
int
 
52
RFCNB_Set_Timeout(int seconds)
 
53
{
 
54
    /* If we are on a Bezerkeley system, use sigvec, else sigaction */
 
55
#if HAVE_SIGACTION
 
56
    struct sigaction inact, outact;
 
57
#else
 
58
    struct sigvec invec, outvec;
 
59
#endif
 
60
 
 
61
    RFCNB_Timeout = seconds;
 
62
 
 
63
    if (RFCNB_Timeout > 0) {    /* Set up handler to ignore but not restart */
 
64
 
 
65
#if HAVE_SIGACTION
 
66
        inact.sa_handler = (void (*)()) rfcnb_alarm;
 
67
        sigemptyset(&inact.sa_mask);
 
68
        inact.sa_flags = 0;     /* Don't restart */
 
69
 
 
70
        if (sigaction(SIGALRM, &inact, &outact) < 0)
 
71
            return (-1);
 
72
#else
 
73
        invec.sv_handler = (void (*)()) rfcnb_alarm;
 
74
        invec.sv_mask = 0;
 
75
        invec.sv_flags = SV_INTERRUPT;
 
76
 
 
77
        if (sigvec(SIGALRM, &invec, &outvec) < 0)
 
78
            return (-1);
 
79
#endif
 
80
 
 
81
    }
 
82
    return (0);
 
83
 
 
84
}
 
85
 
 
86
/** Discard the rest of an incoming packet as we do not have space for it
 
87
 * in the buffer we allocated or were passed ...
 
88
 */
 
89
int
 
90
RFCNB_Discard_Rest(struct RFCNB_Con *con, int len)
 
91
{
 
92
    char temp[100];             /* Read into here */
 
93
    int rest, this_read, bytes_read;
 
94
 
 
95
    /* len is the amount we should read */
 
96
 
 
97
#ifdef RFCNB_DEBUG
 
98
    fprintf(stderr, "Discard_Rest called to discard: %i\n", len);
 
99
#endif
 
100
 
 
101
    rest = len;
 
102
 
 
103
    while (rest > 0) {
 
104
 
 
105
        this_read = (rest > sizeof(temp) ? sizeof(temp) : rest);
 
106
 
 
107
        bytes_read = read(con->fd, temp, this_read);
 
108
 
 
109
        if (bytes_read <= 0) {  /* Error so return */
 
110
 
 
111
            if (bytes_read < 0)
 
112
                RFCNB_errno = RFCNBE_BadRead;
 
113
            else
 
114
                RFCNB_errno = RFCNBE_ConGone;
 
115
 
 
116
            RFCNB_saved_errno = errno;
 
117
            return (RFCNBE_Bad);
 
118
 
 
119
        }
 
120
        rest = rest - bytes_read;
 
121
 
 
122
    }
 
123
 
 
124
    return (0);
 
125
 
 
126
}
 
127
 
 
128
 
 
129
/** Send an RFCNB packet to the connection.
 
130
 *
 
131
 * We just send each of the blocks linked together ...
 
132
 *
 
133
 * If we can, try to send it as one iovec ...
 
134
 *
 
135
 */
 
136
int
 
137
RFCNB_Put_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len)
 
138
{
 
139
    int len_sent, tot_sent, this_len;
 
140
    struct RFCNB_Pkt *pkt_ptr;
 
141
    char *this_data;
 
142
    int i;
 
143
    struct iovec io_list[10];   /* We should never have more      */
 
144
    /* If we do, this will blow up ... */
 
145
 
 
146
    /* Try to send the data ... We only send as many bytes as len claims */
 
147
    /* We should try to stuff it into an IOVEC and send as one write     */
 
148
 
 
149
 
 
150
    pkt_ptr = pkt;
 
151
    len_sent = tot_sent = 0;    /* Nothing sent so far */
 
152
    i = 0;
 
153
 
 
154
    while ((pkt_ptr != NULL) & (i < 10)) {      /* Watch that magic number! */
 
155
 
 
156
        this_len = pkt_ptr->len;
 
157
        this_data = pkt_ptr->data;
 
158
        if ((tot_sent + this_len) > len)
 
159
            this_len = len - tot_sent;  /* Adjust so we don't send too much */
 
160
 
 
161
        /* Now plug into the iovec ... */
 
162
 
 
163
        io_list[i].iov_len = this_len;
 
164
        io_list[i].iov_base = this_data;
 
165
        i++;
 
166
 
 
167
        tot_sent += this_len;
 
168
 
 
169
        if (tot_sent == len)
 
170
            break;              /* Let's not send too much */
 
171
 
 
172
        pkt_ptr = pkt_ptr->next;
 
173
 
 
174
    }
 
175
 
 
176
#ifdef RFCNB_DEBUG
 
177
    fprintf(stderr, "Frags = %i, tot_sent = %i\n", i, tot_sent);
 
178
#endif
 
179
 
 
180
    /* Set up an alarm if timeouts are set ... */
 
181
 
 
182
    if (RFCNB_Timeout > 0)
 
183
        alarm(RFCNB_Timeout);
 
184
 
 
185
    if ((len_sent = writev(con->fd, io_list, i)) < 0) {         /* An error */
 
186
 
 
187
        con->rfc_errno = errno;
 
188
        if (errno == EINTR)     /* We were interrupted ... */
 
189
            RFCNB_errno = RFCNBE_Timeout;
 
190
        else
 
191
            RFCNB_errno = RFCNBE_BadWrite;
 
192
        RFCNB_saved_errno = errno;
 
193
        return (RFCNBE_Bad);
 
194
 
 
195
    }
 
196
    if (len_sent < tot_sent) {  /* Less than we wanted */
 
197
        if (errno == EINTR)     /* We were interrupted */
 
198
            RFCNB_errno = RFCNBE_Timeout;
 
199
        else
 
200
            RFCNB_errno = RFCNBE_BadWrite;
 
201
        RFCNB_saved_errno = errno;
 
202
        return (RFCNBE_Bad);
 
203
    }
 
204
    if (RFCNB_Timeout > 0)
 
205
        alarm(0);               /* Reset that sucker */
 
206
 
 
207
#ifdef RFCNB_DEBUG
 
208
 
 
209
    fprintf(stderr, "Len sent = %i ...\n", len_sent);
 
210
    RFCNB_Print_Pkt(stderr, "sent", pkt, len_sent);     /* Print what send ... */
 
211
 
 
212
#endif
 
213
 
 
214
    return (len_sent);
 
215
 
 
216
}
 
217
 
 
218
/** Read an RFCNB packet off the connection.
 
219
 *
 
220
 * We read the first 4 bytes, that tells us the length, then read the
 
221
 * rest. We should implement a timeout, but we don't just yet
 
222
 *
 
223
 */
 
224
int
 
225
RFCNB_Get_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len)
 
226
{
 
227
    int read_len, pkt_len;
 
228
    char hdr[RFCNB_Pkt_Hdr_Len];        /* Local space for the header */
 
229
    struct RFCNB_Pkt *pkt_frag;
 
230
    int more, this_time, offset, frag_len, this_len;
 
231
    BOOL seen_keep_alive = TRUE;
 
232
 
 
233
    /* Read that header straight into the buffer */
 
234
 
 
235
    if (len < RFCNB_Pkt_Hdr_Len) {      /* What a bozo */
 
236
 
 
237
#ifdef RFCNB_DEBUG
 
238
        fprintf(stderr, "Trying to read less than a packet:");
 
239
        perror("");
 
240
#endif
 
241
        RFCNB_errno = RFCNBE_BadParam;
 
242
        return (RFCNBE_Bad);
 
243
 
 
244
    }
 
245
    /* We discard keep alives here ... */
 
246
 
 
247
    if (RFCNB_Timeout > 0)
 
248
        alarm(RFCNB_Timeout);
 
249
 
 
250
    while (seen_keep_alive) {
 
251
 
 
252
        if ((read_len = read(con->fd, hdr, sizeof(hdr))) < 0) {         /* Problems */
 
253
#ifdef RFCNB_DEBUG
 
254
            fprintf(stderr, "Reading the packet, we got:");
 
255
            perror("");
 
256
#endif
 
257
            if (errno == EINTR)
 
258
                RFCNB_errno = RFCNBE_Timeout;
 
259
            else
 
260
                RFCNB_errno = RFCNBE_BadRead;
 
261
            RFCNB_saved_errno = errno;
 
262
            return (RFCNBE_Bad);
 
263
 
 
264
        }
 
265
        /* Now we check out what we got */
 
266
 
 
267
        if (read_len == 0) {    /* Connection closed, send back eof?  */
 
268
 
 
269
#ifdef RFCNB_DEBUG
 
270
            fprintf(stderr, "Connection closed reading\n");
 
271
#endif
 
272
 
 
273
            if (errno == EINTR)
 
274
                RFCNB_errno = RFCNBE_Timeout;
 
275
            else
 
276
                RFCNB_errno = RFCNBE_ConGone;
 
277
            RFCNB_saved_errno = errno;
 
278
            return (RFCNBE_Bad);
 
279
 
 
280
        }
 
281
        if (RFCNB_Pkt_Type(hdr) == RFCNB_SESSION_KEEP_ALIVE) {
 
282
 
 
283
#ifdef RFCNB_DEBUG
 
284
            fprintf(stderr, "RFCNB KEEP ALIVE received\n");
 
285
#endif
 
286
 
 
287
        } else {
 
288
            seen_keep_alive = FALSE;
 
289
        }
 
290
 
 
291
    }
 
292
 
 
293
    /* What if we got less than or equal to a hdr size in bytes? */
 
294
 
 
295
    if (read_len < sizeof(hdr)) {       /* We got a small packet */
 
296
 
 
297
        /* Now we need to copy the hdr portion we got into the supplied packet */
 
298
 
 
299
        memcpy(pkt->data, hdr, read_len);       /*Copy data */
 
300
 
 
301
#ifdef RFCNB_DEBUG
 
302
        RFCNB_Print_Pkt(stderr, "rcvd", pkt, read_len);
 
303
#endif
 
304
 
 
305
        return (read_len);
 
306
 
 
307
    }
 
308
    /* Now, if we got at least a hdr size, alloc space for rest, if we need it */
 
309
 
 
310
    pkt_len = RFCNB_Pkt_Len(hdr);
 
311
 
 
312
#ifdef RFCNB_DEBUG
 
313
    fprintf(stderr, "Reading Pkt: Length = %i\n", pkt_len);
 
314
#endif
 
315
 
 
316
    /* Now copy in the hdr */
 
317
 
 
318
    memcpy(pkt->data, hdr, sizeof(hdr));
 
319
 
 
320
    /* Get the rest of the packet ... first figure out how big our buf is? */
 
321
    /* And make sure that we handle the fragments properly ... Sure should */
 
322
    /* use an iovec ...                                                    */
 
323
 
 
324
    if (len < pkt_len)          /* Only get as much as we have space for */
 
325
        more = len - RFCNB_Pkt_Hdr_Len;
 
326
    else
 
327
        more = pkt_len;
 
328
 
 
329
    this_time = 0;
 
330
 
 
331
    /* We read for each fragment ... */
 
332
 
 
333
    if (pkt->len == read_len) { /* If this frag was exact size */
 
334
        pkt_frag = pkt->next;   /* Stick next lot in next frag */
 
335
        offset = 0;             /* then we start at 0 in next  */
 
336
    } else {
 
337
        pkt_frag = pkt;         /* Otherwise use rest of this frag */
 
338
        offset = RFCNB_Pkt_Hdr_Len;     /* Otherwise skip the header       */
 
339
    }
 
340
 
 
341
    frag_len = pkt_frag->len;
 
342
 
 
343
    if (more <= frag_len)       /* If len left to get less than frag space */
 
344
        this_len = more;        /* Get the rest ...                        */
 
345
    else
 
346
        this_len = frag_len - offset;
 
347
 
 
348
    while (more > 0) {
 
349
 
 
350
        if ((this_time = read(con->fd, (pkt_frag->data) + offset, this_len)) <= 0) {    /* Problems */
 
351
 
 
352
            if (errno == EINTR) {
 
353
 
 
354
                RFCNB_errno = RFCNB_Timeout;
 
355
 
 
356
            } else {
 
357
                if (this_time < 0)
 
358
                    RFCNB_errno = RFCNBE_BadRead;
 
359
                else
 
360
                    RFCNB_errno = RFCNBE_ConGone;
 
361
            }
 
362
 
 
363
            RFCNB_saved_errno = errno;
 
364
            return (RFCNBE_Bad);
 
365
 
 
366
        }
 
367
#ifdef RFCNB_DEBUG
 
368
        fprintf(stderr, "Frag_Len = %i, this_time = %i, this_len = %i, more = %i\n", frag_len,
 
369
                this_time, this_len, more);
 
370
#endif
 
371
 
 
372
        read_len = read_len + this_time;        /* How much have we read ... */
 
373
 
 
374
        /* Now set up the next part */
 
375
 
 
376
        if (pkt_frag->next == NULL)
 
377
            break;              /* That's it here */
 
378
 
 
379
        pkt_frag = pkt_frag->next;
 
380
        this_len = pkt_frag->len;
 
381
        offset = 0;
 
382
 
 
383
        more = more - this_time;
 
384
 
 
385
    }
 
386
 
 
387
#ifdef RFCNB_DEBUG
 
388
    fprintf(stderr, "Pkt Len = %i, read_len = %i\n", pkt_len, read_len);
 
389
    RFCNB_Print_Pkt(stderr, "rcvd", pkt, read_len + sizeof(hdr));
 
390
#endif
 
391
 
 
392
    if (read_len < (pkt_len + sizeof(hdr))) {   /* Discard the rest */
 
393
 
 
394
        return (RFCNB_Discard_Rest(con, (pkt_len + sizeof(hdr)) - read_len));
 
395
 
 
396
    }
 
397
    if (RFCNB_Timeout > 0)
 
398
        alarm(0);               /* Reset that sucker */
 
399
 
 
400
    return (read_len + sizeof(RFCNB_Hdr));
 
401
}