"Fossies" - the Fresh Open Source Software Archive 
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 /* mod_ntlm file: $Id: rfcnb-io.inc.c,v 1.2 2003/02/21 01:55:14 casz Exp $ */
2
3
4 /* UNIX RFCNB (RFC1001/RFC1002) NEtBIOS implementation
5 *
6 * Version 1.0 RFCNB IO Routines ...
7 *
8 * Copyright (C) Richard Sharpe 1996
9 *
10 */
11
12 /*
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation; either version 2 of the
16 * License, or (at your option) any later version. This program is
17 * distributed in the hope that it will be useful, but WITHOUT ANY
18 * WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
20 * License for more details. You should have received a copy of the
21 * GNU General Public License along with this program; if not, write
22 * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
23 * 02139, USA. */
24
25 #include "std-includes.h"
26 #include "rfcnb-priv.h"
27 #include "rfcnb-util.h"
28 #include "rfcnb-io.h"
29 #include <sys/uio.h>
30 #include <sys/signal.h>
31 #include <string.h>
32
33 static int RFCNB_Timeout = 0; /* Timeout in seconds ... */
34
35 /* Discard the rest of an incoming packet as we do not have space for
36 * it in the buffer we allocated or were passed ... */
37 static int
38 RFCNB_Discard_Rest(struct RFCNB_Con *con, int len)
39 {
40 char temp[100]; /* Read into here */
41 int rest, this_read, bytes_read;
42
43 /* len is the amount we should read */
44 #ifdef RFCNB_DEBUG
45 fprintf(stderr, "Discard_Rest called to discard: %i\n", len);
46 #endif
47
48 rest = len;
49 while (rest > 0) {
50 this_read = (rest > sizeof(temp) ? sizeof(temp) : rest);
51 bytes_read = read(con->fd, temp, this_read);
52 if (bytes_read <= 0) { /* Error so return */
53 if (bytes_read < 0)
54 RFCNB_errno = RFCNBE_BadRead;
55 else
56 RFCNB_errno = RFCNBE_ConGone;
57
58 RFCNB_saved_errno = errno;
59 return (RFCNBE_Bad);
60 }
61 rest = rest - bytes_read;
62 }
63 return 0;
64 }
65
66 /* Send an RFCNB packet to the connection. We just send each of the
67 * blocks linked together ... If we can, try to send it as one iovec
68 * ... */
69 static int
70 RFCNB_Put_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len)
71 {
72 int len_sent, tot_sent, this_len;
73 struct RFCNB_Pkt *pkt_ptr;
74 char *this_data;
75 int i;
76 struct iovec io_list[10]; /* We should never have more */
77 /* If we do, this will blow up ... */
78
79 /* Try to send the data ... We only send as many bytes as len
80 * claims */
81 /* We should try to stuff it into an IOVEC and send as one write */
82
83 pkt_ptr = pkt;
84 len_sent = tot_sent = 0; /* Nothing sent so far */
85 i = 0;
86
87 while ((pkt_ptr != NULL) & (i < 10)) { /* Watch that magic number! */
88 this_len = pkt_ptr->len;
89 this_data = pkt_ptr->data;
90 if ((tot_sent + this_len) > len)
91 this_len = len - tot_sent; /* Adjust so we don't send too
92 * much */
93
94 /* Now plug into the iovec ... */
95 io_list[i].iov_len = this_len;
96 io_list[i].iov_base = this_data;
97 i++;
98
99 tot_sent += this_len;
100
101 if (tot_sent == len)
102 break; /* Let's not send too much */
103
104 pkt_ptr = pkt_ptr->next;
105 }
106
107 #ifdef RFCNB_DEBUG
108 fprintf(stderr, "Frags = %i, tot_sent = %i\n", i, tot_sent);
109 #endif
110
111 /* Set up an alarm if timeouts are set ... */
112
113 if (RFCNB_Timeout > 0)
114 alarm(RFCNB_Timeout);
115
116 if ((len_sent = writev(con->fd, io_list, i)) < 0) { /* An error */
117 con->rfc_errno = errno;
118 if (errno == EINTR) /* We were interrupted ... */
119 RFCNB_errno = RFCNBE_Timeout;
120 else
121 RFCNB_errno = RFCNBE_BadWrite;
122 RFCNB_saved_errno = errno;
123 return (RFCNBE_Bad);
124 }
125 if (len_sent < tot_sent) { /* Less than we wanted */
126 if (errno == EINTR) /* We were interrupted */
127 RFCNB_errno = RFCNBE_Timeout;
128 else
129 RFCNB_errno = RFCNBE_BadWrite;
130 RFCNB_saved_errno = errno;
131 return (RFCNBE_Bad);
132 }
133 if (RFCNB_Timeout > 0)
134 alarm(0); /* Reset that sucker */
135
136 #ifdef RFCNB_DEBUG
137 fprintf(stderr, "Len sent = %i ...\n", len_sent);
138 RFCNB_Print_Pkt(stderr, "sent", pkt, len_sent); /* Print what send... */
139 #endif
140 return len_sent;
141 }
142
143 /* Read an RFCNB packet off the connection. We read the first 4
144 * bytes, that tells us the length, then read the rest. We should
145 * implement a timeout, but we don't just yet */
146 static int
147 RFCNB_Get_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len)
148 {
149 int read_len, pkt_len;
150 char hdr[RFCNB_Pkt_Hdr_Len]; /* Local space for the header */
151 struct RFCNB_Pkt *pkt_frag;
152 int more, this_time, offset, frag_len, this_len;
153 BOOL seen_keep_alive = TRUE;
154
155 /* Read that header straight into the buffer */
156 if (len < RFCNB_Pkt_Hdr_Len) { /* What a bozo */
157 #ifdef RFCNB_DEBUG
158 fprintf(stderr, "Trying to read less than a packet:");
159 perror("");
160 #endif
161 RFCNB_errno = RFCNBE_BadParam;
162 return (RFCNBE_Bad);
163 }
164 /* We discard keep alives here ... */
165 if (RFCNB_Timeout > 0)
166 alarm(RFCNB_Timeout);
167
168 while (seen_keep_alive) {
169 if ((read_len = read(con->fd, hdr, sizeof(hdr))) < 0) { /* Problems */
170 #ifdef RFCNB_DEBUG
171 fprintf(stderr, "Reading the packet, we got:");
172 perror("");
173 #endif
174 if (errno == EINTR)
175 RFCNB_errno = RFCNBE_Timeout;
176 else
177 RFCNB_errno = RFCNBE_BadRead;
178 RFCNB_saved_errno = errno;
179 return (RFCNBE_Bad);
180 }
181 /* Now we check out what we got */
182 if (read_len == 0) { /* Connection closed, send back eof? */
183 #ifdef RFCNB_DEBUG
184 fprintf(stderr, "Connection closed reading\n");
185 #endif
186 if (errno == EINTR)
187 RFCNB_errno = RFCNBE_Timeout;
188 else
189 RFCNB_errno = RFCNBE_ConGone;
190 RFCNB_saved_errno = errno;
191 return (RFCNBE_Bad);
192 }
193 if (RFCNB_Pkt_Type(hdr) == RFCNB_SESSION_KEEP_ALIVE) {
194 #ifdef RFCNB_DEBUG
195 fprintf(stderr, "RFCNB KEEP ALIVE received\n");
196 #endif
197 } else {
198 seen_keep_alive = FALSE;
199 }
200 }
201
202 /* What if we got less than or equal to a hdr size in bytes? */
203 if (read_len < sizeof(hdr)) { /* We got a small packet */
204 /* Now we need to copy the hdr portion we got into the
205 * supplied packet */
206 memcpy(pkt->data, hdr, read_len); /* Copy data */
207 #ifdef RFCNB_DEBUG
208 RFCNB_Print_Pkt(stderr, "rcvd", pkt, read_len);
209 #endif
210 return read_len;
211 }
212 /* Now, if we got at least a hdr size, alloc space for rest, if we
213 * need it */
214 pkt_len = RFCNB_Pkt_Len(hdr);
215
216 #ifdef RFCNB_DEBUG
217 fprintf(stderr, "Reading Pkt: Length = %i\n", pkt_len);
218 #endif
219
220 /* Now copy in the hdr */
221 memcpy(pkt->data, hdr, sizeof(hdr));
222
223 /* Get the rest of the packet ... first figure out how big our buf
224 * is? And make sure that we handle the fragments properly
225 * ... Sure should use an iovec ... */
226 if (len < pkt_len) /* Only get as much as we have space for */
227 more = len - RFCNB_Pkt_Hdr_Len;
228 else
229 more = pkt_len;
230
231 this_time = 0;
232
233 /* We read for each fragment ... */
234 if (pkt->len == read_len) { /* If this frag was exact size */
235 pkt_frag = pkt->next; /* Stick next lot in next frag */
236 offset = 0; /* then we start at 0 in next */
237 } else {
238 pkt_frag = pkt; /* Otherwise use rest of this frag */
239 offset = RFCNB_Pkt_Hdr_Len; /* Otherwise skip the header */
240 }
241
242 frag_len = pkt_frag->len;
243 if (more <= frag_len) /* If len left to get less than frag space */
244 this_len = more; /* Get the rest ... */
245 else
246 this_len = frag_len - offset;
247
248 while (more > 0) {
249 if ((this_time = read(con->fd, (pkt_frag->data) + offset,
250 this_len)) <= 0) { /* Problems */
251 if (errno == EINTR) {
252 RFCNB_errno = RFCNB_Timeout;
253 } else {
254 if (this_time < 0)
255 RFCNB_errno = RFCNBE_BadRead;
256 else
257 RFCNB_errno = RFCNBE_ConGone;
258 }
259 RFCNB_saved_errno = errno;
260 return (RFCNBE_Bad);
261
262 }
263 #ifdef RFCNB_DEBUG
264 fprintf(stderr, "Frag_Len = %i, this_time = %i, this_len = %i, more = %i\n", frag_len,
265 this_time, this_len, more);
266 #endif
267
268 read_len = read_len + this_time; /* How much have we read... */
269 /* Now set up the next part */
270 if (pkt_frag->next == NULL)
271 break; /* That's it here */
272
273 pkt_frag = pkt_frag->next;
274 this_len = pkt_frag->len;
275 offset = 0;
276
277 more = more - this_time;
278 }
279
280 #ifdef RFCNB_DEBUG
281 fprintf(stderr, "Pkt Len = %i, read_len = %i\n", pkt_len, read_len);
282 RFCNB_Print_Pkt(stderr, "rcvd", pkt, read_len + sizeof(hdr));
283 #endif
284
285 if (read_len < (pkt_len + sizeof(hdr))) { /* Discard the rest */
286 return (RFCNB_Discard_Rest(con, (pkt_len + sizeof(hdr)) - read_len));
287 }
288 if (RFCNB_Timeout > 0)
289 alarm(0); /* Reset that sucker */
290
291 return (read_len + sizeof(RFCNB_Hdr));
292 }