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