]>
git.ipfire.org Git - thirdparty/squid.git/blob - lib/rfcnb/rfcnb-io.c
3 /* UNIX RFCNB (RFC1001/RFC1002) NEtBIOS implementation
6 * RFCNB IO Routines ...
8 * Copyright (C) Richard Sharpe 1996
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.
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.
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.
28 #include "rfcnb/std-includes.h"
29 #include "rfcnb/rfcnb-priv.h"
30 #include "rfcnb/rfcnb-util.h"
31 #include "rfcnb/rfcnb-io.h"
33 #include <sys/signal.h>
39 int RFCNB_Timeout
= 0; /* Timeout in seconds ... */
41 static int RFCNB_Discard_Rest(struct RFCNB_Con
*con
, int len
);
48 fprintf(stderr
, "IO Timed out ...\n");
55 /* Set timeout value and setup signal handling */
57 RFCNB_Set_Timeout(int seconds
)
59 /* If we are on a Bezerkeley system, use sigvec, else sigaction */
61 #if ORIGINAL_SAMBA_CODE
63 struct sigvec invec
, outvec
;
65 struct sigaction inact
, outact
;
68 RFCNB_Timeout
= seconds
;
70 if (RFCNB_Timeout
> 0) { /* Set up handler to ignore but not restart */
73 invec
.sv_handler
= (void (*)()) rfcnb_alarm
;
75 invec
.sv_flags
= SV_INTERRUPT
;
77 if (sigvec(SIGALRM
, &invec
, &outvec
) < 0)
79 #else /* !SA_RESTART */
80 inact
.sa_handler
= (void (*)()) rfcnb_alarm
;
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;
88 inact
.sa_mask
= (sigset_t
) 0;
90 inact
.sa_flags
= 0; /* Don't restart */
92 if (sigaction(SIGALRM
, &inact
, &outact
) < 0)
95 #endif /* !SA_RESTART */
98 #else /* !ORIGINAL_SAMBA_CODE ADAPTED SQUID CODE */
100 struct sigaction inact
, outact
;
102 struct sigvec invec
, outvec
;
105 RFCNB_Timeout
= seconds
;
107 if (RFCNB_Timeout
> 0) { /* Set up handler to ignore but not restart */
110 inact
.sa_handler
= (void (*)()) rfcnb_alarm
;
111 sigemptyset(&inact
.sa_mask
);
112 inact
.sa_flags
= 0; /* Don't restart */
114 if (sigaction(SIGALRM
, &inact
, &outact
) < 0)
116 #else /* !HAVE_SIGACTION */
117 invec
.sv_handler
= (void (*)()) rfcnb_alarm
;
119 invec
.sv_flags
= SV_INTERRUPT
;
121 if (sigvec(SIGALRM
, &invec
, &outvec
) < 0)
123 #endif /* !HAVE_SIGACTION */
125 #endif /* !ORIGINAL_SAMBA_CODE ADAPTED SQUID CODE */
128 #endif /* NOT_USED */
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 ... */
134 RFCNB_Discard_Rest(struct RFCNB_Con
*con
, int len
)
136 char temp
[100]; /* Read into here */
137 int rest
, this_read
, bytes_read
;
139 /* len is the amount we should read */
142 fprintf(stderr
, "Discard_Rest called to discard: %i\n", len
);
149 this_read
= (rest
> sizeof(temp
) ? sizeof(temp
) : rest
);
151 bytes_read
= read(con
->fd
, temp
, this_read
);
153 if (bytes_read
<= 0) { /* Error so return */
156 RFCNB_errno
= RFCNBE_BadRead
;
158 RFCNB_errno
= RFCNBE_ConGone
;
160 RFCNB_saved_errno
= errno
;
164 rest
= rest
- bytes_read
;
173 /* Send an RFCNB packet to the connection.
175 * We just send each of the blocks linked together ...
177 * If we can, try to send it as one iovec ...
182 RFCNB_Put_Pkt(struct RFCNB_Con
*con
, struct RFCNB_Pkt
*pkt
, int len
)
184 int len_sent
, tot_sent
, this_len
;
185 struct RFCNB_Pkt
*pkt_ptr
;
188 struct iovec io_list
[10]; /* We should never have more */
189 /* If we do, this will blow up ... */
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 */
196 len_sent
= tot_sent
= 0; /* Nothing sent so far */
199 while ((pkt_ptr
!= NULL
) & (i
< 10)) { /* Watch that magic number! */
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 */
206 /* Now plug into the iovec ... */
208 io_list
[i
].iov_len
= this_len
;
209 io_list
[i
].iov_base
= this_data
;
212 tot_sent
+= this_len
;
215 break; /* Let's not send too much */
217 pkt_ptr
= pkt_ptr
->next
;
222 fprintf(stderr
, "Frags = %i, tot_sent = %i\n", i
, tot_sent
);
225 /* Set up an alarm if timeouts are set ... */
227 if (RFCNB_Timeout
> 0)
228 alarm(RFCNB_Timeout
);
230 if ((len_sent
= writev(con
->fd
, io_list
, i
)) < 0) { /* An error */
233 if (errno
== EINTR
) /* We were interrupted ... */
234 RFCNB_errno
= RFCNBE_Timeout
;
236 RFCNB_errno
= RFCNBE_BadWrite
;
237 RFCNB_saved_errno
= errno
;
241 if (len_sent
< tot_sent
) { /* Less than we wanted */
242 if (errno
== EINTR
) /* We were interrupted */
243 RFCNB_errno
= RFCNBE_Timeout
;
245 RFCNB_errno
= RFCNBE_BadWrite
;
246 RFCNB_saved_errno
= errno
;
249 if (RFCNB_Timeout
> 0)
250 alarm(0); /* Reset that sucker */
254 fprintf(stderr
, "Len sent = %i ...\n", len_sent
);
255 RFCNB_Print_Pkt(stderr
, "sent", pkt
, len_sent
); /* Print what send ... */
263 /* Read an RFCNB packet off the connection.
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
272 RFCNB_Get_Pkt(struct RFCNB_Con
*con
, struct RFCNB_Pkt
*pkt
, int len
)
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
;
280 /* Read that header straight into the buffer */
282 if (len
< RFCNB_Pkt_Hdr_Len
) { /* What a bozo */
285 fprintf(stderr
, "Trying to read less than a packet:");
288 RFCNB_errno
= RFCNBE_BadParam
;
292 /* We discard keep alives here ... */
294 if (RFCNB_Timeout
> 0)
295 alarm(RFCNB_Timeout
);
297 while (seen_keep_alive
) {
299 if ((read_len
= read(con
->fd
, hdr
, sizeof(hdr
))) < 0) { /* Problems */
301 fprintf(stderr
, "Reading the packet, we got:");
305 RFCNB_errno
= RFCNBE_Timeout
;
307 RFCNB_errno
= RFCNBE_BadRead
;
308 RFCNB_saved_errno
= errno
;
312 /* Now we check out what we got */
314 if (read_len
== 0) { /* Connection closed, send back eof? */
317 fprintf(stderr
, "Connection closed reading\n");
321 RFCNB_errno
= RFCNBE_Timeout
;
323 RFCNB_errno
= RFCNBE_ConGone
;
324 RFCNB_saved_errno
= errno
;
328 if (RFCNB_Pkt_Type(hdr
) == RFCNB_SESSION_KEEP_ALIVE
) {
331 fprintf(stderr
, "RFCNB KEEP ALIVE received\n");
335 seen_keep_alive
= FALSE
;
340 /* What if we got less than or equal to a hdr size in bytes? */
342 if (read_len
< sizeof(hdr
)) { /* We got a small packet */
344 /* Now we need to copy the hdr portion we got into the supplied packet */
346 memcpy(pkt
->data
, hdr
, read_len
); /*Copy data */
349 RFCNB_Print_Pkt(stderr
, "rcvd", pkt
, read_len
);
355 /* Now, if we got at least a hdr size, alloc space for rest, if we need it */
357 pkt_len
= RFCNB_Pkt_Len(hdr
);
360 fprintf(stderr
, "Reading Pkt: Length = %i\n", pkt_len
);
363 /* Now copy in the hdr */
365 memcpy(pkt
->data
, hdr
, sizeof(hdr
));
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 ... */
371 if (len
< pkt_len
) /* Only get as much as we have space for */
372 more
= len
- RFCNB_Pkt_Hdr_Len
;
378 /* We read for each fragment ... */
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 */
384 pkt_frag
= pkt
; /* Otherwise use rest of this frag */
385 offset
= RFCNB_Pkt_Hdr_Len
; /* Otherwise skip the header */
388 frag_len
= pkt_frag
->len
;
390 if (more
<= frag_len
) /* If len left to get less than frag space */
391 this_len
= more
; /* Get the rest ... */
393 this_len
= frag_len
- offset
;
397 if ((this_time
= read(con
->fd
, (pkt_frag
->data
) + offset
, this_len
)) <= 0) { /* Problems */
399 if (errno
== EINTR
) {
401 RFCNB_errno
= RFCNB_Timeout
;
405 RFCNB_errno
= RFCNBE_BadRead
;
407 RFCNB_errno
= RFCNBE_ConGone
;
410 RFCNB_saved_errno
= errno
;
415 fprintf(stderr
, "Frag_Len = %i, this_time = %i, this_len = %i, more = %i\n", frag_len
,
416 this_time
, this_len
, more
);
419 read_len
= read_len
+ this_time
; /* How much have we read ... */
421 /* Now set up the next part */
423 if (pkt_frag
->next
== NULL
)
424 break; /* That's it here */
426 pkt_frag
= pkt_frag
->next
;
427 this_len
= pkt_frag
->len
;
430 more
= more
- this_time
;
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
));
439 if (read_len
< (pkt_len
+ sizeof(hdr
))) { /* Discard the rest */
441 return (RFCNB_Discard_Rest(con
, (pkt_len
+ sizeof(hdr
)) - read_len
));
444 if (RFCNB_Timeout
> 0)
445 alarm(0); /* Reset that sucker */
447 return (read_len
+ sizeof(RFCNB_Hdr
));