1 /* UNIX RFCNB (RFC1001/RFC1002) NEtBIOS implementation
6 Copyright (C) Richard Sharpe 1996
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 /* #include <features.h> */
26 #include "std-includes.h"
27 #include "rfcnb-priv.h"
28 #include "rfcnb-util.h"
35 #ifdef HAVE_SYS_SIGNAL_H
36 #include <sys/signal.h>
41 int RFCNB_Timeout = 0; /* Timeout in seconds ... */
43 void rfcnb_alarm(int sig)
47 fprintf(stderr, "IO Timed out ...\n");
51 /* Set timeout value and setup signal handling */
53 int RFCNB_Set_Timeout(int seconds)
57 /* If we are on a Bezerkeley system, use sigvec, else sigaction */
59 struct sigvec invec, outvec;
61 struct sigaction inact, outact;
64 RFCNB_Timeout = seconds;
66 if (RFCNB_Timeout > 0) { /* Set up handler to ignore but not restart */
69 invec.sv_handler = (void (*)())rfcnb_alarm;
71 invec.sv_flags = SV_INTERRUPT;
73 if (sigvec(SIGALRM, &invec, &outvec) < 0)
76 inact.sa_handler = (void (*)())rfcnb_alarm;
77 sigemptyset(&inact.sa_mask);
78 inact.sa_flags = 0; /* Don't restart */
80 if (sigaction(SIGALRM, &inact, &outact) < 0)
91 /* Discard the rest of an incoming packet as we do not have space for it
92 in the buffer we allocated or were passed ... */
94 int RFCNB_Discard_Rest(struct RFCNB_Con *con, int len)
96 { char temp[100]; /* Read into here */
97 int rest, this_read, bytes_read;
99 /* len is the amount we should read */
102 fprintf(stderr, "Discard_Rest called to discard: %i\n", len);
109 this_read = (rest > sizeof(temp)?sizeof(temp):rest);
111 bytes_read = read(con -> fd, temp, this_read);
113 if (bytes_read <= 0) { /* Error so return */
116 RFCNB_errno = RFCNBE_BadRead;
118 RFCNB_errno = RFCNBE_ConGone;
120 RFCNB_saved_errno = errno;
125 rest = rest - bytes_read;
134 /* Send an RFCNB packet to the connection.
136 We just send each of the blocks linked together ...
138 If we can, try to send it as one iovec ...
142 int RFCNB_Put_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len)
144 { int len_sent, tot_sent, this_len;
145 struct RFCNB_Pkt *pkt_ptr;
148 struct iovec io_list[10]; /* We should never have more */
149 /* If we do, this will blow up ...*/
151 /* Try to send the data ... We only send as many bytes as len claims */
152 /* We should try to stuff it into an IOVEC and send as one write */
156 len_sent = tot_sent = 0; /* Nothing sent so far */
159 while ((pkt_ptr != NULL) & (i < 10)) { /* Watch that magic number! */
161 this_len = pkt_ptr -> len;
162 this_data = pkt_ptr -> data;
163 if ((tot_sent + this_len) > len)
164 this_len = len - tot_sent; /* Adjust so we don't send too much */
166 /* Now plug into the iovec ... */
168 io_list[i].iov_len = this_len;
169 io_list[i].iov_base = this_data;
172 tot_sent += this_len;
174 if (tot_sent == len) break; /* Let's not send too much */
176 pkt_ptr = pkt_ptr -> next;
181 fprintf(stderr, "Frags = %i, tot_sent = %i\n", i, tot_sent);
184 /* Set up an alarm if timeouts are set ... */
186 if (RFCNB_Timeout > 0)
187 alarm(RFCNB_Timeout);
189 if ((len_sent = writev(con -> fd, io_list, i)) < 0) { /* An error */
191 con -> rfc_errno = errno;
192 if (errno == EINTR) /* We were interrupted ... */
193 RFCNB_errno = RFCNBE_Timeout;
195 RFCNB_errno = RFCNBE_BadWrite;
196 RFCNB_saved_errno = errno;
201 if (len_sent < tot_sent) { /* Less than we wanted */
202 if (errno == EINTR) /* We were interrupted */
203 RFCNB_errno = RFCNBE_Timeout;
205 RFCNB_errno = RFCNBE_BadWrite;
206 RFCNB_saved_errno = errno;
210 if (RFCNB_Timeout > 0)
211 alarm(0); /* Reset that sucker */
215 fprintf(stderr, "Len sent = %i ...\n", len_sent);
216 RFCNB_Print_Pkt(stderr, "sent", pkt, len_sent); /* Print what send ... */
224 /* Read an RFCNB packet off the connection.
226 We read the first 4 bytes, that tells us the length, then read the
227 rest. We should implement a timeout, but we don't just yet
232 int RFCNB_Get_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len)
234 { int read_len, pkt_len;
235 char hdr[RFCNB_Pkt_Hdr_Len]; /* Local space for the header */
236 struct RFCNB_Pkt *pkt_frag;
237 int more, this_time, offset, frag_len, this_len;
238 BOOL seen_keep_alive = TRUE;
240 /* Read that header straight into the buffer */
242 if (len < RFCNB_Pkt_Hdr_Len) { /* What a bozo */
245 fprintf(stderr, "Trying to read less than a packet:");
248 RFCNB_errno = RFCNBE_BadParam;
253 /* We discard keep alives here ... */
255 if (RFCNB_Timeout > 0)
256 alarm(RFCNB_Timeout);
258 while (seen_keep_alive) {
260 if ((read_len = read(con -> fd, hdr, sizeof(hdr))) < 0) { /* Problems */
262 fprintf(stderr, "Reading the packet, we got:");
266 RFCNB_errno = RFCNBE_Timeout;
268 RFCNB_errno = RFCNBE_BadRead;
269 RFCNB_saved_errno = errno;
274 /* Now we check out what we got */
276 if (read_len == 0) { /* Connection closed, send back eof? */
279 fprintf(stderr, "Connection closed reading\n");
283 RFCNB_errno = RFCNBE_Timeout;
285 RFCNB_errno = RFCNBE_ConGone;
286 RFCNB_saved_errno = errno;
291 if (RFCNB_Pkt_Type(hdr) == RFCNB_SESSION_KEEP_ALIVE) {
294 fprintf(stderr, "RFCNB KEEP ALIVE received\n");
299 seen_keep_alive = FALSE;
304 /* What if we got less than or equal to a hdr size in bytes? */
306 if (read_len < sizeof(hdr)) { /* We got a small packet */
308 /* Now we need to copy the hdr portion we got into the supplied packet */
310 memcpy(pkt -> data, hdr, read_len); /*Copy data */
313 RFCNB_Print_Pkt(stderr, "rcvd", pkt, read_len);
320 /* Now, if we got at least a hdr size, alloc space for rest, if we need it */
322 pkt_len = RFCNB_Pkt_Len(hdr);
325 fprintf(stderr, "Reading Pkt: Length = %i\n", pkt_len);
328 /* Now copy in the hdr */
330 memcpy(pkt -> data, hdr, sizeof(hdr));
332 /* Get the rest of the packet ... first figure out how big our buf is? */
333 /* And make sure that we handle the fragments properly ... Sure should */
334 /* use an iovec ... */
336 if (len < pkt_len) /* Only get as much as we have space for */
337 more = len - RFCNB_Pkt_Hdr_Len;
343 /* We read for each fragment ... */
345 if (pkt -> len == read_len){ /* If this frag was exact size */
346 pkt_frag = pkt -> next; /* Stick next lot in next frag */
347 offset = 0; /* then we start at 0 in next */
350 pkt_frag = pkt; /* Otherwise use rest of this frag */
351 offset = RFCNB_Pkt_Hdr_Len; /* Otherwise skip the header */
354 frag_len = pkt_frag -> len;
356 if (more <= frag_len) /* If len left to get less than frag space */
357 this_len = more; /* Get the rest ... */
359 this_len = frag_len - offset;
363 if ((this_time = read(con -> fd, (pkt_frag -> data) + offset, this_len)) <= 0) { /* Problems */
365 if (errno == EINTR) {
367 RFCNB_errno = RFCNB_Timeout;
372 RFCNB_errno = RFCNBE_BadRead;
374 RFCNB_errno = RFCNBE_ConGone;
377 RFCNB_saved_errno = errno;
383 fprintf(stderr, "Frag_Len = %i, this_time = %i, this_len = %i, more = %i\n", frag_len,
384 this_time, this_len, more);
387 read_len = read_len + this_time; /* How much have we read ... */
389 /* Now set up the next part */
391 if (pkt_frag -> next == NULL) break; /* That's it here */
393 pkt_frag = pkt_frag -> next;
394 this_len = pkt_frag -> len;
397 more = more - this_time;
402 fprintf(stderr,"Pkt Len = %i, read_len = %i\n", pkt_len, read_len);
403 RFCNB_Print_Pkt(stderr, "rcvd", pkt, read_len + sizeof(hdr));
406 if (read_len < (pkt_len + sizeof(hdr))) { /* Discard the rest */
408 return(RFCNB_Discard_Rest(con, (pkt_len + sizeof(hdr)) - read_len));
412 if (RFCNB_Timeout > 0)
413 alarm(0); /* Reset that sucker */
415 return(read_len + sizeof(RFCNB_Hdr));