rfcnb-io.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2017 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 static int RFCNB_Discard_Rest(struct RFCNB_Con *con, int len);
50 
51 #ifdef NOT_USED
52 void
53 rfcnb_alarm(int sig)
54 {
55 
56  fprintf(stderr, "IO Timed out ...\n");
57 
58 }
59 
60 #endif /* NOT_USED */
61 
62 #ifdef NOT_USED
63 /* Set timeout value and setup signal handling */
64 int
65 RFCNB_Set_Timeout(int seconds)
66 {
67  /* If we are on a Bezerkeley system, use sigvec, else sigaction */
68 
69 #if ORIGINAL_SAMBA_CODE
70 #ifndef SA_RESTART
71  struct sigvec invec, outvec;
72 #else
73  struct sigaction inact, outact;
74 #endif
75 
76  RFCNB_Timeout = seconds;
77 
78  if (RFCNB_Timeout > 0) { /* Set up handler to ignore but not restart */
79 
80 #ifndef SA_RESTART
81  invec.sv_handler = (void (*)()) rfcnb_alarm;
82  invec.sv_mask = 0;
83  invec.sv_flags = SV_INTERRUPT;
84 
85  if (sigvec(SIGALRM, &invec, &outvec) < 0)
86  return (-1);
87 #else /* !SA_RESTART */
88  inact.sa_handler = (void (*)()) rfcnb_alarm;
89 #ifdef Solaris
90  /* Solaris seems to have an array of vectors ... */
91  inact.sa_mask.__sigbits[0] = 0;
92  inact.sa_mask.__sigbits[1] = 0;
93  inact.sa_mask.__sigbits[2] = 0;
94  inact.sa_mask.__sigbits[3] = 0;
95 #else /* !Solaris */
96  inact.sa_mask = (sigset_t) 0;
97 #endif /* Solaris */
98  inact.sa_flags = 0; /* Don't restart */
99 
100  if (sigaction(SIGALRM, &inact, &outact) < 0)
101  return (-1);
102 
103 #endif /* !SA_RESTART */
104 
105  }
106 #else /* !ORIGINAL_SAMBA_CODE ADAPTED SQUID CODE */
107 #if HAVE_SIGACTION
108  struct sigaction inact, outact;
109 #else
110  struct sigvec invec, outvec;
111 #endif
112 
113  RFCNB_Timeout = seconds;
114 
115  if (RFCNB_Timeout > 0) { /* Set up handler to ignore but not restart */
116 
117 #if HAVE_SIGACTION
118  inact.sa_handler = (void (*)()) rfcnb_alarm;
119  sigemptyset(&inact.sa_mask);
120  inact.sa_flags = 0; /* Don't restart */
121 
122  if (sigaction(SIGALRM, &inact, &outact) < 0)
123  return (-1);
124 #else /* !HAVE_SIGACTION */
125  invec.sv_handler = (void (*)()) rfcnb_alarm;
126  invec.sv_mask = 0;
127  invec.sv_flags = SV_INTERRUPT;
128 
129  if (sigvec(SIGALRM, &invec, &outvec) < 0)
130  return (-1);
131 #endif /* !HAVE_SIGACTION */
132  }
133 #endif /* !ORIGINAL_SAMBA_CODE ADAPTED SQUID CODE */
134  return (0);
135 }
136 #endif /* NOT_USED */
137 
138 /* Discard the rest of an incoming packet as we do not have space for it
139  * in the buffer we allocated or were passed ... */
140 
141 int
143 {
144  char temp[100]; /* Read into here */
145  int rest, this_read, bytes_read;
146 
147  /* len is the amount we should read */
148 
149 #ifdef RFCNB_DEBUG
150  fprintf(stderr, "Discard_Rest called to discard: %i\n", len);
151 #endif
152 
153  rest = len;
154 
155  while (rest > 0) {
156 
157  this_read = (rest > sizeof(temp) ? sizeof(temp) : rest);
158 
159  bytes_read = read(con->fd, temp, this_read);
160 
161  if (bytes_read <= 0) { /* Error so return */
162 
163  if (bytes_read < 0)
165  else
167 
168  RFCNB_saved_errno = errno;
169  return (RFCNBE_Bad);
170 
171  }
172  rest = rest - bytes_read;
173 
174  }
175 
176  return (0);
177 
178 }
179 
180 /* Send an RFCNB packet to the connection.
181  *
182  * We just send each of the blocks linked together ...
183  *
184  * If we can, try to send it as one iovec ...
185  *
186  */
187 
188 int
189 RFCNB_Put_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len)
190 {
191  int len_sent, tot_sent, this_len;
192  struct RFCNB_Pkt *pkt_ptr;
193  char *this_data;
194  int i;
195  struct iovec io_list[10]; /* We should never have more */
196  /* If we do, this will blow up ... */
197 
198  /* Try to send the data ... We only send as many bytes as len claims */
199  /* We should try to stuff it into an IOVEC and send as one write */
200 
201  pkt_ptr = pkt;
202  len_sent = tot_sent = 0; /* Nothing sent so far */
203  i = 0;
204 
205  while ((pkt_ptr != NULL) & (i < 10)) { /* Watch that magic number! */
206 
207  this_len = pkt_ptr->len;
208  this_data = pkt_ptr->data;
209  if ((tot_sent + this_len) > len)
210  this_len = len - tot_sent; /* Adjust so we don't send too much */
211 
212  /* Now plug into the iovec ... */
213 
214  io_list[i].iov_len = this_len;
215  io_list[i].iov_base = this_data;
216  i++;
217 
218  tot_sent += this_len;
219 
220  if (tot_sent == len)
221  break; /* Let's not send too much */
222 
223  pkt_ptr = pkt_ptr->next;
224 
225  }
226 
227 #ifdef RFCNB_DEBUG
228  fprintf(stderr, "Frags = %i, tot_sent = %i\n", i, tot_sent);
229 #endif
230 
231  /* Set up an alarm if timeouts are set ... */
232 
233  if (RFCNB_Timeout > 0)
234  alarm(RFCNB_Timeout);
235 
236  if ((len_sent = writev(con->fd, io_list, i)) < 0) { /* An error */
237 
238  con->errn = errno;
239  if (errno == EINTR) /* We were interrupted ... */
241  else
243  RFCNB_saved_errno = errno;
244  return (RFCNBE_Bad);
245 
246  }
247  if (len_sent < tot_sent) { /* Less than we wanted */
248  if (errno == EINTR) /* We were interrupted */
250  else
252  RFCNB_saved_errno = errno;
253  return (RFCNBE_Bad);
254  }
255  if (RFCNB_Timeout > 0)
256  alarm(0); /* Reset that sucker */
257 
258 #ifdef RFCNB_DEBUG
259 
260  fprintf(stderr, "Len sent = %i ...\n", len_sent);
261  RFCNB_Print_Pkt(stderr, "sent", pkt, len_sent); /* Print what send ... */
262 
263 #endif
264 
265  return (len_sent);
266 
267 }
268 
269 /* Read an RFCNB packet off the connection.
270  *
271  * We read the first 4 bytes, that tells us the length, then read the
272  * rest. We should implement a timeout, but we don't just yet
273  *
274  */
275 
276 int
277 RFCNB_Get_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len)
278 {
279  int read_len, pkt_len;
280  char hdr[RFCNB_Pkt_Hdr_Len]; /* Local space for the header */
281  struct RFCNB_Pkt *pkt_frag;
282  int more, this_time, offset, frag_len, this_len;
283  BOOL seen_keep_alive = TRUE;
284 
285  /* Read that header straight into the buffer */
286 
287  if (len < RFCNB_Pkt_Hdr_Len) { /* What a bozo */
288 
289 #ifdef RFCNB_DEBUG
290  fprintf(stderr, "Trying to read less than a packet:");
291  perror("");
292 #endif
294  return (RFCNBE_Bad);
295 
296  }
297  /* We discard keep alives here ... */
298 
299  if (RFCNB_Timeout > 0)
300  alarm(RFCNB_Timeout);
301 
302  while (seen_keep_alive) {
303 
304  if ((read_len = read(con->fd, hdr, sizeof(hdr))) < 0) { /* Problems */
305 #ifdef RFCNB_DEBUG
306  fprintf(stderr, "Reading the packet, we got:");
307  perror("");
308 #endif
309  if (errno == EINTR)
311  else
313  RFCNB_saved_errno = errno;
314  return (RFCNBE_Bad);
315 
316  }
317  /* Now we check out what we got */
318 
319  if (read_len == 0) { /* Connection closed, send back eof? */
320 
321 #ifdef RFCNB_DEBUG
322  fprintf(stderr, "Connection closed reading\n");
323 #endif
324 
325  if (errno == EINTR)
327  else
329  RFCNB_saved_errno = errno;
330  return (RFCNBE_Bad);
331 
332  }
334 
335 #ifdef RFCNB_DEBUG
336  fprintf(stderr, "RFCNB KEEP ALIVE received\n");
337 #endif
338 
339  } else {
340  seen_keep_alive = FALSE;
341  }
342 
343  }
344 
345  /* What if we got less than or equal to a hdr size in bytes? */
346 
347  if (read_len < sizeof(hdr)) { /* We got a small packet */
348 
349  /* Now we need to copy the hdr portion we got into the supplied packet */
350 
351  memcpy(pkt->data, hdr, read_len); /*Copy data */
352 
353 #ifdef RFCNB_DEBUG
354  RFCNB_Print_Pkt(stderr, "rcvd", pkt, read_len);
355 #endif
356 
357  return (read_len);
358 
359  }
360  /* Now, if we got at least a hdr size, alloc space for rest, if we need it */
361 
362  pkt_len = RFCNB_Pkt_Len(hdr);
363 
364 #ifdef RFCNB_DEBUG
365  fprintf(stderr, "Reading Pkt: Length = %i\n", pkt_len);
366 #endif
367 
368  /* Now copy in the hdr */
369 
370  memcpy(pkt->data, hdr, sizeof(hdr));
371 
372  /* Get the rest of the packet ... first figure out how big our buf is? */
373  /* And make sure that we handle the fragments properly ... Sure should */
374  /* use an iovec ... */
375 
376  if (len < pkt_len) /* Only get as much as we have space for */
377  more = len - RFCNB_Pkt_Hdr_Len;
378  else
379  more = pkt_len;
380 
381  this_time = 0;
382 
383  /* We read for each fragment ... */
384 
385  if (pkt->len == read_len) { /* If this frag was exact size */
386  pkt_frag = pkt->next; /* Stick next lot in next frag */
387  offset = 0; /* then we start at 0 in next */
388  } else {
389  pkt_frag = pkt; /* Otherwise use rest of this frag */
390  offset = RFCNB_Pkt_Hdr_Len; /* Otherwise skip the header */
391  }
392 
393  frag_len = (pkt_frag ? pkt_frag->len : 0);
394 
395  if (more <= frag_len) /* If len left to get less than frag space */
396  this_len = more; /* Get the rest ... */
397  else
398  this_len = frag_len - offset;
399 
400  while (more > 0) {
401 
402  if ((this_time = read(con->fd, (pkt_frag->data) + offset, this_len)) <= 0) { /* Problems */
403 
404  if (errno == EINTR) {
405 
407 
408  } else {
409  if (this_time < 0)
411  else
413  }
414 
415  RFCNB_saved_errno = errno;
416  return (RFCNBE_Bad);
417 
418  }
419 #ifdef RFCNB_DEBUG
420  fprintf(stderr, "Frag_Len = %i, this_time = %i, this_len = %i, more = %i\n", frag_len,
421  this_time, this_len, more);
422 #endif
423 
424  read_len = read_len + this_time; /* How much have we read ... */
425 
426  /* Now set up the next part */
427 
428  if (pkt_frag->next == NULL)
429  break; /* That's it here */
430 
431  pkt_frag = pkt_frag->next;
432  this_len = pkt_frag->len;
433  offset = 0;
434 
435  more = more - this_time;
436 
437  }
438 
439 #ifdef RFCNB_DEBUG
440  fprintf(stderr, "Pkt Len = %i, read_len = %i\n", pkt_len, read_len);
441  RFCNB_Print_Pkt(stderr, "rcvd", pkt, read_len + sizeof(hdr));
442 #endif
443 
444  if (read_len < (pkt_len + sizeof(hdr))) { /* Discard the rest */
445 
446  return (RFCNB_Discard_Rest(con, (pkt_len + sizeof(hdr)) - read_len));
447 
448  }
449  if (RFCNB_Timeout > 0)
450  alarm(0); /* Reset that sucker */
451 
452  return (read_len + sizeof(RFCNB_Hdr));
453 }
454 
size_t iov_len
Definition: cmsg.h:83
int RFCNB_Get_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len)
Definition: rfcnb-io.c:277
int errn
Definition: rfcnb-priv.h:82
void * iov_base
Definition: cmsg.h:82
#define RFCNB_SESSION_KEEP_ALIVE
Definition: rfcnb-priv.h:65
#define RFCNB_Pkt_Len(p)
Definition: rfcnb-priv.h:115
int i
Definition: membanger.c:49
static int RFCNB_Discard_Rest(struct RFCNB_Con *con, int len)
Definition: rfcnb-io.c:142
char * data
Definition: rfcnb-common.h:44
char RFCNB_Hdr[4]
Definition: rfcnb-priv.h:90
#define RFCNBE_Timeout
Definition: rfcnb-error.h:62
typedef BOOL(WINAPI *PFChangeServiceConfig2)(SC_HANDLE
#define RFCNBE_Bad
Definition: rfcnb-error.h:42
#define RFCNBE_ConGone
Definition: rfcnb-error.h:52
void RFCNB_Print_Pkt(FILE *fd, char *dirn, struct RFCNB_Pkt *pkt, int len)
Definition: rfcnb-util.c:254
#define TRUE
Definition: std-includes.h:55
int unsigned int const char *desc STUB void int len
Definition: stub_fd.cc:20
int RFCNB_saved_errno
Definition: session.c:36
#define RFCNB_Pkt_Type(p)
Definition: rfcnb-priv.h:122
struct RFCNB_Pkt * next
Definition: rfcnb-common.h:46
int RFCNB_Timeout
Definition: rfcnb-io.c:47
#define FALSE
Definition: std-includes.h:56
#define RFCNB_Pkt_Hdr_Len
Definition: rfcnb-priv.h:97
#define RFCNBE_BadWrite
Definition: rfcnb-error.h:50
#define RFCNBE_BadParam
Definition: rfcnb-error.h:61
#define RFCNBE_BadRead
Definition: rfcnb-error.h:49
int RFCNB_Put_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len)
Definition: rfcnb-io.c:189
#define NULL
Definition: types.h:166
int RFCNB_errno
Definition: session.c:35
Definition: cmsg.h:81

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors