rfcnb-io.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  * RFCNB IO 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 #include "rfcnb/rfcnb-io.h"
35 #include "rfcnb/rfcnb-priv.h"
36 #include "rfcnb/rfcnb-util.h"
37 #include "rfcnb/std-includes.h"
38 
39 #if HAVE_SIGNAL_H
40 #include <signal.h>
41 #endif
42 #if HAVE_STRING_H
43 #include <string.h>
44 #endif
45 #include <sys/uio.h>
46 
47 int RFCNB_Timeout = 0; /* Timeout in seconds ... */
48 
49 /* Discard the rest of an incoming packet as we do not have space for it
50  * in the buffer we allocated or were passed ... */
51 
52 static
53 int
54 RFCNB_Discard_Rest(struct RFCNB_Con *con, int len)
55 {
56  char temp[100]; /* Read into here */
57  int rest, this_read, bytes_read;
58 
59  /* len is the amount we should read */
60 
61 #ifdef RFCNB_DEBUG
62  fprintf(stderr, "Discard_Rest called to discard: %i\n", len);
63 #endif
64 
65  rest = len;
66 
67  while (rest > 0) {
68 
69  this_read = (rest > sizeof(temp) ? sizeof(temp) : rest);
70 
71  bytes_read = read(con->fd, temp, this_read);
72 
73  if (bytes_read <= 0) { /* Error so return */
74 
75  if (bytes_read < 0)
77  else
79 
80  RFCNB_saved_errno = errno;
81  return (RFCNBE_Bad);
82 
83  }
84  rest = rest - bytes_read;
85 
86  }
87 
88  return (0);
89 
90 }
91 
92 /* Send an RFCNB packet to the connection.
93  *
94  * We just send each of the blocks linked together ...
95  *
96  * If we can, try to send it as one iovec ...
97  *
98  */
99 
100 int
101 RFCNB_Put_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len)
102 {
103  int len_sent, tot_sent, this_len;
104  struct RFCNB_Pkt *pkt_ptr;
105  char *this_data;
106  int i;
107  struct iovec io_list[10]; /* We should never have more */
108  /* If we do, this will blow up ... */
109 
110  /* Try to send the data ... We only send as many bytes as len claims */
111  /* We should try to stuff it into an IOVEC and send as one write */
112 
113  pkt_ptr = pkt;
114  len_sent = tot_sent = 0; /* Nothing sent so far */
115  i = 0;
116 
117  while ((pkt_ptr != NULL) & (i < 10)) { /* Watch that magic number! */
118 
119  this_len = pkt_ptr->len;
120  this_data = pkt_ptr->data;
121  if ((tot_sent + this_len) > len)
122  this_len = len - tot_sent; /* Adjust so we don't send too much */
123 
124  /* Now plug into the iovec ... */
125 
126  io_list[i].iov_len = this_len;
127  io_list[i].iov_base = this_data;
128  i++;
129 
130  tot_sent += this_len;
131 
132  if (tot_sent == len)
133  break; /* Let's not send too much */
134 
135  pkt_ptr = pkt_ptr->next;
136 
137  }
138 
139 #ifdef RFCNB_DEBUG
140  fprintf(stderr, "Frags = %i, tot_sent = %i\n", i, tot_sent);
141 #endif
142 
143  /* Set up an alarm if timeouts are set ... */
144 
145  if (RFCNB_Timeout > 0)
146  alarm(RFCNB_Timeout);
147 
148  if ((len_sent = writev(con->fd, io_list, i)) < 0) { /* An error */
149 
150  con->errn = errno;
151  if (errno == EINTR) /* We were interrupted ... */
153  else
155  RFCNB_saved_errno = errno;
156  return (RFCNBE_Bad);
157 
158  }
159  if (len_sent < tot_sent) { /* Less than we wanted */
160  if (errno == EINTR) /* We were interrupted */
162  else
164  RFCNB_saved_errno = errno;
165  return (RFCNBE_Bad);
166  }
167  if (RFCNB_Timeout > 0)
168  alarm(0); /* Reset that sucker */
169 
170 #ifdef RFCNB_DEBUG
171 
172  fprintf(stderr, "Len sent = %i ...\n", len_sent);
173  RFCNB_Print_Pkt(stderr, "sent", pkt, len_sent); /* Print what send ... */
174 
175 #endif
176 
177  return (len_sent);
178 
179 }
180 
181 /* Read an RFCNB packet off the connection.
182  *
183  * We read the first 4 bytes, that tells us the length, then read the
184  * rest. We should implement a timeout, but we don't just yet
185  *
186  */
187 
188 int
189 RFCNB_Get_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len)
190 {
191  int read_len, pkt_len;
192  char hdr[RFCNB_Pkt_Hdr_Len]; /* Local space for the header */
193  struct RFCNB_Pkt *pkt_frag;
194  int more, this_time, offset, frag_len, this_len;
195  BOOL seen_keep_alive = TRUE;
196 
197  /* Read that header straight into the buffer */
198 
199  if (len < RFCNB_Pkt_Hdr_Len) { /* What a bozo */
200 
201 #ifdef RFCNB_DEBUG
202  fprintf(stderr, "Trying to read less than a packet:");
203  perror("");
204 #endif
206  return (RFCNBE_Bad);
207 
208  }
209  /* We discard keep alives here ... */
210 
211  if (RFCNB_Timeout > 0)
212  alarm(RFCNB_Timeout);
213 
214  while (seen_keep_alive) {
215 
216  if ((read_len = read(con->fd, hdr, sizeof(hdr))) < 0) { /* Problems */
217 #ifdef RFCNB_DEBUG
218  fprintf(stderr, "Reading the packet, we got:");
219  perror("");
220 #endif
221  if (errno == EINTR)
223  else
225  RFCNB_saved_errno = errno;
226  return (RFCNBE_Bad);
227 
228  }
229  /* Now we check out what we got */
230 
231  if (read_len == 0) { /* Connection closed, send back eof? */
232 
233 #ifdef RFCNB_DEBUG
234  fprintf(stderr, "Connection closed reading\n");
235 #endif
236 
237  if (errno == EINTR)
239  else
241  RFCNB_saved_errno = errno;
242  return (RFCNBE_Bad);
243 
244  }
246 
247 #ifdef RFCNB_DEBUG
248  fprintf(stderr, "RFCNB KEEP ALIVE received\n");
249 #endif
250 
251  } else {
252  seen_keep_alive = FALSE;
253  }
254 
255  }
256 
257  /* What if we got less than or equal to a hdr size in bytes? */
258 
259  if (read_len < sizeof(hdr)) { /* We got a small packet */
260 
261  /* Now we need to copy the hdr portion we got into the supplied packet */
262 
263  memcpy(pkt->data, hdr, read_len); /*Copy data */
264 
265 #ifdef RFCNB_DEBUG
266  RFCNB_Print_Pkt(stderr, "rcvd", pkt, read_len);
267 #endif
268 
269  return (read_len);
270 
271  }
272  /* Now, if we got at least a hdr size, alloc space for rest, if we need it */
273 
274  pkt_len = RFCNB_Pkt_Len(hdr);
275 
276 #ifdef RFCNB_DEBUG
277  fprintf(stderr, "Reading Pkt: Length = %i\n", pkt_len);
278 #endif
279 
280  /* Now copy in the hdr */
281 
282  memcpy(pkt->data, hdr, sizeof(hdr));
283 
284  /* Get the rest of the packet ... first figure out how big our buf is? */
285  /* And make sure that we handle the fragments properly ... Sure should */
286  /* use an iovec ... */
287 
288  if (len < pkt_len) /* Only get as much as we have space for */
289  more = len - RFCNB_Pkt_Hdr_Len;
290  else
291  more = pkt_len;
292 
293  this_time = 0;
294 
295  /* We read for each fragment ... */
296 
297  if (pkt->len == read_len) { /* If this frag was exact size */
298  pkt_frag = pkt->next; /* Stick next lot in next frag */
299  offset = 0; /* then we start at 0 in next */
300  } else {
301  pkt_frag = pkt; /* Otherwise use rest of this frag */
302  offset = RFCNB_Pkt_Hdr_Len; /* Otherwise skip the header */
303  }
304 
305  frag_len = (pkt_frag ? pkt_frag->len : 0);
306 
307  if (more <= frag_len) /* If len left to get less than frag space */
308  this_len = more; /* Get the rest ... */
309  else
310  this_len = frag_len - offset;
311 
312  while (more > 0) {
313 
314  if ((this_time = read(con->fd, (pkt_frag->data) + offset, this_len)) <= 0) { /* Problems */
315 
316  if (errno == EINTR) {
317 
319 
320  } else {
321  if (this_time < 0)
323  else
325  }
326 
327  RFCNB_saved_errno = errno;
328  return (RFCNBE_Bad);
329 
330  }
331 #ifdef RFCNB_DEBUG
332  fprintf(stderr, "Frag_Len = %i, this_time = %i, this_len = %i, more = %i\n", frag_len,
333  this_time, this_len, more);
334 #endif
335 
336  read_len = read_len + this_time; /* How much have we read ... */
337 
338  /* Now set up the next part */
339 
340  if (pkt_frag->next == NULL)
341  break; /* That's it here */
342 
343  pkt_frag = pkt_frag->next;
344  this_len = pkt_frag->len;
345  offset = 0;
346 
347  more = more - this_time;
348 
349  }
350 
351 #ifdef RFCNB_DEBUG
352  fprintf(stderr, "Pkt Len = %i, read_len = %i\n", pkt_len, read_len);
353  RFCNB_Print_Pkt(stderr, "rcvd", pkt, read_len + sizeof(hdr));
354 #endif
355 
356  if (read_len < (pkt_len + sizeof(hdr))) { /* Discard the rest */
357 
358  return (RFCNB_Discard_Rest(con, (pkt_len + sizeof(hdr)) - read_len));
359 
360  }
361  if (RFCNB_Timeout > 0)
362  alarm(0); /* Reset that sucker */
363 
364  return (read_len + sizeof(RFCNB_Hdr));
365 }
366 
#define RFCNB_Pkt_Type(p)
Definition: rfcnb-priv.h:122
#define RFCNBE_ConGone
Definition: rfcnb-error.h:52
char RFCNB_Hdr[4]
Definition: rfcnb-priv.h:90
void * iov_base
Definition: cmsg.h:82
#define FALSE
Definition: std-includes.h:56
size_t iov_len
Definition: cmsg.h:83
#define RFCNBE_BadRead
Definition: rfcnb-error.h:49
#define RFCNB_Pkt_Len(p)
Definition: rfcnb-priv.h:115
#define RFCNBE_BadWrite
Definition: rfcnb-error.h:50
#define NULL
Definition: types.h:145
#define RFCNB_Pkt_Hdr_Len
Definition: rfcnb-priv.h:97
static int RFCNB_Discard_Rest(struct RFCNB_Con *con, int len)
Definition: rfcnb-io.c:54
void RFCNB_Print_Pkt(FILE *fd, char *dirn, struct RFCNB_Pkt *pkt, int len)
Definition: rfcnb-util.c:254
#define RFCNBE_BadParam
Definition: rfcnb-error.h:61
char * data
Definition: rfcnb-common.h:44
#define RFCNBE_Bad
Definition: rfcnb-error.h:42
#define TRUE
Definition: std-includes.h:55
int errn
Definition: rfcnb-priv.h:82
Definition: cmsg.h:81
int RFCNB_errno
Definition: session.c:35
int RFCNB_Timeout
Definition: rfcnb-io.c:47
int RFCNB_saved_errno
Definition: session.c:36
#define RFCNB_SESSION_KEEP_ALIVE
Definition: rfcnb-priv.h:65
#define RFCNBE_Timeout
Definition: rfcnb-error.h:62
int RFCNB_Put_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len)
Definition: rfcnb-io.c:101
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

 

Introduction

Documentation

Support

Miscellaneous