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

« back to all changes in this revision

Viewing changes to helpers/ntlm_auth/SMB/smbval/session.c

  • Committer: Bazaar Package Importer
  • Author(s): Luigi Gangitano
  • Date: 2006-11-11 10:32:06 UTC
  • Revision ID: james.westby@ubuntu.com-20061111103206-f3p0r9g0vq44rp3r
Tags: upstream-3.0.PRE5
ImportĀ upstreamĀ versionĀ 3.0.PRE5

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
 * Session 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
 
 
26
#include <string.h>
 
27
#include <stdlib.h>
 
28
 
 
29
int RFCNB_errno = 0;
 
30
int RFCNB_saved_errno = 0;
 
31
#define RFCNB_ERRNO
 
32
 
 
33
#include "std-includes.h"
 
34
#include <netinet/tcp.h>
 
35
#include "rfcnb-priv.h"
 
36
#include "rfcnb-util.h"
 
37
#include "rfcnb-io.h"
 
38
 
 
39
/* global data structures */
 
40
 
 
41
char *RFCNB_Error_Strings[] =
 
42
{
 
43
 
 
44
    "RFCNBE_OK: Routine completed successfully.",
 
45
    "RFCNBE_NoSpace: No space available for a malloc call.",
 
46
    "RFCNBE_BadName: NetBIOS name could not be translated to IP address.",
 
47
    "RFCNBE_BadRead: Read system call returned an error. Check errno.",
 
48
    "RFCNBE_BadWrite: Write system call returned an error. Check errno.",
 
49
    "RFCNBE_ProtErr: A protocol error has occurred.",
 
50
    "RFCNBE_ConGone: Connection dropped during a read or write system call.",
 
51
    "RFCNBE_BadHandle: Bad connection handle passed.",
 
52
    "RFCNBE_BadSocket: Problems creating socket.",
 
53
    "RFCNBE_ConnectFailed: Connection failed. See errno.",
 
54
    "RFCNBE_CallRejNLOCN: Call rejected. Not listening on called name.",
 
55
    "RFCNBE_CallRejNLFCN: Call rejected. Not listening for called name.",
 
56
    "RFCNBE_CallRejCNNP: Call rejected. Called name not present.",
 
57
    "RFCNBE_CallRejInfRes: Call rejected. Name present, but insufficient resources.",
 
58
    "RFCNBE_CallRejUnSpec: Call rejected. Unspecified error.",
 
59
    "RFCNBE_BadParam: Bad parameters passed to a routine.",
 
60
    "RFCNBE_Timeout: IO Operation timed out ..."
 
61
 
 
62
};
 
63
 
 
64
int RFCNB_Stats[RFCNB_MAX_STATS];
 
65
 
 
66
void (*Prot_Print_Routine) () = NULL;   /* Pointer to print routine */
 
67
 
 
68
/* Set up a session with a remote name. We are passed Called_Name as a
 
69
 * string which we convert to a NetBIOS name, ie space terminated, up to
 
70
 * 16 characters only if we need to. If Called_Address is not empty, then
 
71
 * we use it to connect to the remote end, but put in Called_Name ... Called 
 
72
 * Address can be a DNS based name, or a TCP/IP address ...
 
73
 */
 
74
 
 
75
void *
 
76
RFCNB_Call(char *Called_Name, char *Calling_Name, char *Called_Address,
 
77
    int port)
 
78
{
 
79
    struct RFCNB_Con *con;
 
80
    struct IN_ADDR Dest_IP;
 
81
    int Client;
 
82
    BOOL redirect;
 
83
    struct redirect_addr *redir_addr;
 
84
    char *Service_Address;
 
85
 
 
86
    /* Now, we really should look up the port in /etc/services ... */
 
87
 
 
88
    if (port == 0)
 
89
        port = RFCNB_Default_Port;
 
90
 
 
91
    /* Create a connection structure first */
 
92
 
 
93
    if ((con = (struct RFCNB_Con *) malloc(sizeof(struct RFCNB_Con))) == NULL) {        /* Error in size */
 
94
 
 
95
        RFCNB_errno = RFCNBE_NoSpace;
 
96
        RFCNB_saved_errno = errno;
 
97
        return (NULL);
 
98
 
 
99
    }
 
100
    con->fd = -0;               /* no descriptor yet */
 
101
    con->rfc_errno = 0;         /* no error yet */
 
102
    con->timeout = 0;           /* no timeout   */
 
103
    con->redirects = 0;
 
104
    con->redirect_list = NULL;  /* Fix bug still in version 0.50 */
 
105
 
 
106
    /* Resolve that name into an IP address */
 
107
 
 
108
    Service_Address = Called_Name;
 
109
    if (strcmp(Called_Address, "") != 0) {      /* If the Called Address = "" */
 
110
        Service_Address = Called_Address;
 
111
    }
 
112
    if ((errno = RFCNB_Name_To_IP(Service_Address, &Dest_IP)) < 0) {    /* Error */
 
113
 
 
114
        /* No need to modify RFCNB_errno as it was done by RFCNB_Name_To_IP */
 
115
 
 
116
        return (NULL);
 
117
 
 
118
    }
 
119
    /* Now connect to the remote end */
 
120
 
 
121
    redirect = TRUE;            /* Fudge this one so we go once through */
 
122
 
 
123
    while (redirect) {          /* Connect and get session info etc */
 
124
 
 
125
        redirect = FALSE;       /* Assume all OK */
 
126
 
 
127
        /* Build the redirect info. First one is first addr called */
 
128
        /* And tack it onto the list of addresses we called        */
 
129
 
 
130
        if ((redir_addr = (struct redirect_addr *) malloc(sizeof(struct redirect_addr))) == NULL) {     /* Could not get space */
 
131
 
 
132
            RFCNB_errno = RFCNBE_NoSpace;
 
133
            RFCNB_saved_errno = errno;
 
134
            return (NULL);
 
135
 
 
136
        }
 
137
        memcpy((char *) &(redir_addr->ip_addr), (char *) &Dest_IP, sizeof(Dest_IP));
 
138
        redir_addr->port = port;
 
139
        redir_addr->next = NULL;
 
140
 
 
141
        if (con->redirect_list == NULL) {       /* Stick on head */
 
142
 
 
143
            con->redirect_list = con->last_addr = redir_addr;
 
144
 
 
145
        } else {
 
146
 
 
147
            con->last_addr->next = redir_addr;
 
148
            con->last_addr = redir_addr;
 
149
 
 
150
        }
 
151
 
 
152
        /* Now, make that connection */
 
153
 
 
154
        if ((Client = RFCNB_IP_Connect(Dest_IP, port)) < 0) {   /* Error */
 
155
 
 
156
            /* No need to modify RFCNB_errno as it was done by RFCNB_IP_Connect */
 
157
 
 
158
            return (NULL);
 
159
 
 
160
        }
 
161
        con->fd = Client;
 
162
 
 
163
        /* Now send and handle the RFCNB session request              */
 
164
        /* If we get a redirect, we will comeback with redirect true 
 
165
         * and a new IP address in DEST_IP                            */
 
166
 
 
167
        if ((errno = RFCNB_Session_Req(con,
 
168
                    Called_Name,
 
169
                    Calling_Name,
 
170
                    &redirect, &Dest_IP, &port)) < 0) {
 
171
 
 
172
            /* No need to modify RFCNB_errno as it was done by RFCNB_Session.. */
 
173
 
 
174
            return (NULL);
 
175
 
 
176
        }
 
177
        if (redirect) {
 
178
 
 
179
            /* We have to close the connection, and then try again */
 
180
 
 
181
            (con->redirects)++;
 
182
 
 
183
            RFCNB_Close(con->fd);       /* Close it */
 
184
 
 
185
        }
 
186
    }
 
187
 
 
188
    return (con);
 
189
 
 
190
}
 
191
 
 
192
/* We send a packet to the other end ... for the moment, we treat the 
 
193
 * data as a series of pointers to blocks of data ... we should check the
 
194
 * length ... */
 
195
 
 
196
int
 
197
RFCNB_Send(struct RFCNB_Con *Con_Handle, struct RFCNB_Pkt *udata, int Length)
 
198
{
 
199
    struct RFCNB_Pkt *pkt;
 
200
    char *hdr;
 
201
    int len;
 
202
 
 
203
    /* Plug in the header and send the data */
 
204
 
 
205
    pkt = RFCNB_Alloc_Pkt(RFCNB_Pkt_Hdr_Len);
 
206
 
 
207
    if (pkt == NULL) {
 
208
 
 
209
        RFCNB_errno = RFCNBE_NoSpace;
 
210
        RFCNB_saved_errno = errno;
 
211
        return (RFCNBE_Bad);
 
212
 
 
213
    }
 
214
    pkt->next = udata;          /* The user data we want to send */
 
215
 
 
216
    hdr = pkt->data;
 
217
 
 
218
    /* Following crap is for portability across multiple UNIX machines */
 
219
 
 
220
    *(hdr + RFCNB_Pkt_Type_Offset) = RFCNB_SESSION_MESSAGE;
 
221
    RFCNB_Put_Pkt_Len(hdr, Length);
 
222
 
 
223
#ifdef RFCNB_DEBUG
 
224
 
 
225
    fprintf(stderr, "Sending packet: ");
 
226
 
 
227
#endif
 
228
 
 
229
    if ((len = RFCNB_Put_Pkt(Con_Handle, pkt, Length + RFCNB_Pkt_Hdr_Len)) < 0) {
 
230
 
 
231
        /* No need to change RFCNB_errno as it was done by put_pkt ...     */
 
232
 
 
233
        return (RFCNBE_Bad);    /* Should be able to write that lot ... */
 
234
 
 
235
    }
 
236
    /* Now we have sent that lot, let's get rid of the RFCNB Header and return */
 
237
 
 
238
    pkt->next = NULL;
 
239
 
 
240
    RFCNB_Free_Pkt(pkt);
 
241
 
 
242
    return (len);
 
243
 
 
244
}
 
245
 
 
246
/* We pick up a message from the internet ... We have to worry about 
 
247
 * non-message packets ...                                           */
 
248
 
 
249
int
 
250
RFCNB_Recv(void *con_Handle, struct RFCNB_Pkt *Data, int Length)
 
251
{
 
252
    struct RFCNB_Pkt *pkt;
 
253
    int ret_len;
 
254
 
 
255
    if (con_Handle == NULL) {
 
256
 
 
257
        RFCNB_errno = RFCNBE_BadHandle;
 
258
        RFCNB_saved_errno = errno;
 
259
        return (RFCNBE_Bad);
 
260
 
 
261
    }
 
262
    /* Now get a packet from below. We allocate a header first */
 
263
 
 
264
    /* Plug in the header and send the data */
 
265
 
 
266
    pkt = RFCNB_Alloc_Pkt(RFCNB_Pkt_Hdr_Len);
 
267
 
 
268
    if (pkt == NULL) {
 
269
 
 
270
        RFCNB_errno = RFCNBE_NoSpace;
 
271
        RFCNB_saved_errno = errno;
 
272
        return (RFCNBE_Bad);
 
273
 
 
274
    }
 
275
    pkt->next = Data;           /* Plug in the data portion */
 
276
 
 
277
    if ((ret_len = RFCNB_Get_Pkt(con_Handle, pkt, Length + RFCNB_Pkt_Hdr_Len)) < 0) {
 
278
 
 
279
#ifdef RFCNB_DEBUG
 
280
        fprintf(stderr, "Bad packet return in RFCNB_Recv... \n");
 
281
#endif
 
282
 
 
283
        return (RFCNBE_Bad);
 
284
 
 
285
    }
 
286
    /* We should check that we go a message and not a keep alive */
 
287
 
 
288
    pkt->next = NULL;
 
289
 
 
290
    RFCNB_Free_Pkt(pkt);
 
291
 
 
292
    return (ret_len);
 
293
 
 
294
}
 
295
 
 
296
/* We just disconnect from the other end, as there is nothing in the RFCNB */
 
297
/* protocol that specifies any exchange as far as I can see                */
 
298
 
 
299
int
 
300
RFCNB_Hangup(struct RFCNB_Con *con_Handle)
 
301
{
 
302
 
 
303
    if (con_Handle != NULL) {
 
304
        RFCNB_Close(con_Handle->fd);    /* Could this fail? */
 
305
        free(con_Handle);
 
306
    }
 
307
    return 0;
 
308
 
 
309
 
 
310
}
 
311
 
 
312
/* Set TCP_NODELAY on the socket                                          */
 
313
 
 
314
int
 
315
RFCNB_Set_Sock_NoDelay(struct RFCNB_Con *con_Handle, BOOL yn)
 
316
{
 
317
 
 
318
    return (setsockopt(con_Handle->fd, IPPROTO_TCP, TCP_NODELAY,
 
319
            (char *) &yn, sizeof(yn)));
 
320
 
 
321
}
 
322
 
 
323
 
 
324
/* Listen for a connection on a port???, when                             */
 
325
/* the connection comes in, we return with the connection                 */
 
326
 
 
327
void *
 
328
RFCNB_Listen()
 
329
{
 
330
    fprintf(stderr, "RFCNB_Listen NOT IMPLEMENTED as yet!\n");
 
331
    return NULL;
 
332
}
 
333
 
 
334
/* Pick up the last error response as a string, hmmm, this routine should */
 
335
/* have been different ...                                                */
 
336
 
 
337
void
 
338
RFCNB_Get_Error(char *buffer, int buf_len)
 
339
{
 
340
 
 
341
    if (RFCNB_saved_errno <= 0) {
 
342
        sprintf(buffer, "%s", RFCNB_Error_Strings[RFCNB_errno]);
 
343
    } else {
 
344
        sprintf(buffer, "%s\n\terrno:%s", RFCNB_Error_Strings[RFCNB_errno],
 
345
            strerror(RFCNB_saved_errno));
 
346
    }
 
347
 
 
348
}
 
349
 
 
350
/* Pick up the last error response and returns as a code                 */
 
351
 
 
352
int
 
353
RFCNB_Get_Last_Error()
 
354
{
 
355
 
 
356
    return (RFCNB_errno);
 
357
 
 
358
}
 
359
 
 
360
/* Pick up saved errno as well */
 
361
 
 
362
int
 
363
RFCNB_Get_Last_Errno()
 
364
{
 
365
 
 
366
    return (RFCNB_saved_errno);
 
367
 
 
368
}
 
369
 
 
370
/* Pick up the last error response and return in string ...             */
 
371
 
 
372
void
 
373
RFCNB_Get_Error_Msg(int code, char *msg_buf, int len)
 
374
{
 
375
 
 
376
    strncpy(msg_buf, RFCNB_Error_Strings[abs(code)], len);
 
377
 
 
378
}
 
379
 
 
380
/* Register a higher level protocol print routine */
 
381
 
 
382
void
 
383
RFCNB_Register_Print_Routine(void (*fn) ())
 
384
{
 
385
 
 
386
    Prot_Print_Routine = fn;
 
387
 
 
388
}