session.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
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  */
8 
9 /* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation
10  *
11  * Version 1.0
12  * Session Routines ...
13  *
14  * Copyright (C) Richard Sharpe 1996
15  */
16 
17 /*
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  */
32 
33 #include "squid.h"
34 
35 int RFCNB_errno = 0;
37 #define RFCNB_ERRNO
38 
39 #include "rfcnb/std-includes.h"
40 #include <netinet/tcp.h>
41 #include "rfcnb/rfcnb-io.h"
42 #include "rfcnb/rfcnb-priv.h"
43 #include "rfcnb/rfcnb-util.h"
44 #include "rfcnb/rfcnb.h"
45 
46 #if HAVE_STRING_H
47 #include <string.h>
48 #endif
49 
51 
52 RFCNB_Prot_Print_Routine *Prot_Print_Routine = NULL; /* Pointer to protocol print routine */
53 
54 /* Set up a session with a remote name. We are passed Called_Name as a
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 
61 void *
62 RFCNB_Call(char *Called_Name, char *Calling_Name, char *Called_Address, int port)
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 
73  if (port == 0)
75 
76  /* Create a connection structure first */
77 
78  if ((con = (struct RFCNB_Con *) malloc(sizeof(struct RFCNB_Con))) == NULL) { /* Error in size */
79 
81  RFCNB_saved_errno = errno;
82  return (NULL);
83 
84  }
85  con->fd = -0; /* no descriptor yet */
86  con->errn = 0; /* no error yet */
87  con->timeout = 0; /* no timeout */
88  con->redirects = 0;
89  con->redirect_list = con->last_addr = NULL;
90 
91  /* Resolve that name into an IP address */
92 
93  Service_Address = Called_Name;
94  if (strlen(Called_Address) != 0) { /* If the Called Address = "" */
95  Service_Address = Called_Address;
96  }
97  if ((errno = RFCNB_Name_To_IP(Service_Address, &Dest_IP)) < 0) { /* Error */
98 
99  /* No need to modify RFCNB_errno as it was done by RFCNB_Name_To_IP */
100  free(con);
101  return (NULL);
102 
103  }
104  /* Now connect to the remote end */
105 
106  redirect = TRUE; /* Fudge this one so we go once through */
107 
108  while (redirect) { /* Connect and get session info etc */
109 
110  redirect = FALSE; /* Assume all OK */
111 
112  /* Build the redirect info. First one is first addr called */
113  /* And tack it onto the list of addresses we called */
114 
115  if ((redir_addr = (struct redirect_addr *) malloc(sizeof(struct redirect_addr))) == NULL) { /* Could not get space */
116 
118  RFCNB_saved_errno = errno;
119  free(con);
120  return (NULL);
121 
122  }
123  memcpy((char *) &(redir_addr->ip_addr), (char *) &Dest_IP, sizeof(Dest_IP));
124  redir_addr->port = port;
125  redir_addr->next = NULL;
126 
127  if (con->redirect_list == NULL) { /* Stick on head */
128 
129  con->redirect_list = con->last_addr = redir_addr;
130 
131  } else {
132 
133  con->last_addr->next = redir_addr;
134  con->last_addr = redir_addr;
135 
136  }
137 
138  /* Now, make that connection */
139 
140  if ((Client = RFCNB_IP_Connect(Dest_IP, port)) < 0) { /* Error */
141 
142  /* No need to modify RFCNB_errno as it was done by RFCNB_IP_Connect */
143  free(con);
144  return (NULL);
145 
146  }
147  con->fd = Client;
148 
149  /* Now send and handle the RFCNB session request */
150  /* If we get a redirect, we will comeback with redirect true
151  * and a new IP address in DEST_IP */
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 
160  RFCNB_Close(con->fd); /* Close it */
161  free(con);
162  return (NULL);
163 
164  }
165  if (redirect) {
166 
167  /* We have to close the connection, and then try again */
168 
169  (con->redirects)++;
170 
171  RFCNB_Close(con->fd); /* Close it */
172 
173  }
174  }
175 
176  return (con);
177 }
178 
179 /* We send a packet to the other end ... for the moment, we treat the
180  * data as a series of pointers to blocks of data ... we should check the
181  * length ... */
182 int
183 RFCNB_Send(struct RFCNB_Con *Con_Handle, struct RFCNB_Pkt *udata, int Length)
184 {
185  struct RFCNB_Pkt *pkt;
186  char *hdr;
187  int len;
188 
189  /* Plug in the header and send the data */
190 
192 
193  if (pkt == NULL) {
194 
196  RFCNB_saved_errno = errno;
197  return (RFCNBE_Bad);
198 
199  }
200  pkt->next = udata; /* The user data we want to send */
201 
202  hdr = pkt->data;
203 
204  /* Following crap is for portability across multiple UNIX machines */
205 
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 
219  RFCNB_Free_Pkt(pkt);
220  return (RFCNBE_Bad); /* Should be able to write that lot ... */
221 
222  }
223  /* Now we have sent that lot, let's get rid of the RFCNB Header and return */
224 
225  pkt->next = NULL;
226 
227  RFCNB_Free_Pkt(pkt);
228 
229  return (len);
230 }
231 
232 /* We pick up a message from the internet ... We have to worry about
233  * non-message packets ... */
234 int
235 RFCNB_Recv(void *con_Handle, struct RFCNB_Pkt *Data, int Length)
236 {
237  struct RFCNB_Pkt *pkt;
238 // struct RFCNB_Hdr *hdr;
239  int ret_len;
240 
241  if (con_Handle == NULL) {
242 
244  RFCNB_saved_errno = errno;
245  return (RFCNBE_Bad);
246 
247  }
248  /* Now get a packet from below. We allocate a header first */
249 
250  /* Plug in the header and send the data */
251 
253 
254  if (pkt == NULL) {
255 
257  RFCNB_saved_errno = errno;
258  return (RFCNBE_Bad);
259 
260  }
261  pkt->next = Data; /* Plug in the data portion */
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
268  RFCNB_Free_Pkt(pkt);
269  return (RFCNBE_Bad);
270 
271  }
272  /* We should check that we go a message and not a keep alive */
273 
274  pkt->next = NULL;
275 
276  RFCNB_Free_Pkt(pkt);
277 
278  return (ret_len);
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 */
283 int
284 RFCNB_Hangup(struct RFCNB_Con *con_Handle)
285 {
286 
287  if (con_Handle != NULL) {
288  RFCNB_Close(con_Handle->fd); /* Could this fail? */
289  free(con_Handle);
290  }
291  return 0;
292 }
293 
294 /* Set TCP_NODELAY on the socket */
295 int
296 RFCNB_Set_Sock_NoDelay(struct RFCNB_Con *con_Handle, BOOL yn)
297 {
298 
299  return (setsockopt(con_Handle->fd, IPPROTO_TCP, TCP_NODELAY,
300  (char *) &yn, sizeof(yn)));
301 }
302 
303 #if NOT_IMPLEMENTED
304 /* Listen for a connection on a port???, when */
305 /* the connection comes in, we return with the connection */
306 void *
307 RFCNB_Listen()
308 {
309 }
310 
311 #endif
312 
313 /* Pick up the last error response as a string, hmmm, this routine should */
314 /* have been different ... */
315 void
316 RFCNB_Get_Error(char *buffer, int buf_len)
317 {
318 
319  if (RFCNB_saved_errno <= 0) {
320  snprintf(buffer, (buf_len - 1), "%s", RFCNB_Error_Strings[RFCNB_errno]);
321  } else {
322  snprintf(buffer, (buf_len - 1), "%s\n\terrno:%s", RFCNB_Error_Strings[RFCNB_errno],
324  }
325 }
326 
327 /* Pick up the last error response and returns as a code */
328 int
330 {
331  return (RFCNB_errno);
332 }
333 
int RFCNB_Recv(void *con_Handle, struct RFCNB_Pkt *Data, int Length)
Definition: session.c:235
int RFCNB_errno
Definition: session.c:35
int RFCNB_Get_Last_Error()
Definition: session.c:329
Definition: Client.h:29
struct redirect_addr * redirect_list
Definition: rfcnb-priv.h:85
#define FALSE
Definition: std-includes.h:56
int timeout
Definition: rfcnb-priv.h:83
void * RFCNB_Listen(void)
#define RFCNB_SESSION_MESSAGE
Definition: rfcnb-priv.h:60
int RFCNB_Stats[RFCNB_MAX_STATS]
Definition: session.c:50
static int port
Definition: ldap_backend.cc:70
char * strerror(int ern)
Definition: strerror.c:22
#define NULL
Definition: types.h:145
#define RFCNB_Pkt_Hdr_Len
Definition: rfcnb-priv.h:97
int RFCNB_IP_Connect(struct in_addr Dest_IP, int port)
Definition: rfcnb-util.c:384
#define RFCNB_Default_Port
Definition: rfcnb-priv.h:53
#define RFCNB_Pkt_Type_Offset
Definition: rfcnb-priv.h:101
RFCNB_Prot_Print_Routine * Prot_Print_Routine
Definition: session.c:52
int RFCNB_Send(struct RFCNB_Con *Con_Handle, struct RFCNB_Pkt *udata, int Length)
Definition: session.c:183
char * data
Definition: rfcnb-common.h:44
#define RFCNBE_Bad
Definition: rfcnb-error.h:42
void RFCNB_Get_Error(char *buffer, int buf_len)
Definition: session.c:316
redirect_ptr next
Definition: rfcnb-priv.h:75
#define RFCNB_Put_Pkt_Len(p, v)
Definition: rfcnb-priv.h:118
struct redirect_addr * last_addr
Definition: rfcnb-priv.h:86
int RFCNB_Set_Sock_NoDelay(struct RFCNB_Con *con_Handle, BOOL yn)
Definition: session.c:296
#define TRUE
Definition: std-includes.h:55
int errn
Definition: rfcnb-priv.h:82
const char * RFCNB_Error_Strings[]
Definition: rfcnb-util.c:47
#define RFCNBE_BadHandle
Definition: rfcnb-error.h:53
void RFCNB_Prot_Print_Routine(FILE *fd, int dir, struct RFCNB_Pkt *pkt, int header, int payload)
Definition: rfcnb-util.h:61
int RFCNB_Name_To_IP(char *host, struct in_addr *Dest_IP)
Definition: rfcnb-util.c:336
int redirects
Definition: rfcnb-priv.h:84
int RFCNB_Session_Req(struct RFCNB_Con *con, char *Called_Name, char *Calling_Name, BOOL *redirect, struct in_addr *Dest_IP, int *port)
Definition: rfcnb-util.c:419
int RFCNB_saved_errno
Definition: session.c:36
void RFCNB_Free_Pkt(struct RFCNB_Pkt *pkt)
Definition: rfcnb-util.c:231
int RFCNB_Hangup(struct RFCNB_Con *con_Handle)
Definition: session.c:284
#define RFCNB_MAX_STATS
Definition: rfcnb-priv.h:56
void * RFCNB_Call(char *Called_Name, char *Calling_Name, char *Called_Address, int port)
Definition: session.c:62
struct in_addr ip_addr
Definition: rfcnb-priv.h:73
int RFCNB_Put_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len)
Definition: rfcnb-io.c:101
#define RFCNBE_NoSpace
Definition: rfcnb-error.h:47
struct RFCNB_Pkt * next
Definition: rfcnb-common.h:46
#define BOOL
Definition: std-includes.h:38
int RFCNB_Get_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len)
Definition: rfcnb-io.c:189
int RFCNB_Close(int fd)
Definition: rfcnb-util.c:371
struct RFCNB_Pkt * RFCNB_Alloc_Pkt(int n)
Definition: rfcnb-util.c:202

 

Introduction

Documentation

Support

Miscellaneous