]> git.ipfire.org Git - thirdparty/squid.git/blame - lib/rfcnb/session.c
SourceFormat Enforcement
[thirdparty/squid.git] / lib / rfcnb / session.c
CommitLineData
462566c5 1/*
4ac4a490 2 * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
462566c5
AJ
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
7c16470c
AJ
8
9/* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation
6ca34f6f
HN
10 *
11 * Version 1.0
12 * Session Routines ...
13 *
14 * Copyright (C) Richard Sharpe 1996
6ca34f6f 15 */
7c16470c
AJ
16
17/*
6ca34f6f
HN
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31 */
7c16470c 32
462566c5
AJ
33#include "squid.h"
34
7c16470c
AJ
35int RFCNB_errno = 0;
36int RFCNB_saved_errno = 0;
37#define RFCNB_ERRNO
38
39#include "rfcnb/std-includes.h"
40#include <netinet/tcp.h>
7c16470c 41#include "rfcnb/rfcnb-io.h"
9864722f 42#include "rfcnb/rfcnb-priv.h"
7c16470c 43#include "rfcnb/rfcnb-util.h"
9864722f 44#include "rfcnb/rfcnb.h"
7c16470c
AJ
45
46#if HAVE_STRING_H
47#include <string.h>
48#endif
49
50int RFCNB_Stats[RFCNB_MAX_STATS];
51
6ca34f6f 52RFCNB_Prot_Print_Routine *Prot_Print_Routine = NULL; /* Pointer to protocol print routine */
7c16470c 53
7c16470c 54/* Set up a session with a remote name. We are passed Called_Name as a
6ca34f6f
HN
55 * string which we convert to a NetBIOS name, ie space terminated, up to
56 * 16 characters only if we need to. If Called_Address is not empty, then
57 * we use it to connect to the remote end, but put in Called_Name ... Called
58 * Address can be a DNS based name, or a TCP/IP address ...
59 */
60
61void *
62RFCNB_Call(char *Called_Name, char *Calling_Name, char *Called_Address, int port)
7c16470c
AJ
63{
64 struct RFCNB_Con *con;
65 struct in_addr Dest_IP;
66 int Client;
67 BOOL redirect;
68 struct redirect_addr *redir_addr;
69 char *Service_Address;
70
71 /* Now, we really should look up the port in /etc/services ... */
72
6ca34f6f
HN
73 if (port == 0)
74 port = RFCNB_Default_Port;
7c16470c
AJ
75
76 /* Create a connection structure first */
77
6ca34f6f 78 if ((con = (struct RFCNB_Con *) malloc(sizeof(struct RFCNB_Con))) == NULL) { /* Error in size */
7c16470c
AJ
79
80 RFCNB_errno = RFCNBE_NoSpace;
81 RFCNB_saved_errno = errno;
6ca34f6f 82 return (NULL);
7c16470c
AJ
83
84 }
6ca34f6f
HN
85 con->fd = -0; /* no descriptor yet */
86 con->errn = 0; /* no error yet */
87 con->timeout = 0; /* no timeout */
88 con->redirects = 0;
cdf6c008 89 con->redirect_list = con->last_addr = NULL;
7c16470c
AJ
90
91 /* Resolve that name into an IP address */
92
93 Service_Address = Called_Name;
b9bb9562 94 if (strlen(Called_Address) != 0) { /* If the Called Address = "" */
7c16470c
AJ
95 Service_Address = Called_Address;
96 }
6ca34f6f 97 if ((errno = RFCNB_Name_To_IP(Service_Address, &Dest_IP)) < 0) { /* Error */
7c16470c
AJ
98
99 /* No need to modify RFCNB_errno as it was done by RFCNB_Name_To_IP */
100 free(con);
6ca34f6f 101 return (NULL);
7c16470c
AJ
102
103 }
7c16470c
AJ
104 /* Now connect to the remote end */
105
6ca34f6f 106 redirect = TRUE; /* Fudge this one so we go once through */
7c16470c 107
6ca34f6f 108 while (redirect) { /* Connect and get session info etc */
7c16470c 109
6ca34f6f 110 redirect = FALSE; /* Assume all OK */
7c16470c
AJ
111
112 /* Build the redirect info. First one is first addr called */
113 /* And tack it onto the list of addresses we called */
114
6ca34f6f 115 if ((redir_addr = (struct redirect_addr *) malloc(sizeof(struct redirect_addr))) == NULL) { /* Could not get space */
7c16470c
AJ
116
117 RFCNB_errno = RFCNBE_NoSpace;
118 RFCNB_saved_errno = errno;
119 free(con);
6ca34f6f 120 return (NULL);
7c16470c
AJ
121
122 }
6ca34f6f
HN
123 memcpy((char *) &(redir_addr->ip_addr), (char *) &Dest_IP, sizeof(Dest_IP));
124 redir_addr->port = port;
125 redir_addr->next = NULL;
7c16470c 126
6ca34f6f 127 if (con->redirect_list == NULL) { /* Stick on head */
7c16470c 128
6ca34f6f 129 con->redirect_list = con->last_addr = redir_addr;
7c16470c
AJ
130
131 } else {
132
6ca34f6f
HN
133 con->last_addr->next = redir_addr;
134 con->last_addr = redir_addr;
7c16470c
AJ
135
136 }
137
138 /* Now, make that connection */
139
6ca34f6f 140 if ((Client = RFCNB_IP_Connect(Dest_IP, port)) < 0) { /* Error */
7c16470c
AJ
141
142 /* No need to modify RFCNB_errno as it was done by RFCNB_IP_Connect */
143 free(con);
6ca34f6f 144 return (NULL);
7c16470c
AJ
145
146 }
6ca34f6f 147 con->fd = Client;
7c16470c
AJ
148
149 /* Now send and handle the RFCNB session request */
150 /* If we get a redirect, we will comeback with redirect true
6ca34f6f 151 * and a new IP address in DEST_IP */
7c16470c
AJ
152
153 if ((errno = RFCNB_Session_Req(con,
154 Called_Name,
155 Calling_Name,
156 &redirect, &Dest_IP, &port)) < 0) {
157
158 /* No need to modify RFCNB_errno as it was done by RFCNB_Session.. */
159
6ca34f6f 160 RFCNB_Close(con->fd); /* Close it */
7c16470c 161 free(con);
6ca34f6f 162 return (NULL);
7c16470c
AJ
163
164 }
7c16470c
AJ
165 if (redirect) {
166
167 /* We have to close the connection, and then try again */
168
6ca34f6f 169 (con->redirects)++;
7c16470c 170
6ca34f6f 171 RFCNB_Close(con->fd); /* Close it */
7c16470c
AJ
172
173 }
174 }
175
6ca34f6f 176 return (con);
7c16470c
AJ
177}
178
179/* We send a packet to the other end ... for the moment, we treat the
6ca34f6f
HN
180 * data as a series of pointers to blocks of data ... we should check the
181 * length ... */
182int
183RFCNB_Send(struct RFCNB_Con *Con_Handle, struct RFCNB_Pkt *udata, int Length)
7c16470c
AJ
184{
185 struct RFCNB_Pkt *pkt;
186 char *hdr;
187 int len;
188
189 /* Plug in the header and send the data */
190
191 pkt = RFCNB_Alloc_Pkt(RFCNB_Pkt_Hdr_Len);
192
193 if (pkt == NULL) {
194
195 RFCNB_errno = RFCNBE_NoSpace;
196 RFCNB_saved_errno = errno;
6ca34f6f 197 return (RFCNBE_Bad);
7c16470c
AJ
198
199 }
6ca34f6f 200 pkt->next = udata; /* The user data we want to send */
7c16470c 201
6ca34f6f 202 hdr = pkt->data;
7c16470c
AJ
203
204 /* Following crap is for portability across multiple UNIX machines */
205
6ca34f6f 206 *(hdr + RFCNB_Pkt_Type_Offset) = RFCNB_SESSION_MESSAGE;
7c16470c
AJ
207 RFCNB_Put_Pkt_Len(hdr, Length);
208
209#ifdef RFCNB_DEBUG
210
211 fprintf(stderr, "Sending packet: ");
212
213#endif
214
215 if ((len = RFCNB_Put_Pkt(Con_Handle, pkt, Length + RFCNB_Pkt_Hdr_Len)) < 0) {
216
217 /* No need to change RFCNB_errno as it was done by put_pkt ... */
218
cdf6c008 219 RFCNB_Free_Pkt(pkt);
6ca34f6f 220 return (RFCNBE_Bad); /* Should be able to write that lot ... */
7c16470c
AJ
221
222 }
7c16470c
AJ
223 /* Now we have sent that lot, let's get rid of the RFCNB Header and return */
224
6ca34f6f 225 pkt->next = NULL;
7c16470c
AJ
226
227 RFCNB_Free_Pkt(pkt);
228
6ca34f6f 229 return (len);
7c16470c
AJ
230}
231
232/* We pick up a message from the internet ... We have to worry about
6ca34f6f
HN
233 * non-message packets ... */
234int
235RFCNB_Recv(void *con_Handle, struct RFCNB_Pkt *Data, int Length)
7c16470c
AJ
236{
237 struct RFCNB_Pkt *pkt;
238// struct RFCNB_Hdr *hdr;
239 int ret_len;
240
241 if (con_Handle == NULL) {
242
243 RFCNB_errno = RFCNBE_BadHandle;
244 RFCNB_saved_errno = errno;
6ca34f6f 245 return (RFCNBE_Bad);
7c16470c
AJ
246
247 }
7c16470c
AJ
248 /* Now get a packet from below. We allocate a header first */
249
250 /* Plug in the header and send the data */
251
252 pkt = RFCNB_Alloc_Pkt(RFCNB_Pkt_Hdr_Len);
253
254 if (pkt == NULL) {
255
256 RFCNB_errno = RFCNBE_NoSpace;
257 RFCNB_saved_errno = errno;
6ca34f6f 258 return (RFCNBE_Bad);
7c16470c
AJ
259
260 }
6ca34f6f 261 pkt->next = Data; /* Plug in the data portion */
7c16470c
AJ
262
263 if ((ret_len = RFCNB_Get_Pkt(con_Handle, pkt, Length + RFCNB_Pkt_Hdr_Len)) < 0) {
264
265#ifdef RFCNB_DEBUG
266 fprintf(stderr, "Bad packet return in RFCNB_Recv... \n");
267#endif
cdf6c008 268 RFCNB_Free_Pkt(pkt);
6ca34f6f 269 return (RFCNBE_Bad);
7c16470c
AJ
270
271 }
7c16470c
AJ
272 /* We should check that we go a message and not a keep alive */
273
6ca34f6f 274 pkt->next = NULL;
7c16470c
AJ
275
276 RFCNB_Free_Pkt(pkt);
277
6ca34f6f 278 return (ret_len);
7c16470c
AJ
279}
280
281/* We just disconnect from the other end, as there is nothing in the RFCNB */
282/* protocol that specifies any exchange as far as I can see */
6ca34f6f
HN
283int
284RFCNB_Hangup(struct RFCNB_Con *con_Handle)
7c16470c
AJ
285{
286
287 if (con_Handle != NULL) {
6ca34f6f 288 RFCNB_Close(con_Handle->fd); /* Could this fail? */
7c16470c
AJ
289 free(con_Handle);
290 }
7c16470c 291 return 0;
7c16470c
AJ
292}
293
294/* Set TCP_NODELAY on the socket */
6ca34f6f
HN
295int
296RFCNB_Set_Sock_NoDelay(struct RFCNB_Con *con_Handle, BOOL yn)
7c16470c
AJ
297{
298
6ca34f6f
HN
299 return (setsockopt(con_Handle->fd, IPPROTO_TCP, TCP_NODELAY,
300 (char *) &yn, sizeof(yn)));
7c16470c
AJ
301}
302
303#if NOT_IMPLEMENTED
7c16470c
AJ
304/* Listen for a connection on a port???, when */
305/* the connection comes in, we return with the connection */
6ca34f6f
HN
306void *
307RFCNB_Listen()
7c16470c 308{
7c16470c 309}
6ca34f6f 310
7c16470c
AJ
311#endif
312
313/* Pick up the last error response as a string, hmmm, this routine should */
314/* have been different ... */
6ca34f6f
HN
315void
316RFCNB_Get_Error(char *buffer, int buf_len)
7c16470c
AJ
317{
318
319 if (RFCNB_saved_errno <= 0) {
6ca34f6f 320 snprintf(buffer, (buf_len - 1), "%s", RFCNB_Error_Strings[RFCNB_errno]);
7c16470c 321 } else {
6ca34f6f 322 snprintf(buffer, (buf_len - 1), "%s\n\terrno:%s", RFCNB_Error_Strings[RFCNB_errno],
3c96dd46 323 strerror(RFCNB_saved_errno));
7c16470c 324 }
7c16470c
AJ
325}
326
327/* Pick up the last error response and returns as a code */
6ca34f6f
HN
328int
329RFCNB_Get_Last_Error()
7c16470c 330{
6ca34f6f 331 return (RFCNB_errno);
7c16470c 332}
f53969cc 333