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