| 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 | } |