]>
git.ipfire.org Git - thirdparty/squid.git/blob - lib/rfcnb/rfcnb-io.c
3 /* UNIX RFCNB (RFC1001/RFC1002) NEtBIOS implementation
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 int RFCNB_Discard_Rest(struct RFCNB_Con
*con
, int len
);
44 void rfcnb_alarm(int sig
)
48 fprintf(stderr
, "IO Timed out ...\n");
52 /* Set timeout value and setup signal handling */
54 int RFCNB_Set_Timeout(int seconds
)
57 /* If we are on a Bezerkeley system, use sigvec, else sigaction */
59 #if ORIGINAL_SAMBA_CODE
61 struct sigvec invec
, outvec
;
63 struct sigaction inact
, outact
;
66 RFCNB_Timeout
= seconds
;
68 if (RFCNB_Timeout
> 0) { /* Set up handler to ignore but not restart */
71 invec
.sv_handler
= (void (*)())rfcnb_alarm
;
73 invec
.sv_flags
= SV_INTERRUPT
;
75 if (sigvec(SIGALRM
, &invec
, &outvec
) < 0)
78 inact
.sa_handler
= (void (*)())rfcnb_alarm
;
80 /* Solaris seems to have an array of vectors ... */
81 inact
.sa_mask
.__sigbits
[0] = 0;
82 inact
.sa_mask
.__sigbits
[1] = 0;
83 inact
.sa_mask
.__sigbits
[2] = 0;
84 inact
.sa_mask
.__sigbits
[3] = 0;
86 inact
.sa_mask
= (sigset_t
)0;
88 inact
.sa_flags
= 0; /* Don't restart */
90 if (sigaction(SIGALRM
, &inact
, &outact
) < 0)
97 #else /* ADAPTED SQUID CODE */
99 struct sigaction inact
, outact
;
101 struct sigvec invec
, outvec
;
104 RFCNB_Timeout
= seconds
;
106 if (RFCNB_Timeout
> 0) { /* Set up handler to ignore but not restart */
109 inact
.sa_handler
= (void (*)()) rfcnb_alarm
;
110 sigemptyset(&inact
.sa_mask
);
111 inact
.sa_flags
= 0; /* Don't restart */
113 if (sigaction(SIGALRM
, &inact
, &outact
) < 0)
116 invec
.sv_handler
= (void (*)()) rfcnb_alarm
;
118 invec
.sv_flags
= SV_INTERRUPT
;
120 if (sigvec(SIGALRM
, &invec
, &outvec
) < 0)
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 ... */
133 int 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
;
165 rest
= rest
- bytes_read
;
174 /* Send an RFCNB packet to the connection.
176 We just send each of the blocks linked together ...
178 If we can, try to send it as one iovec ...
182 int RFCNB_Put_Pkt(struct RFCNB_Con
*con
, struct RFCNB_Pkt
*pkt
, int len
)
185 int len_sent
, tot_sent
, this_len
;
186 struct RFCNB_Pkt
*pkt_ptr
;
189 struct iovec io_list
[10]; /* We should never have more */
190 /* If we do, this will blow up ...*/
192 /* Try to send the data ... We only send as many bytes as len claims */
193 /* We should try to stuff it into an IOVEC and send as one write */
197 len_sent
= tot_sent
= 0; /* Nothing sent so far */
200 while ((pkt_ptr
!= NULL
) & (i
< 10)) { /* Watch that magic number! */
202 this_len
= pkt_ptr
-> len
;
203 this_data
= pkt_ptr
-> data
;
204 if ((tot_sent
+ this_len
) > len
)
205 this_len
= len
- tot_sent
; /* Adjust so we don't send too much */
207 /* Now plug into the iovec ... */
209 io_list
[i
].iov_len
= this_len
;
210 io_list
[i
].iov_base
= this_data
;
213 tot_sent
+= this_len
;
215 if (tot_sent
== len
) 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
;
242 if (len_sent
< tot_sent
) { /* Less than we wanted */
243 if (errno
== EINTR
) /* We were interrupted */
244 RFCNB_errno
= RFCNBE_Timeout
;
246 RFCNB_errno
= RFCNBE_BadWrite
;
247 RFCNB_saved_errno
= errno
;
251 if (RFCNB_Timeout
> 0)
252 alarm(0); /* Reset that sucker */
256 fprintf(stderr
, "Len sent = %i ...\n", len_sent
);
257 RFCNB_Print_Pkt(stderr
, "sent", pkt
, len_sent
); /* Print what send ... */
265 /* Read an RFCNB packet off the connection.
267 We read the first 4 bytes, that tells us the length, then read the
268 rest. We should implement a timeout, but we don't just yet
273 int RFCNB_Get_Pkt(struct RFCNB_Con
*con
, struct RFCNB_Pkt
*pkt
, int len
)
276 int read_len
, pkt_len
;
277 char hdr
[RFCNB_Pkt_Hdr_Len
]; /* Local space for the header */
278 struct RFCNB_Pkt
*pkt_frag
;
279 int more
, this_time
, offset
, frag_len
, this_len
;
280 BOOL seen_keep_alive
= TRUE
;
282 /* Read that header straight into the buffer */
284 if (len
< RFCNB_Pkt_Hdr_Len
) { /* What a bozo */
287 fprintf(stderr
, "Trying to read less than a packet:");
290 RFCNB_errno
= RFCNBE_BadParam
;
295 /* We discard keep alives here ... */
297 if (RFCNB_Timeout
> 0)
298 alarm(RFCNB_Timeout
);
300 while (seen_keep_alive
) {
302 if ((read_len
= read(con
-> fd
, hdr
, sizeof(hdr
))) < 0) { /* Problems */
304 fprintf(stderr
, "Reading the packet, we got:");
308 RFCNB_errno
= RFCNBE_Timeout
;
310 RFCNB_errno
= RFCNBE_BadRead
;
311 RFCNB_saved_errno
= errno
;
316 /* Now we check out what we got */
318 if (read_len
== 0) { /* Connection closed, send back eof? */
321 fprintf(stderr
, "Connection closed reading\n");
325 RFCNB_errno
= RFCNBE_Timeout
;
327 RFCNB_errno
= RFCNBE_ConGone
;
328 RFCNB_saved_errno
= errno
;
333 if (RFCNB_Pkt_Type(hdr
) == RFCNB_SESSION_KEEP_ALIVE
) {
336 fprintf(stderr
, "RFCNB KEEP ALIVE received\n");
340 seen_keep_alive
= FALSE
;
345 /* What if we got less than or equal to a hdr size in bytes? */
347 if (read_len
< sizeof(hdr
)) { /* We got a small packet */
349 /* Now we need to copy the hdr portion we got into the supplied packet */
351 memcpy(pkt
-> data
, hdr
, read_len
); /*Copy data */
354 RFCNB_Print_Pkt(stderr
, "rcvd", pkt
, read_len
);
361 /* Now, if we got at least a hdr size, alloc space for rest, if we need it */
363 pkt_len
= RFCNB_Pkt_Len(hdr
);
366 fprintf(stderr
, "Reading Pkt: Length = %i\n", pkt_len
);
369 /* Now copy in the hdr */
371 memcpy(pkt
-> data
, hdr
, sizeof(hdr
));
373 /* Get the rest of the packet ... first figure out how big our buf is? */
374 /* And make sure that we handle the fragments properly ... Sure should */
375 /* use an iovec ... */
377 if (len
< pkt_len
) /* Only get as much as we have space for */
378 more
= len
- RFCNB_Pkt_Hdr_Len
;
384 /* We read for each fragment ... */
386 if (pkt
-> len
== read_len
) { /* If this frag was exact size */
387 pkt_frag
= pkt
-> next
; /* Stick next lot in next frag */
388 offset
= 0; /* then we start at 0 in next */
390 pkt_frag
= pkt
; /* Otherwise use rest of this frag */
391 offset
= RFCNB_Pkt_Hdr_Len
; /* Otherwise skip the header */
394 frag_len
= pkt_frag
-> len
;
396 if (more
<= frag_len
) /* If len left to get less than frag space */
397 this_len
= more
; /* Get the rest ... */
399 this_len
= frag_len
- offset
;
403 if ((this_time
= read(con
-> fd
, (pkt_frag
-> data
) + offset
, this_len
)) <= 0) { /* Problems */
405 if (errno
== EINTR
) {
407 RFCNB_errno
= RFCNB_Timeout
;
411 RFCNB_errno
= RFCNBE_BadRead
;
413 RFCNB_errno
= RFCNBE_ConGone
;
416 RFCNB_saved_errno
= errno
;
422 fprintf(stderr
, "Frag_Len = %i, this_time = %i, this_len = %i, more = %i\n", frag_len
,
423 this_time
, this_len
, more
);
426 read_len
= read_len
+ this_time
; /* How much have we read ... */
428 /* Now set up the next part */
430 if (pkt_frag
-> next
== NULL
) break; /* That's it here */
432 pkt_frag
= pkt_frag
-> next
;
433 this_len
= pkt_frag
-> len
;
436 more
= more
- this_time
;
441 fprintf(stderr
,"Pkt Len = %i, read_len = %i\n", pkt_len
, read_len
);
442 RFCNB_Print_Pkt(stderr
, "rcvd", pkt
, read_len
+ sizeof(hdr
));
445 if (read_len
< (pkt_len
+ sizeof(hdr
))) { /* Discard the rest */
447 return(RFCNB_Discard_Rest(con
, (pkt_len
+ sizeof(hdr
)) - read_len
));
451 if (RFCNB_Timeout
> 0)
452 alarm(0); /* Reset that sucker */
454 return(read_len
+ sizeof(RFCNB_Hdr
));