]>
git.ipfire.org Git - thirdparty/squid.git/blob - lib/rfcnb/rfcnb-io.c
2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
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.
9 /* UNIX RFCNB (RFC1001/RFC1002) NEtBIOS implementation
12 * RFCNB IO Routines ...
14 * Copyright (C) Richard Sharpe 1996
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.
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.
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.
34 #include "rfcnb/rfcnb-io.h"
35 #include "rfcnb/rfcnb-priv.h"
36 #include "rfcnb/rfcnb-util.h"
37 #include "rfcnb/std-includes.h"
47 int RFCNB_Timeout
= 0; /* Timeout in seconds ... */
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 ... */
54 RFCNB_Discard_Rest(struct RFCNB_Con
*con
, int len
)
56 char temp
[100]; /* Read into here */
57 int rest
, this_read
, bytes_read
;
59 /* len is the amount we should read */
62 fprintf(stderr
, "Discard_Rest called to discard: %i\n", len
);
69 this_read
= (rest
> sizeof(temp
) ? sizeof(temp
) : rest
);
71 bytes_read
= read(con
->fd
, temp
, this_read
);
73 if (bytes_read
<= 0) { /* Error so return */
76 RFCNB_errno
= RFCNBE_BadRead
;
78 RFCNB_errno
= RFCNBE_ConGone
;
80 RFCNB_saved_errno
= errno
;
84 rest
= rest
- bytes_read
;
92 /* Send an RFCNB packet to the connection.
94 * We just send each of the blocks linked together ...
96 * If we can, try to send it as one iovec ...
101 RFCNB_Put_Pkt(struct RFCNB_Con
*con
, struct RFCNB_Pkt
*pkt
, int len
)
103 int len_sent
, tot_sent
, this_len
;
104 struct RFCNB_Pkt
*pkt_ptr
;
107 struct iovec io_list
[10]; /* We should never have more */
108 /* If we do, this will blow up ... */
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 */
114 len_sent
= tot_sent
= 0; /* Nothing sent so far */
117 while ((pkt_ptr
!= NULL
) & (i
< 10)) { /* Watch that magic number! */
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 */
124 /* Now plug into the iovec ... */
126 io_list
[i
].iov_len
= this_len
;
127 io_list
[i
].iov_base
= this_data
;
130 tot_sent
+= this_len
;
133 break; /* Let's not send too much */
135 pkt_ptr
= pkt_ptr
->next
;
140 fprintf(stderr
, "Frags = %i, tot_sent = %i\n", i
, tot_sent
);
143 /* Set up an alarm if timeouts are set ... */
145 if (RFCNB_Timeout
> 0)
146 alarm(RFCNB_Timeout
);
148 if ((len_sent
= writev(con
->fd
, io_list
, i
)) < 0) { /* An error */
151 if (errno
== EINTR
) /* We were interrupted ... */
152 RFCNB_errno
= RFCNBE_Timeout
;
154 RFCNB_errno
= RFCNBE_BadWrite
;
155 RFCNB_saved_errno
= errno
;
159 if (len_sent
< tot_sent
) { /* Less than we wanted */
160 if (errno
== EINTR
) /* We were interrupted */
161 RFCNB_errno
= RFCNBE_Timeout
;
163 RFCNB_errno
= RFCNBE_BadWrite
;
164 RFCNB_saved_errno
= errno
;
167 if (RFCNB_Timeout
> 0)
168 alarm(0); /* Reset that sucker */
172 fprintf(stderr
, "Len sent = %i ...\n", len_sent
);
173 RFCNB_Print_Pkt(stderr
, "sent", pkt
, len_sent
); /* Print what send ... */
181 /* Read an RFCNB packet off the connection.
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
189 RFCNB_Get_Pkt(struct RFCNB_Con
*con
, struct RFCNB_Pkt
*pkt
, int len
)
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
;
197 /* Read that header straight into the buffer */
199 if (len
< RFCNB_Pkt_Hdr_Len
) { /* What a bozo */
202 fprintf(stderr
, "Trying to read less than a packet:");
205 RFCNB_errno
= RFCNBE_BadParam
;
209 /* We discard keep alives here ... */
211 if (RFCNB_Timeout
> 0)
212 alarm(RFCNB_Timeout
);
214 while (seen_keep_alive
) {
216 if ((read_len
= read(con
->fd
, hdr
, sizeof(hdr
))) < 0) { /* Problems */
218 fprintf(stderr
, "Reading the packet, we got:");
222 RFCNB_errno
= RFCNBE_Timeout
;
224 RFCNB_errno
= RFCNBE_BadRead
;
225 RFCNB_saved_errno
= errno
;
229 /* Now we check out what we got */
231 if (read_len
== 0) { /* Connection closed, send back eof? */
234 fprintf(stderr
, "Connection closed reading\n");
238 RFCNB_errno
= RFCNBE_Timeout
;
240 RFCNB_errno
= RFCNBE_ConGone
;
241 RFCNB_saved_errno
= errno
;
245 if (RFCNB_Pkt_Type(hdr
) == RFCNB_SESSION_KEEP_ALIVE
) {
248 fprintf(stderr
, "RFCNB KEEP ALIVE received\n");
252 seen_keep_alive
= FALSE
;
257 /* What if we got less than or equal to a hdr size in bytes? */
259 if (read_len
< sizeof(hdr
)) { /* We got a small packet */
261 /* Now we need to copy the hdr portion we got into the supplied packet */
263 memcpy(pkt
->data
, hdr
, read_len
); /*Copy data */
266 RFCNB_Print_Pkt(stderr
, "rcvd", pkt
, read_len
);
272 /* Now, if we got at least a hdr size, alloc space for rest, if we need it */
274 pkt_len
= RFCNB_Pkt_Len(hdr
);
277 fprintf(stderr
, "Reading Pkt: Length = %i\n", pkt_len
);
280 /* Now copy in the hdr */
282 memcpy(pkt
->data
, hdr
, sizeof(hdr
));
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 ... */
288 if (len
< pkt_len
) /* Only get as much as we have space for */
289 more
= len
- RFCNB_Pkt_Hdr_Len
;
295 /* We read for each fragment ... */
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 */
301 pkt_frag
= pkt
; /* Otherwise use rest of this frag */
302 offset
= RFCNB_Pkt_Hdr_Len
; /* Otherwise skip the header */
305 frag_len
= (pkt_frag
? pkt_frag
->len
: 0);
307 if (more
<= frag_len
) /* If len left to get less than frag space */
308 this_len
= more
; /* Get the rest ... */
310 this_len
= frag_len
- offset
;
314 if ((this_time
= read(con
->fd
, (pkt_frag
->data
) + offset
, this_len
)) <= 0) { /* Problems */
316 if (errno
== EINTR
) {
318 RFCNB_errno
= RFCNB_Timeout
;
322 RFCNB_errno
= RFCNBE_BadRead
;
324 RFCNB_errno
= RFCNBE_ConGone
;
327 RFCNB_saved_errno
= errno
;
332 fprintf(stderr
, "Frag_Len = %i, this_time = %i, this_len = %i, more = %i\n", frag_len
,
333 this_time
, this_len
, more
);
336 read_len
= read_len
+ this_time
; /* How much have we read ... */
338 /* Now set up the next part */
340 if (pkt_frag
->next
== NULL
)
341 break; /* That's it here */
343 pkt_frag
= pkt_frag
->next
;
344 this_len
= pkt_frag
->len
;
347 more
= more
- this_time
;
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
));
356 if (read_len
< (pkt_len
+ sizeof(hdr
))) { /* Discard the rest */
358 return (RFCNB_Discard_Rest(con
, (pkt_len
+ sizeof(hdr
)) - read_len
));
361 if (RFCNB_Timeout
> 0)
362 alarm(0); /* Reset that sucker */
364 return (read_len
+ sizeof(RFCNB_Hdr
));