File: | slirp/socket.c |
Location: | line 236, column 5 |
Description: | Null pointer passed as an argument to a 'nonnull' parameter |
1 | /* | |||
2 | * Copyright (c) 1995 Danny Gasparovski. | |||
3 | * | |||
4 | * Please read the file COPYRIGHT for the | |||
5 | * terms and conditions of the copyright. | |||
6 | */ | |||
7 | ||||
8 | #include "qemu-common.h" | |||
9 | #include <slirp.h> | |||
10 | #include "ip_icmp.h" | |||
11 | #ifdef __sun__ | |||
12 | #include <sys/filio.h> | |||
13 | #endif | |||
14 | ||||
15 | static void sofcantrcvmore(struct socket *so); | |||
16 | static void sofcantsendmore(struct socket *so); | |||
17 | ||||
18 | struct socket * | |||
19 | solookup(struct socket *head, struct in_addr laddr, u_int lport, | |||
20 | struct in_addr faddr, u_int fport) | |||
21 | { | |||
22 | struct socket *so; | |||
23 | ||||
24 | for (so = head->so_next; so != head; so = so->so_next) { | |||
25 | if (so->so_lport == lport && | |||
26 | so->so_laddr.s_addr == laddr.s_addr && | |||
27 | so->so_faddr.s_addr == faddr.s_addr && | |||
28 | so->so_fport == fport) | |||
29 | break; | |||
30 | } | |||
31 | ||||
32 | if (so == head) | |||
33 | return (struct socket *)NULL((void*)0); | |||
34 | return so; | |||
35 | ||||
36 | } | |||
37 | ||||
38 | /* | |||
39 | * Create a new socket, initialise the fields | |||
40 | * It is the responsibility of the caller to | |||
41 | * insque() it into the correct linked-list | |||
42 | */ | |||
43 | struct socket * | |||
44 | socreate(Slirp *slirp) | |||
45 | { | |||
46 | struct socket *so; | |||
47 | ||||
48 | so = (struct socket *)malloc(sizeof(struct socket)); | |||
49 | if(so) { | |||
50 | memset(so, 0, sizeof(struct socket)); | |||
51 | so->so_state = SS_NOFDREF0x001; | |||
52 | so->s = -1; | |||
53 | so->slirp = slirp; | |||
54 | so->pollfds_idx = -1; | |||
55 | } | |||
56 | return(so); | |||
57 | } | |||
58 | ||||
59 | /* | |||
60 | * remque and free a socket, clobber cache | |||
61 | */ | |||
62 | void | |||
63 | sofree(struct socket *so) | |||
64 | { | |||
65 | Slirp *slirp = so->slirp; | |||
66 | ||||
67 | if (so->so_emu==EMU_RSH0x8 && so->extra) { | |||
68 | sofree(so->extra); | |||
69 | so->extra=NULL((void*)0); | |||
70 | } | |||
71 | if (so == slirp->tcp_last_so) { | |||
72 | slirp->tcp_last_so = &slirp->tcb; | |||
73 | } else if (so == slirp->udp_last_so) { | |||
74 | slirp->udp_last_so = &slirp->udb; | |||
75 | } else if (so == slirp->icmp_last_so) { | |||
76 | slirp->icmp_last_so = &slirp->icmp; | |||
77 | } | |||
78 | m_free(so->so_m); | |||
79 | ||||
80 | if(so->so_next && so->so_prev) | |||
81 | remqueslirp_remque(so); /* crashes if so is not in a queue */ | |||
82 | ||||
83 | free(so); | |||
84 | } | |||
85 | ||||
86 | size_t sopreprbuf(struct socket *so, struct iovec *iov, int *np) | |||
87 | { | |||
88 | int n, lss, total; | |||
89 | struct sbuf *sb = &so->so_snd; | |||
90 | int len = sb->sb_datalen - sb->sb_cc; | |||
91 | int mss = so->so_tcpcb->t_maxseg; | |||
92 | ||||
93 | DEBUG_CALL("sopreprbuf"); | |||
94 | DEBUG_ARG("so = %lx", (long )so); | |||
95 | ||||
96 | if (len <= 0) | |||
97 | return 0; | |||
98 | ||||
99 | iov[0].iov_base = sb->sb_wptr; | |||
100 | iov[1].iov_base = NULL((void*)0); | |||
101 | iov[1].iov_len = 0; | |||
102 | if (sb->sb_wptr < sb->sb_rptr) { | |||
103 | iov[0].iov_len = sb->sb_rptr - sb->sb_wptr; | |||
104 | /* Should never succeed, but... */ | |||
105 | if (iov[0].iov_len > len) | |||
106 | iov[0].iov_len = len; | |||
107 | if (iov[0].iov_len > mss) | |||
108 | iov[0].iov_len -= iov[0].iov_len%mss; | |||
109 | n = 1; | |||
110 | } else { | |||
111 | iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_wptr; | |||
112 | /* Should never succeed, but... */ | |||
113 | if (iov[0].iov_len > len) iov[0].iov_len = len; | |||
114 | len -= iov[0].iov_len; | |||
115 | if (len) { | |||
116 | iov[1].iov_base = sb->sb_data; | |||
117 | iov[1].iov_len = sb->sb_rptr - sb->sb_data; | |||
118 | if(iov[1].iov_len > len) | |||
119 | iov[1].iov_len = len; | |||
120 | total = iov[0].iov_len + iov[1].iov_len; | |||
121 | if (total > mss) { | |||
122 | lss = total%mss; | |||
123 | if (iov[1].iov_len > lss) { | |||
124 | iov[1].iov_len -= lss; | |||
125 | n = 2; | |||
126 | } else { | |||
127 | lss -= iov[1].iov_len; | |||
128 | iov[0].iov_len -= lss; | |||
129 | n = 1; | |||
130 | } | |||
131 | } else | |||
132 | n = 2; | |||
133 | } else { | |||
134 | if (iov[0].iov_len > mss) | |||
135 | iov[0].iov_len -= iov[0].iov_len%mss; | |||
136 | n = 1; | |||
137 | } | |||
138 | } | |||
139 | if (np) | |||
140 | *np = n; | |||
141 | ||||
142 | return iov[0].iov_len + (n - 1) * iov[1].iov_len; | |||
143 | } | |||
144 | ||||
145 | /* | |||
146 | * Read from so's socket into sb_snd, updating all relevant sbuf fields | |||
147 | * NOTE: This will only be called if it is select()ed for reading, so | |||
148 | * a read() of 0 (or less) means it's disconnected | |||
149 | */ | |||
150 | int | |||
151 | soread(struct socket *so) | |||
152 | { | |||
153 | int n, nn; | |||
154 | struct sbuf *sb = &so->so_snd; | |||
155 | struct iovec iov[2]; | |||
156 | ||||
157 | DEBUG_CALL("soread"); | |||
158 | DEBUG_ARG("so = %lx", (long )so); | |||
159 | ||||
160 | /* | |||
161 | * No need to check if there's enough room to read. | |||
162 | * soread wouldn't have been called if there weren't | |||
163 | */ | |||
164 | sopreprbuf(so, iov, &n); | |||
165 | ||||
166 | #ifdef HAVE_READV | |||
167 | nn = readv(so->s, (struct iovec *)iov, n); | |||
168 | DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn)); | |||
169 | #else | |||
170 | nn = qemu_recv(so->s, iov[0].iov_base, iov[0].iov_len,0)recv(so->s, iov[0].iov_base, iov[0].iov_len, 0); | |||
171 | #endif | |||
172 | if (nn <= 0) { | |||
173 | if (nn < 0 && (errno(*__errno_location ()) == EINTR4 || errno(*__errno_location ()) == EAGAIN11)) | |||
174 | return 0; | |||
175 | else { | |||
176 | DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,strerror(errno))); | |||
177 | sofcantrcvmore(so); | |||
178 | tcp_sockclosed(sototcpcb(so)((so)->so_tcpcb)); | |||
179 | return -1; | |||
180 | } | |||
181 | } | |||
182 | ||||
183 | #ifndef HAVE_READV | |||
184 | /* | |||
185 | * If there was no error, try and read the second time round | |||
186 | * We read again if n = 2 (ie, there's another part of the buffer) | |||
187 | * and we read as much as we could in the first read | |||
188 | * We don't test for <= 0 this time, because there legitimately | |||
189 | * might not be any more data (since the socket is non-blocking), | |||
190 | * a close will be detected on next iteration. | |||
191 | * A return of -1 wont (shouldn't) happen, since it didn't happen above | |||
192 | */ | |||
193 | if (n == 2 && nn == iov[0].iov_len) { | |||
194 | int ret; | |||
195 | ret = qemu_recv(so->s, iov[1].iov_base, iov[1].iov_len,0)recv(so->s, iov[1].iov_base, iov[1].iov_len, 0); | |||
196 | if (ret > 0) | |||
197 | nn += ret; | |||
198 | } | |||
199 | ||||
200 | DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn)); | |||
201 | #endif | |||
202 | ||||
203 | /* Update fields */ | |||
204 | sb->sb_cc += nn; | |||
205 | sb->sb_wptr += nn; | |||
206 | if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen)) | |||
207 | sb->sb_wptr -= sb->sb_datalen; | |||
208 | return nn; | |||
209 | } | |||
210 | ||||
211 | int soreadbuf(struct socket *so, const char *buf, int size) | |||
212 | { | |||
213 | int n, nn, copy = size; | |||
214 | struct sbuf *sb = &so->so_snd; | |||
215 | struct iovec iov[2]; | |||
216 | ||||
217 | DEBUG_CALL("soreadbuf"); | |||
218 | DEBUG_ARG("so = %lx", (long )so); | |||
219 | ||||
220 | /* | |||
221 | * No need to check if there's enough room to read. | |||
222 | * soread wouldn't have been called if there weren't | |||
223 | */ | |||
224 | if (sopreprbuf(so, iov, &n) < size) | |||
| ||||
225 | goto err; | |||
226 | ||||
227 | nn = MIN(iov[0].iov_len, copy)(((iov[0].iov_len) < (copy)) ? (iov[0].iov_len) : (copy)); | |||
228 | memcpy(iov[0].iov_base, buf, nn); | |||
229 | ||||
230 | copy -= nn; | |||
231 | buf += nn; | |||
232 | ||||
233 | if (copy == 0) | |||
234 | goto done; | |||
235 | ||||
236 | memcpy(iov[1].iov_base, buf, copy); | |||
| ||||
237 | ||||
238 | done: | |||
239 | /* Update fields */ | |||
240 | sb->sb_cc += size; | |||
241 | sb->sb_wptr += size; | |||
242 | if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen)) | |||
243 | sb->sb_wptr -= sb->sb_datalen; | |||
244 | return size; | |||
245 | err: | |||
246 | ||||
247 | sofcantrcvmore(so); | |||
248 | tcp_sockclosed(sototcpcb(so)((so)->so_tcpcb)); | |||
249 | fprintf(stderrstderr, "soreadbuf buffer to small"); | |||
250 | return -1; | |||
251 | } | |||
252 | ||||
253 | /* | |||
254 | * Get urgent data | |||
255 | * | |||
256 | * When the socket is created, we set it SO_OOBINLINE, | |||
257 | * so when OOB data arrives, we soread() it and everything | |||
258 | * in the send buffer is sent as urgent data | |||
259 | */ | |||
260 | void | |||
261 | sorecvoob(struct socket *so) | |||
262 | { | |||
263 | struct tcpcb *tp = sototcpcb(so)((so)->so_tcpcb); | |||
264 | ||||
265 | DEBUG_CALL("sorecvoob"); | |||
266 | DEBUG_ARG("so = %lx", (long)so); | |||
267 | ||||
268 | /* | |||
269 | * We take a guess at how much urgent data has arrived. | |||
270 | * In most situations, when urgent data arrives, the next | |||
271 | * read() should get all the urgent data. This guess will | |||
272 | * be wrong however if more data arrives just after the | |||
273 | * urgent data, or the read() doesn't return all the | |||
274 | * urgent data. | |||
275 | */ | |||
276 | soread(so); | |||
277 | tp->snd_up = tp->snd_una + so->so_snd.sb_cc; | |||
278 | tp->t_force = 1; | |||
279 | tcp_output(tp); | |||
280 | tp->t_force = 0; | |||
281 | } | |||
282 | ||||
283 | /* | |||
284 | * Send urgent data | |||
285 | * There's a lot duplicated code here, but... | |||
286 | */ | |||
287 | int | |||
288 | sosendoob(struct socket *so) | |||
289 | { | |||
290 | struct sbuf *sb = &so->so_rcv; | |||
291 | char buff[2048]; /* XXX Shouldn't be sending more oob data than this */ | |||
292 | ||||
293 | int n, len; | |||
294 | ||||
295 | DEBUG_CALL("sosendoob"); | |||
296 | DEBUG_ARG("so = %lx", (long)so); | |||
297 | DEBUG_ARG("sb->sb_cc = %d", sb->sb_cc); | |||
298 | ||||
299 | if (so->so_urgc > 2048) | |||
300 | so->so_urgc = 2048; /* XXXX */ | |||
301 | ||||
302 | if (sb->sb_rptr < sb->sb_wptr) { | |||
303 | /* We can send it directly */ | |||
304 | n = slirp_send(so, sb->sb_rptr, so->so_urgc, (MSG_OOBMSG_OOB)); /* |MSG_DONTWAIT)); */ | |||
305 | so->so_urgc -= n; | |||
306 | ||||
307 | DEBUG_MISC((dfd, " --- sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc)); | |||
308 | } else { | |||
309 | /* | |||
310 | * Since there's no sendv or sendtov like writev, | |||
311 | * we must copy all data to a linear buffer then | |||
312 | * send it all | |||
313 | */ | |||
314 | len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr; | |||
315 | if (len > so->so_urgc) len = so->so_urgc; | |||
316 | memcpy(buff, sb->sb_rptr, len); | |||
317 | so->so_urgc -= len; | |||
318 | if (so->so_urgc) { | |||
319 | n = sb->sb_wptr - sb->sb_data; | |||
320 | if (n > so->so_urgc) n = so->so_urgc; | |||
321 | memcpy((buff + len), sb->sb_data, n); | |||
322 | so->so_urgc -= n; | |||
323 | len += n; | |||
324 | } | |||
325 | n = slirp_send(so, buff, len, (MSG_OOBMSG_OOB)); /* |MSG_DONTWAIT)); */ | |||
326 | #ifdef DEBUG | |||
327 | if (n != len) | |||
328 | DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n")); | |||
329 | #endif | |||
330 | DEBUG_MISC((dfd, " ---2 sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc)); | |||
331 | } | |||
332 | ||||
333 | sb->sb_cc -= n; | |||
334 | sb->sb_rptr += n; | |||
335 | if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen)) | |||
336 | sb->sb_rptr -= sb->sb_datalen; | |||
337 | ||||
338 | return n; | |||
339 | } | |||
340 | ||||
341 | /* | |||
342 | * Write data from so_rcv to so's socket, | |||
343 | * updating all sbuf field as necessary | |||
344 | */ | |||
345 | int | |||
346 | sowrite(struct socket *so) | |||
347 | { | |||
348 | int n,nn; | |||
349 | struct sbuf *sb = &so->so_rcv; | |||
350 | int len = sb->sb_cc; | |||
351 | struct iovec iov[2]; | |||
352 | ||||
353 | DEBUG_CALL("sowrite"); | |||
354 | DEBUG_ARG("so = %lx", (long)so); | |||
355 | ||||
356 | if (so->so_urgc) { | |||
357 | sosendoob(so); | |||
358 | if (sb->sb_cc == 0) | |||
359 | return 0; | |||
360 | } | |||
361 | ||||
362 | /* | |||
363 | * No need to check if there's something to write, | |||
364 | * sowrite wouldn't have been called otherwise | |||
365 | */ | |||
366 | ||||
367 | iov[0].iov_base = sb->sb_rptr; | |||
368 | iov[1].iov_base = NULL((void*)0); | |||
369 | iov[1].iov_len = 0; | |||
370 | if (sb->sb_rptr < sb->sb_wptr) { | |||
371 | iov[0].iov_len = sb->sb_wptr - sb->sb_rptr; | |||
372 | /* Should never succeed, but... */ | |||
373 | if (iov[0].iov_len > len) iov[0].iov_len = len; | |||
374 | n = 1; | |||
375 | } else { | |||
376 | iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr; | |||
377 | if (iov[0].iov_len > len) iov[0].iov_len = len; | |||
378 | len -= iov[0].iov_len; | |||
379 | if (len) { | |||
380 | iov[1].iov_base = sb->sb_data; | |||
381 | iov[1].iov_len = sb->sb_wptr - sb->sb_data; | |||
382 | if (iov[1].iov_len > len) iov[1].iov_len = len; | |||
383 | n = 2; | |||
384 | } else | |||
385 | n = 1; | |||
386 | } | |||
387 | /* Check if there's urgent data to send, and if so, send it */ | |||
388 | ||||
389 | #ifdef HAVE_READV | |||
390 | nn = writev(so->s, (const struct iovec *)iov, n); | |||
391 | ||||
392 | DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn)); | |||
393 | #else | |||
394 | nn = slirp_send(so, iov[0].iov_base, iov[0].iov_len,0); | |||
395 | #endif | |||
396 | /* This should never happen, but people tell me it does *shrug* */ | |||
397 | if (nn < 0 && (errno(*__errno_location ()) == EAGAIN11 || errno(*__errno_location ()) == EINTR4)) | |||
398 | return 0; | |||
399 | ||||
400 | if (nn <= 0) { | |||
401 | DEBUG_MISC((dfd, " --- sowrite disconnected, so->so_state = %x, errno = %d\n", | |||
402 | so->so_state, errno)); | |||
403 | sofcantsendmore(so); | |||
404 | tcp_sockclosed(sototcpcb(so)((so)->so_tcpcb)); | |||
405 | return -1; | |||
406 | } | |||
407 | ||||
408 | #ifndef HAVE_READV | |||
409 | if (n == 2 && nn == iov[0].iov_len) { | |||
410 | int ret; | |||
411 | ret = slirp_send(so, iov[1].iov_base, iov[1].iov_len,0); | |||
412 | if (ret > 0) | |||
413 | nn += ret; | |||
414 | } | |||
415 | DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn)); | |||
416 | #endif | |||
417 | ||||
418 | /* Update sbuf */ | |||
419 | sb->sb_cc -= nn; | |||
420 | sb->sb_rptr += nn; | |||
421 | if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen)) | |||
422 | sb->sb_rptr -= sb->sb_datalen; | |||
423 | ||||
424 | /* | |||
425 | * If in DRAIN mode, and there's no more data, set | |||
426 | * it CANTSENDMORE | |||
427 | */ | |||
428 | if ((so->so_state & SS_FWDRAIN0x040) && sb->sb_cc == 0) | |||
429 | sofcantsendmore(so); | |||
430 | ||||
431 | return nn; | |||
432 | } | |||
433 | ||||
434 | /* | |||
435 | * recvfrom() a UDP socket | |||
436 | */ | |||
437 | void | |||
438 | sorecvfrom(struct socket *so) | |||
439 | { | |||
440 | struct sockaddr_in addr; | |||
441 | socklen_t addrlen = sizeof(struct sockaddr_in); | |||
442 | ||||
443 | DEBUG_CALL("sorecvfrom"); | |||
444 | DEBUG_ARG("so = %lx", (long)so); | |||
445 | ||||
446 | if (so->so_type == IPPROTO_ICMPIPPROTO_ICMP) { /* This is a "ping" reply */ | |||
447 | char buff[256]; | |||
448 | int len; | |||
449 | ||||
450 | len = recvfrom(so->s, buff, 256, 0, | |||
451 | (struct sockaddr *)&addr, &addrlen); | |||
452 | /* XXX Check if reply is "correct"? */ | |||
453 | ||||
454 | if(len == -1 || len == 0) { | |||
455 | u_char code=ICMP_UNREACH_PORT3; | |||
456 | ||||
457 | if(errno(*__errno_location ()) == EHOSTUNREACH113) code=ICMP_UNREACH_HOST1; | |||
458 | else if(errno(*__errno_location ()) == ENETUNREACH101) code=ICMP_UNREACH_NET0; | |||
459 | ||||
460 | DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n", | |||
461 | errno,strerror(errno))); | |||
462 | icmp_error(so->so_m, ICMP_UNREACH3,code, 0,strerror(errno(*__errno_location ()))); | |||
463 | } else { | |||
464 | icmp_reflect(so->so_m); | |||
465 | so->so_m = NULL((void*)0); /* Don't m_free() it again! */ | |||
466 | } | |||
467 | /* No need for this socket anymore, udp_detach it */ | |||
468 | udp_detach(so); | |||
469 | } else { /* A "normal" UDP packet */ | |||
470 | struct mbuf *m; | |||
471 | int len; | |||
472 | #ifdef _WIN32 | |||
473 | unsigned long n; | |||
474 | #else | |||
475 | int n; | |||
476 | #endif | |||
477 | ||||
478 | m = m_get(so->slirp); | |||
479 | if (!m) { | |||
480 | return; | |||
481 | } | |||
482 | m->m_data += IF_MAXLINKHDR(2 + 14 + 40); | |||
483 | ||||
484 | /* | |||
485 | * XXX Shouldn't FIONREAD packets destined for port 53, | |||
486 | * but I don't know the max packet size for DNS lookups | |||
487 | */ | |||
488 | len = M_FREEROOM(m)(((m->m_flags & 0x01)? (((m)->m_ext + (m)->m_size ) - (m)->m_data) : (((m)->m_dat + (m)->m_size) - (m) ->m_data)) - (m)->m_len); | |||
489 | /* if (so->so_fport != htons(53)) { */ | |||
490 | ioctlsocketioctl(so->s, FIONREAD0x541B, &n); | |||
491 | ||||
492 | if (n > len) { | |||
493 | n = (m->m_data - m->m_dat) + m->m_len + n + 1; | |||
494 | m_inc(m, n); | |||
495 | len = M_FREEROOM(m)(((m->m_flags & 0x01)? (((m)->m_ext + (m)->m_size ) - (m)->m_data) : (((m)->m_dat + (m)->m_size) - (m) ->m_data)) - (m)->m_len); | |||
496 | } | |||
497 | /* } */ | |||
498 | ||||
499 | m->m_len = recvfrom(so->s, m->m_data, len, 0, | |||
500 | (struct sockaddr *)&addr, &addrlen); | |||
501 | DEBUG_MISC((dfd, " did recvfrom %d, errno = %d-%s\n", | |||
502 | m->m_len, errno,strerror(errno))); | |||
503 | if(m->m_len<0) { | |||
504 | u_char code=ICMP_UNREACH_PORT3; | |||
505 | ||||
506 | if(errno(*__errno_location ()) == EHOSTUNREACH113) code=ICMP_UNREACH_HOST1; | |||
507 | else if(errno(*__errno_location ()) == ENETUNREACH101) code=ICMP_UNREACH_NET0; | |||
508 | ||||
509 | DEBUG_MISC((dfd," rx error, tx icmp ICMP_UNREACH:%i\n", code)); | |||
510 | icmp_error(so->so_m, ICMP_UNREACH3,code, 0,strerror(errno(*__errno_location ()))); | |||
511 | m_free(m); | |||
512 | } else { | |||
513 | /* | |||
514 | * Hack: domain name lookup will be used the most for UDP, | |||
515 | * and since they'll only be used once there's no need | |||
516 | * for the 4 minute (or whatever) timeout... So we time them | |||
517 | * out much quicker (10 seconds for now...) | |||
518 | */ | |||
519 | if (so->so_expire) { | |||
520 | if (so->so_fport == htons(53)) | |||
521 | so->so_expire = curtime + SO_EXPIREFAST10000; | |||
522 | else | |||
523 | so->so_expire = curtime + SO_EXPIRE240000; | |||
524 | } | |||
525 | ||||
526 | /* | |||
527 | * If this packet was destined for CTL_ADDR, | |||
528 | * make it look like that's where it came from, done by udp_output | |||
529 | */ | |||
530 | udp_output(so, m, &addr); | |||
531 | } /* rx error */ | |||
532 | } /* if ping packet */ | |||
533 | } | |||
534 | ||||
535 | /* | |||
536 | * sendto() a socket | |||
537 | */ | |||
538 | int | |||
539 | sosendto(struct socket *so, struct mbuf *m) | |||
540 | { | |||
541 | Slirp *slirp = so->slirp; | |||
542 | int ret; | |||
543 | struct sockaddr_in addr; | |||
544 | ||||
545 | DEBUG_CALL("sosendto"); | |||
546 | DEBUG_ARG("so = %lx", (long)so); | |||
547 | DEBUG_ARG("m = %lx", (long)m); | |||
548 | ||||
549 | addr.sin_family = AF_INET2; | |||
550 | if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) == | |||
551 | slirp->vnetwork_addr.s_addr) { | |||
552 | /* It's an alias */ | |||
553 | if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) { | |||
554 | if (get_dns_addr(&addr.sin_addr) < 0) | |||
555 | addr.sin_addr = loopback_addr; | |||
556 | } else { | |||
557 | addr.sin_addr = loopback_addr; | |||
558 | } | |||
559 | } else | |||
560 | addr.sin_addr = so->so_faddr; | |||
561 | addr.sin_port = so->so_fport; | |||
562 | ||||
563 | DEBUG_MISC((dfd, " sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%.16s\n", ntohs(addr.sin_port), inet_ntoa(addr.sin_addr))); | |||
564 | ||||
565 | /* Don't care what port we get */ | |||
566 | ret = sendto(so->s, m->m_data, m->m_len, 0, | |||
567 | (struct sockaddr *)&addr, sizeof (struct sockaddr)); | |||
568 | if (ret < 0) | |||
569 | return -1; | |||
570 | ||||
571 | /* | |||
572 | * Kill the socket if there's no reply in 4 minutes, | |||
573 | * but only if it's an expirable socket | |||
574 | */ | |||
575 | if (so->so_expire) | |||
576 | so->so_expire = curtime + SO_EXPIRE240000; | |||
577 | so->so_state &= SS_PERSISTENT_MASK0xf000; | |||
578 | so->so_state |= SS_ISFCONNECTED0x004; /* So that it gets select()ed */ | |||
579 | return 0; | |||
580 | } | |||
581 | ||||
582 | /* | |||
583 | * Listen for incoming TCP connections | |||
584 | */ | |||
585 | struct socket * | |||
586 | tcp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr, | |||
587 | u_int lport, int flags) | |||
588 | { | |||
589 | struct sockaddr_in addr; | |||
590 | struct socket *so; | |||
591 | int s, opt = 1; | |||
592 | socklen_t addrlen = sizeof(addr); | |||
593 | memset(&addr, 0, addrlen); | |||
594 | ||||
595 | DEBUG_CALL("tcp_listen"); | |||
596 | DEBUG_ARG("haddr = %x", haddr); | |||
597 | DEBUG_ARG("hport = %d", hport); | |||
598 | DEBUG_ARG("laddr = %x", laddr); | |||
599 | DEBUG_ARG("lport = %d", lport); | |||
600 | DEBUG_ARG("flags = %x", flags); | |||
601 | ||||
602 | so = socreate(slirp); | |||
603 | if (!so) { | |||
604 | return NULL((void*)0); | |||
605 | } | |||
606 | ||||
607 | /* Don't tcp_attach... we don't need so_snd nor so_rcv */ | |||
608 | if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL((void*)0)) { | |||
609 | free(so); | |||
610 | return NULL((void*)0); | |||
611 | } | |||
612 | insqueslirp_insque(so, &slirp->tcb); | |||
613 | ||||
614 | /* | |||
615 | * SS_FACCEPTONCE sockets must time out. | |||
616 | */ | |||
617 | if (flags & SS_FACCEPTONCE0x200) | |||
618 | so->so_tcpcb->t_timer[TCPT_KEEP2] = TCPTV_KEEP_INIT( 75*2)*2; | |||
619 | ||||
620 | so->so_state &= SS_PERSISTENT_MASK0xf000; | |||
621 | so->so_state |= (SS_FACCEPTCONN0x100 | flags); | |||
622 | so->so_lport = lport; /* Kept in network format */ | |||
623 | so->so_laddr.s_addr = laddr; /* Ditto */ | |||
624 | ||||
625 | addr.sin_family = AF_INET2; | |||
626 | addr.sin_addr.s_addr = haddr; | |||
627 | addr.sin_port = hport; | |||
628 | ||||
629 | if (((s = qemu_socket(AF_INET2,SOCK_STREAMSOCK_STREAM,0)) < 0) || | |||
630 | (socket_set_fast_reuse(s) < 0) || | |||
631 | (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) || | |||
632 | (listen(s,1) < 0)) { | |||
633 | int tmperrno = errno(*__errno_location ()); /* Don't clobber the real reason we failed */ | |||
634 | ||||
635 | close(s); | |||
636 | sofree(so); | |||
637 | /* Restore the real errno */ | |||
638 | #ifdef _WIN32 | |||
639 | WSASetLastError(tmperrno); | |||
640 | #else | |||
641 | errno(*__errno_location ()) = tmperrno; | |||
642 | #endif | |||
643 | return NULL((void*)0); | |||
644 | } | |||
645 | qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int))setsockopt(s, 1, 10, &opt, sizeof(int)); | |||
646 | ||||
647 | getsockname(s,(struct sockaddr *)&addr,&addrlen); | |||
648 | so->so_fport = addr.sin_port; | |||
649 | if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr) | |||
650 | so->so_faddr = slirp->vhost_addr; | |||
651 | else | |||
652 | so->so_faddr = addr.sin_addr; | |||
653 | ||||
654 | so->s = s; | |||
655 | return so; | |||
656 | } | |||
657 | ||||
658 | /* | |||
659 | * Various session state calls | |||
660 | * XXX Should be #define's | |||
661 | * The socket state stuff needs work, these often get call 2 or 3 | |||
662 | * times each when only 1 was needed | |||
663 | */ | |||
664 | void | |||
665 | soisfconnecting(struct socket *so) | |||
666 | { | |||
667 | so->so_state &= ~(SS_NOFDREF0x001|SS_ISFCONNECTED0x004|SS_FCANTRCVMORE0x008| | |||
668 | SS_FCANTSENDMORE0x010|SS_FWDRAIN0x040); | |||
669 | so->so_state |= SS_ISFCONNECTING0x002; /* Clobber other states */ | |||
670 | } | |||
671 | ||||
672 | void | |||
673 | soisfconnected(struct socket *so) | |||
674 | { | |||
675 | so->so_state &= ~(SS_ISFCONNECTING0x002|SS_FWDRAIN0x040|SS_NOFDREF0x001); | |||
676 | so->so_state |= SS_ISFCONNECTED0x004; /* Clobber other states */ | |||
677 | } | |||
678 | ||||
679 | static void | |||
680 | sofcantrcvmore(struct socket *so) | |||
681 | { | |||
682 | if ((so->so_state & SS_NOFDREF0x001) == 0) { | |||
683 | shutdown(so->s,0); | |||
684 | } | |||
685 | so->so_state &= ~(SS_ISFCONNECTING0x002); | |||
686 | if (so->so_state & SS_FCANTSENDMORE0x010) { | |||
687 | so->so_state &= SS_PERSISTENT_MASK0xf000; | |||
688 | so->so_state |= SS_NOFDREF0x001; /* Don't select it */ | |||
689 | } else { | |||
690 | so->so_state |= SS_FCANTRCVMORE0x008; | |||
691 | } | |||
692 | } | |||
693 | ||||
694 | static void | |||
695 | sofcantsendmore(struct socket *so) | |||
696 | { | |||
697 | if ((so->so_state & SS_NOFDREF0x001) == 0) { | |||
698 | shutdown(so->s,1); /* send FIN to fhost */ | |||
699 | } | |||
700 | so->so_state &= ~(SS_ISFCONNECTING0x002); | |||
701 | if (so->so_state & SS_FCANTRCVMORE0x008) { | |||
702 | so->so_state &= SS_PERSISTENT_MASK0xf000; | |||
703 | so->so_state |= SS_NOFDREF0x001; /* as above */ | |||
704 | } else { | |||
705 | so->so_state |= SS_FCANTSENDMORE0x010; | |||
706 | } | |||
707 | } | |||
708 | ||||
709 | /* | |||
710 | * Set write drain mode | |||
711 | * Set CANTSENDMORE once all data has been write()n | |||
712 | */ | |||
713 | void | |||
714 | sofwdrain(struct socket *so) | |||
715 | { | |||
716 | if (so->so_rcv.sb_cc) | |||
717 | so->so_state |= SS_FWDRAIN0x040; | |||
718 | else | |||
719 | sofcantsendmore(so); | |||
720 | } |