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.
31 #include "rfcnb-priv.h"
32 #include "rfcnb-util.h"
35 int RFCNB_Timeout = 0; /* Timeout in seconds ... */
37 /* Discard the rest of an incoming packet as we do not have space for it
38 in the buffer we allocated or were passed ... */
40 int RFCNB_Discard_Rest(struct RFCNB_Con *con, int len)
42 { char temp[100]; /* Read into here */
43 int rest, this_read, bytes_read;
45 /* len is the amount we should read */
51 this_read = (rest > sizeof(temp)?sizeof(temp):rest);
53 bytes_read = read(con -> fd, temp, this_read);
55 if (bytes_read <= 0) { /* Error so return */
58 RFCNB_errno = RFCNBE_BadRead;
60 RFCNB_errno = RFCNBE_ConGone;
62 RFCNB_saved_errno = errno;
67 rest = rest - bytes_read;
76 /* Send an RFCNB packet to the connection.
78 We just send each of the blocks linked together ...
80 If we can, try to send it as one iovec ...
84 int RFCNB_Put_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len)
86 { int len_sent, tot_sent, this_len;
87 struct RFCNB_Pkt *pkt_ptr;
90 struct iovec io_list[10]; /* We should never have more */
91 /* If we do, this will blow up ...*/
93 /* Try to send the data ... We only send as many bytes as len claims */
94 /* We should try to stuff it into an IOVEC and send as one write */
98 len_sent = tot_sent = 0; /* Nothing sent so far */
101 while ((pkt_ptr != NULL) & (i < 10)) { /* Watch that magic number! */
103 this_len = pkt_ptr -> len;
104 this_data = pkt_ptr -> data;
105 if ((tot_sent + this_len) > len)
106 this_len = len - tot_sent; /* Adjust so we don't send too much */
108 /* Now plug into the iovec ... */
110 io_list[i].iov_len = this_len;
111 io_list[i].iov_base = this_data;
114 tot_sent += this_len;
116 if (tot_sent == len) break; /* Let's not send too much */
118 pkt_ptr = pkt_ptr -> next;
122 /* Set up an alarm if timeouts are set ... */
124 if (RFCNB_Timeout > 0)
125 alarm(RFCNB_Timeout);
127 if ((len_sent = writev(con -> fd, io_list, i)) < 0) { /* An error */
129 con -> rfc_errno = errno;
130 if (errno == EINTR) /* We were interrupted ... */
131 RFCNB_errno = RFCNBE_Timeout;
133 RFCNB_errno = RFCNBE_BadWrite;
134 RFCNB_saved_errno = errno;
139 if (len_sent < tot_sent) { /* Less than we wanted */
140 if (errno == EINTR) /* We were interrupted */
141 RFCNB_errno = RFCNBE_Timeout;
143 RFCNB_errno = RFCNBE_BadWrite;
144 RFCNB_saved_errno = errno;
148 if (RFCNB_Timeout > 0)
149 alarm(0); /* Reset that sucker */
155 /* Read an RFCNB packet off the connection.
157 We read the first 4 bytes, that tells us the length, then read the
158 rest. We should implement a timeout, but we don't just yet
163 int RFCNB_Get_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len)
165 { int read_len, pkt_len;
166 char hdr[RFCNB_Pkt_Hdr_Len]; /* Local space for the header */
167 struct RFCNB_Pkt *pkt_frag;
168 int more, this_time, offset, frag_len, this_len;
169 bool seen_keep_alive = true;
171 /* Read that header straight into the buffer */
173 if (len < RFCNB_Pkt_Hdr_Len) { /* What a bozo */
175 RFCNB_errno = RFCNBE_BadParam;
180 /* We discard keep alives here ... */
182 if (RFCNB_Timeout > 0)
183 alarm(RFCNB_Timeout);
185 while (seen_keep_alive) {
187 if ((read_len = read(con -> fd, hdr, sizeof(hdr))) < 0) { /* Problems */
189 RFCNB_errno = RFCNBE_Timeout;
191 RFCNB_errno = RFCNBE_BadRead;
192 RFCNB_saved_errno = errno;
197 /* Now we check out what we got */
199 if (read_len == 0) { /* Connection closed, send back eof? */
202 RFCNB_errno = RFCNBE_Timeout;
204 RFCNB_errno = RFCNBE_ConGone;
205 RFCNB_saved_errno = errno;
210 if (RFCNB_Pkt_Type(hdr) != RFCNB_SESSION_KEEP_ALIVE) {
211 seen_keep_alive = false;
216 /* What if we got less than or equal to a hdr size in bytes? */
218 if (read_len < sizeof(hdr)) { /* We got a small packet */
220 /* Now we need to copy the hdr portion we got into the supplied packet */
222 memcpy(pkt -> data, hdr, read_len); /*Copy data */
228 /* Now, if we got at least a hdr size, alloc space for rest, if we need it */
230 pkt_len = RFCNB_Pkt_Len(hdr);
232 /* Now copy in the hdr */
234 memcpy(pkt -> data, hdr, sizeof(hdr));
236 /* Get the rest of the packet ... first figure out how big our buf is? */
237 /* And make sure that we handle the fragments properly ... Sure should */
238 /* use an iovec ... */
240 if (len < pkt_len) /* Only get as much as we have space for */
241 more = len - RFCNB_Pkt_Hdr_Len;
247 /* We read for each fragment ... */
249 if (pkt -> len == read_len){ /* If this frag was exact size */
250 pkt_frag = pkt -> next; /* Stick next lot in next frag */
251 offset = 0; /* then we start at 0 in next */
254 pkt_frag = pkt; /* Otherwise use rest of this frag */
255 offset = RFCNB_Pkt_Hdr_Len; /* Otherwise skip the header */
258 frag_len = pkt_frag -> len;
260 if (more <= frag_len) /* If len left to get less than frag space */
261 this_len = more; /* Get the rest ... */
263 this_len = frag_len - offset;
267 if ((this_time = read(con -> fd, (pkt_frag -> data) + offset, this_len)) <= 0) { /* Problems */
269 if (errno == EINTR) {
271 RFCNB_errno = RFCNB_Timeout;
276 RFCNB_errno = RFCNBE_BadRead;
278 RFCNB_errno = RFCNBE_ConGone;
281 RFCNB_saved_errno = errno;
286 read_len = read_len + this_time; /* How much have we read ... */
288 /* Now set up the next part */
290 if (pkt_frag -> next == NULL) break; /* That's it here */
292 pkt_frag = pkt_frag -> next;
293 this_len = pkt_frag -> len;
296 more = more - this_time;
300 if (read_len < (pkt_len + sizeof(hdr))) { /* Discard the rest */
302 return(RFCNB_Discard_Rest(con, (pkt_len + sizeof(hdr)) - read_len));
306 if (RFCNB_Timeout > 0)
307 alarm(0); /* Reset that sucker */
309 return(read_len + sizeof(RFCNB_Hdr));