bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 1995 Danny Gasparovski. |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 3 | * |
| 4 | * Please read the file COPYRIGHT for the |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 5 | * terms and conditions of the copyright. |
| 6 | */ |
| 7 | |
Peter Maydell | 7df7482 | 2016-01-29 17:49:59 +0000 | [diff] [blame] | 8 | #include "qemu/osdep.h" |
aliguori | e1c5a2b | 2009-01-08 19:18:21 +0000 | [diff] [blame] | 9 | #include "qemu-common.h" |
Markus Armbruster | a9c9427 | 2016-06-22 19:11:19 +0200 | [diff] [blame] | 10 | #include "slirp.h" |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 11 | #include "ip_icmp.h" |
bellard | ec530c8 | 2006-04-25 22:36:06 +0000 | [diff] [blame] | 12 | #ifdef __sun__ |
| 13 | #include <sys/filio.h> |
| 14 | #endif |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 15 | |
blueswir1 | 9634d90 | 2007-10-26 19:01:16 +0000 | [diff] [blame] | 16 | static void sofcantrcvmore(struct socket *so); |
| 17 | static void sofcantsendmore(struct socket *so); |
| 18 | |
Guillaume Subiron | 8a87f12 | 2015-12-19 22:25:01 +0100 | [diff] [blame] | 19 | struct socket *solookup(struct socket **last, struct socket *head, |
| 20 | struct sockaddr_storage *lhost, struct sockaddr_storage *fhost) |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 21 | { |
Guillaume Subiron | a5fd24a | 2015-12-19 22:25:00 +0100 | [diff] [blame] | 22 | struct socket *so = *last; |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 23 | |
Guillaume Subiron | a5fd24a | 2015-12-19 22:25:00 +0100 | [diff] [blame] | 24 | /* Optimisation */ |
Guillaume Subiron | 8a87f12 | 2015-12-19 22:25:01 +0100 | [diff] [blame] | 25 | if (so != head && sockaddr_equal(&(so->lhost.ss), lhost) |
| 26 | && (!fhost || sockaddr_equal(&so->fhost.ss, fhost))) { |
Guillaume Subiron | a5fd24a | 2015-12-19 22:25:00 +0100 | [diff] [blame] | 27 | return so; |
| 28 | } |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 29 | |
Guillaume Subiron | a5fd24a | 2015-12-19 22:25:00 +0100 | [diff] [blame] | 30 | for (so = head->so_next; so != head; so = so->so_next) { |
Guillaume Subiron | 8a87f12 | 2015-12-19 22:25:01 +0100 | [diff] [blame] | 31 | if (sockaddr_equal(&(so->lhost.ss), lhost) |
| 32 | && (!fhost || sockaddr_equal(&so->fhost.ss, fhost))) { |
Guillaume Subiron | a5fd24a | 2015-12-19 22:25:00 +0100 | [diff] [blame] | 33 | *last = so; |
| 34 | return so; |
| 35 | } |
| 36 | } |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 37 | |
Guillaume Subiron | a5fd24a | 2015-12-19 22:25:00 +0100 | [diff] [blame] | 38 | return (struct socket *)NULL; |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 39 | } |
| 40 | |
| 41 | /* |
| 42 | * Create a new socket, initialise the fields |
| 43 | * It is the responsibility of the caller to |
| 44 | * insque() it into the correct linked-list |
| 45 | */ |
| 46 | struct socket * |
Jan Kiszka | 460fec6 | 2009-06-24 14:42:31 +0200 | [diff] [blame] | 47 | socreate(Slirp *slirp) |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 48 | { |
| 49 | struct socket *so; |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 50 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 51 | so = (struct socket *)malloc(sizeof(struct socket)); |
| 52 | if(so) { |
| 53 | memset(so, 0, sizeof(struct socket)); |
| 54 | so->so_state = SS_NOFDREF; |
| 55 | so->s = -1; |
Jan Kiszka | 460fec6 | 2009-06-24 14:42:31 +0200 | [diff] [blame] | 56 | so->slirp = slirp; |
Jan Kiszka | 7bd43ec | 2013-02-22 20:47:10 +0100 | [diff] [blame] | 57 | so->pollfds_idx = -1; |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 58 | } |
| 59 | return(so); |
| 60 | } |
| 61 | |
| 62 | /* |
| 63 | * remque and free a socket, clobber cache |
| 64 | */ |
| 65 | void |
blueswir1 | 511d2b1 | 2009-03-07 15:32:56 +0000 | [diff] [blame] | 66 | sofree(struct socket *so) |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 67 | { |
Jan Kiszka | 460fec6 | 2009-06-24 14:42:31 +0200 | [diff] [blame] | 68 | Slirp *slirp = so->slirp; |
Samuel Thibault | ea64d5f | 2016-11-13 23:54:27 +0100 | [diff] [blame] | 69 | struct mbuf *ifm; |
| 70 | |
| 71 | for (ifm = (struct mbuf *) slirp->if_fastq.qh_link; |
| 72 | (struct quehead *) ifm != &slirp->if_fastq; |
| 73 | ifm = ifm->ifq_next) { |
| 74 | if (ifm->ifq_so == so) { |
| 75 | ifm->ifq_so = NULL; |
| 76 | } |
| 77 | } |
| 78 | |
| 79 | for (ifm = (struct mbuf *) slirp->if_batchq.qh_link; |
| 80 | (struct quehead *) ifm != &slirp->if_batchq; |
| 81 | ifm = ifm->ifq_next) { |
| 82 | if (ifm->ifq_so == so) { |
| 83 | ifm->ifq_so = NULL; |
| 84 | } |
| 85 | } |
Jan Kiszka | 460fec6 | 2009-06-24 14:42:31 +0200 | [diff] [blame] | 86 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 87 | if (so->so_emu==EMU_RSH && so->extra) { |
| 88 | sofree(so->extra); |
| 89 | so->extra=NULL; |
| 90 | } |
Jan Kiszka | 460fec6 | 2009-06-24 14:42:31 +0200 | [diff] [blame] | 91 | if (so == slirp->tcp_last_so) { |
| 92 | slirp->tcp_last_so = &slirp->tcb; |
| 93 | } else if (so == slirp->udp_last_so) { |
| 94 | slirp->udp_last_so = &slirp->udb; |
Jan Kiszka | e6d43cf | 2011-07-20 12:20:18 +0200 | [diff] [blame] | 95 | } else if (so == slirp->icmp_last_so) { |
| 96 | slirp->icmp_last_so = &slirp->icmp; |
Jan Kiszka | 460fec6 | 2009-06-24 14:42:31 +0200 | [diff] [blame] | 97 | } |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 98 | m_free(so->so_m); |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 99 | |
| 100 | if(so->so_next && so->so_prev) |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 101 | remque(so); /* crashes if so is not in a queue */ |
| 102 | |
| 103 | free(so); |
| 104 | } |
| 105 | |
aliguori | e1c5a2b | 2009-01-08 19:18:21 +0000 | [diff] [blame] | 106 | size_t sopreprbuf(struct socket *so, struct iovec *iov, int *np) |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 107 | { |
aliguori | e1c5a2b | 2009-01-08 19:18:21 +0000 | [diff] [blame] | 108 | int n, lss, total; |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 109 | struct sbuf *sb = &so->so_snd; |
| 110 | int len = sb->sb_datalen - sb->sb_cc; |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 111 | int mss = so->so_tcpcb->t_maxseg; |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 112 | |
aliguori | e1c5a2b | 2009-01-08 19:18:21 +0000 | [diff] [blame] | 113 | DEBUG_CALL("sopreprbuf"); |
Stefan Weil | ecc804c | 2015-08-29 09:12:35 +0200 | [diff] [blame] | 114 | DEBUG_ARG("so = %p", so); |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 115 | |
aliguori | e1c5a2b | 2009-01-08 19:18:21 +0000 | [diff] [blame] | 116 | if (len <= 0) |
| 117 | return 0; |
| 118 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 119 | iov[0].iov_base = sb->sb_wptr; |
blueswir1 | 66029f6 | 2008-10-01 19:39:40 +0000 | [diff] [blame] | 120 | iov[1].iov_base = NULL; |
| 121 | iov[1].iov_len = 0; |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 122 | if (sb->sb_wptr < sb->sb_rptr) { |
| 123 | iov[0].iov_len = sb->sb_rptr - sb->sb_wptr; |
| 124 | /* Should never succeed, but... */ |
| 125 | if (iov[0].iov_len > len) |
| 126 | iov[0].iov_len = len; |
| 127 | if (iov[0].iov_len > mss) |
| 128 | iov[0].iov_len -= iov[0].iov_len%mss; |
| 129 | n = 1; |
| 130 | } else { |
| 131 | iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_wptr; |
| 132 | /* Should never succeed, but... */ |
| 133 | if (iov[0].iov_len > len) iov[0].iov_len = len; |
| 134 | len -= iov[0].iov_len; |
| 135 | if (len) { |
| 136 | iov[1].iov_base = sb->sb_data; |
| 137 | iov[1].iov_len = sb->sb_rptr - sb->sb_data; |
| 138 | if(iov[1].iov_len > len) |
| 139 | iov[1].iov_len = len; |
| 140 | total = iov[0].iov_len + iov[1].iov_len; |
| 141 | if (total > mss) { |
| 142 | lss = total%mss; |
| 143 | if (iov[1].iov_len > lss) { |
| 144 | iov[1].iov_len -= lss; |
| 145 | n = 2; |
| 146 | } else { |
| 147 | lss -= iov[1].iov_len; |
| 148 | iov[0].iov_len -= lss; |
| 149 | n = 1; |
| 150 | } |
| 151 | } else |
| 152 | n = 2; |
| 153 | } else { |
| 154 | if (iov[0].iov_len > mss) |
| 155 | iov[0].iov_len -= iov[0].iov_len%mss; |
| 156 | n = 1; |
| 157 | } |
| 158 | } |
aliguori | e1c5a2b | 2009-01-08 19:18:21 +0000 | [diff] [blame] | 159 | if (np) |
| 160 | *np = n; |
| 161 | |
| 162 | return iov[0].iov_len + (n - 1) * iov[1].iov_len; |
| 163 | } |
| 164 | |
| 165 | /* |
| 166 | * Read from so's socket into sb_snd, updating all relevant sbuf fields |
| 167 | * NOTE: This will only be called if it is select()ed for reading, so |
| 168 | * a read() of 0 (or less) means it's disconnected |
| 169 | */ |
| 170 | int |
blueswir1 | 511d2b1 | 2009-03-07 15:32:56 +0000 | [diff] [blame] | 171 | soread(struct socket *so) |
aliguori | e1c5a2b | 2009-01-08 19:18:21 +0000 | [diff] [blame] | 172 | { |
| 173 | int n, nn; |
| 174 | struct sbuf *sb = &so->so_snd; |
| 175 | struct iovec iov[2]; |
| 176 | |
| 177 | DEBUG_CALL("soread"); |
Stefan Weil | ecc804c | 2015-08-29 09:12:35 +0200 | [diff] [blame] | 178 | DEBUG_ARG("so = %p", so); |
aliguori | e1c5a2b | 2009-01-08 19:18:21 +0000 | [diff] [blame] | 179 | |
| 180 | /* |
| 181 | * No need to check if there's enough room to read. |
| 182 | * soread wouldn't have been called if there weren't |
| 183 | */ |
| 184 | sopreprbuf(so, iov, &n); |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 185 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 186 | #ifdef HAVE_READV |
| 187 | nn = readv(so->s, (struct iovec *)iov, n); |
| 188 | DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn)); |
| 189 | #else |
Blue Swirl | 00aa004 | 2011-07-23 20:04:29 +0000 | [diff] [blame] | 190 | nn = qemu_recv(so->s, iov[0].iov_base, iov[0].iov_len,0); |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 191 | #endif |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 192 | if (nn <= 0) { |
| 193 | if (nn < 0 && (errno == EINTR || errno == EAGAIN)) |
| 194 | return 0; |
| 195 | else { |
Edgar E. Iglesias | 27d92eb | 2016-04-06 22:04:43 -0700 | [diff] [blame] | 196 | int err; |
| 197 | socklen_t slen = sizeof err; |
| 198 | |
| 199 | err = errno; |
| 200 | if (nn == 0) { |
| 201 | getsockopt(so->s, SOL_SOCKET, SO_ERROR, |
| 202 | &err, &slen); |
| 203 | } |
| 204 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 205 | DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,strerror(errno))); |
| 206 | sofcantrcvmore(so); |
Edgar E. Iglesias | 27d92eb | 2016-04-06 22:04:43 -0700 | [diff] [blame] | 207 | |
Steven Luo | 6625d83 | 2016-04-06 22:04:55 -0700 | [diff] [blame] | 208 | if (err == ECONNRESET || err == ECONNREFUSED |
Edgar E. Iglesias | 27d92eb | 2016-04-06 22:04:43 -0700 | [diff] [blame] | 209 | || err == ENOTCONN || err == EPIPE) { |
| 210 | tcp_drop(sototcpcb(so), err); |
| 211 | } else { |
| 212 | tcp_sockclosed(sototcpcb(so)); |
| 213 | } |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 214 | return -1; |
| 215 | } |
| 216 | } |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 217 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 218 | #ifndef HAVE_READV |
| 219 | /* |
| 220 | * If there was no error, try and read the second time round |
| 221 | * We read again if n = 2 (ie, there's another part of the buffer) |
| 222 | * and we read as much as we could in the first read |
| 223 | * We don't test for <= 0 this time, because there legitimately |
| 224 | * might not be any more data (since the socket is non-blocking), |
| 225 | * a close will be detected on next iteration. |
Stefan Weil | cb8d4c8 | 2016-03-23 15:59:57 +0100 | [diff] [blame] | 226 | * A return of -1 won't (shouldn't) happen, since it didn't happen above |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 227 | */ |
bellard | 17444c9 | 2004-11-21 20:02:08 +0000 | [diff] [blame] | 228 | if (n == 2 && nn == iov[0].iov_len) { |
| 229 | int ret; |
Blue Swirl | 00aa004 | 2011-07-23 20:04:29 +0000 | [diff] [blame] | 230 | ret = qemu_recv(so->s, iov[1].iov_base, iov[1].iov_len,0); |
bellard | 17444c9 | 2004-11-21 20:02:08 +0000 | [diff] [blame] | 231 | if (ret > 0) |
| 232 | nn += ret; |
| 233 | } |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 234 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 235 | DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn)); |
| 236 | #endif |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 237 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 238 | /* Update fields */ |
| 239 | sb->sb_cc += nn; |
| 240 | sb->sb_wptr += nn; |
| 241 | if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen)) |
| 242 | sb->sb_wptr -= sb->sb_datalen; |
| 243 | return nn; |
| 244 | } |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 245 | |
aliguori | e1c5a2b | 2009-01-08 19:18:21 +0000 | [diff] [blame] | 246 | int soreadbuf(struct socket *so, const char *buf, int size) |
| 247 | { |
| 248 | int n, nn, copy = size; |
| 249 | struct sbuf *sb = &so->so_snd; |
| 250 | struct iovec iov[2]; |
| 251 | |
| 252 | DEBUG_CALL("soreadbuf"); |
Stefan Weil | ecc804c | 2015-08-29 09:12:35 +0200 | [diff] [blame] | 253 | DEBUG_ARG("so = %p", so); |
aliguori | e1c5a2b | 2009-01-08 19:18:21 +0000 | [diff] [blame] | 254 | |
| 255 | /* |
| 256 | * No need to check if there's enough room to read. |
| 257 | * soread wouldn't have been called if there weren't |
| 258 | */ |
| 259 | if (sopreprbuf(so, iov, &n) < size) |
| 260 | goto err; |
| 261 | |
| 262 | nn = MIN(iov[0].iov_len, copy); |
| 263 | memcpy(iov[0].iov_base, buf, nn); |
| 264 | |
| 265 | copy -= nn; |
| 266 | buf += nn; |
| 267 | |
| 268 | if (copy == 0) |
| 269 | goto done; |
| 270 | |
| 271 | memcpy(iov[1].iov_base, buf, copy); |
| 272 | |
| 273 | done: |
| 274 | /* Update fields */ |
| 275 | sb->sb_cc += size; |
| 276 | sb->sb_wptr += size; |
| 277 | if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen)) |
| 278 | sb->sb_wptr -= sb->sb_datalen; |
| 279 | return size; |
| 280 | err: |
| 281 | |
| 282 | sofcantrcvmore(so); |
| 283 | tcp_sockclosed(sototcpcb(so)); |
| 284 | fprintf(stderr, "soreadbuf buffer to small"); |
| 285 | return -1; |
| 286 | } |
| 287 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 288 | /* |
| 289 | * Get urgent data |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 290 | * |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 291 | * When the socket is created, we set it SO_OOBINLINE, |
| 292 | * so when OOB data arrives, we soread() it and everything |
| 293 | * in the send buffer is sent as urgent data |
| 294 | */ |
Steven Luo | bfb1ac1 | 2016-04-06 22:04:32 -0700 | [diff] [blame] | 295 | int |
blueswir1 | 511d2b1 | 2009-03-07 15:32:56 +0000 | [diff] [blame] | 296 | sorecvoob(struct socket *so) |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 297 | { |
| 298 | struct tcpcb *tp = sototcpcb(so); |
Steven Luo | bfb1ac1 | 2016-04-06 22:04:32 -0700 | [diff] [blame] | 299 | int ret; |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 300 | |
| 301 | DEBUG_CALL("sorecvoob"); |
Stefan Weil | ecc804c | 2015-08-29 09:12:35 +0200 | [diff] [blame] | 302 | DEBUG_ARG("so = %p", so); |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 303 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 304 | /* |
| 305 | * We take a guess at how much urgent data has arrived. |
| 306 | * In most situations, when urgent data arrives, the next |
| 307 | * read() should get all the urgent data. This guess will |
| 308 | * be wrong however if more data arrives just after the |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 309 | * urgent data, or the read() doesn't return all the |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 310 | * urgent data. |
| 311 | */ |
Steven Luo | bfb1ac1 | 2016-04-06 22:04:32 -0700 | [diff] [blame] | 312 | ret = soread(so); |
| 313 | if (ret > 0) { |
| 314 | tp->snd_up = tp->snd_una + so->so_snd.sb_cc; |
| 315 | tp->t_force = 1; |
| 316 | tcp_output(tp); |
| 317 | tp->t_force = 0; |
| 318 | } |
| 319 | |
| 320 | return ret; |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 321 | } |
| 322 | |
| 323 | /* |
| 324 | * Send urgent data |
| 325 | * There's a lot duplicated code here, but... |
| 326 | */ |
| 327 | int |
blueswir1 | 511d2b1 | 2009-03-07 15:32:56 +0000 | [diff] [blame] | 328 | sosendoob(struct socket *so) |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 329 | { |
| 330 | struct sbuf *sb = &so->so_rcv; |
| 331 | char buff[2048]; /* XXX Shouldn't be sending more oob data than this */ |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 332 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 333 | int n, len; |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 334 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 335 | DEBUG_CALL("sosendoob"); |
Stefan Weil | ecc804c | 2015-08-29 09:12:35 +0200 | [diff] [blame] | 336 | DEBUG_ARG("so = %p", so); |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 337 | DEBUG_ARG("sb->sb_cc = %d", sb->sb_cc); |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 338 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 339 | if (so->so_urgc > 2048) |
| 340 | so->so_urgc = 2048; /* XXXX */ |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 341 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 342 | if (sb->sb_rptr < sb->sb_wptr) { |
| 343 | /* We can send it directly */ |
aliguori | e1c5a2b | 2009-01-08 19:18:21 +0000 | [diff] [blame] | 344 | n = slirp_send(so, sb->sb_rptr, so->so_urgc, (MSG_OOB)); /* |MSG_DONTWAIT)); */ |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 345 | so->so_urgc -= n; |
ths | 3b46e62 | 2007-09-17 08:09:54 +0000 | [diff] [blame] | 346 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 347 | DEBUG_MISC((dfd, " --- sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc)); |
| 348 | } else { |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 349 | /* |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 350 | * Since there's no sendv or sendtov like writev, |
| 351 | * we must copy all data to a linear buffer then |
| 352 | * send it all |
| 353 | */ |
| 354 | len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr; |
| 355 | if (len > so->so_urgc) len = so->so_urgc; |
| 356 | memcpy(buff, sb->sb_rptr, len); |
| 357 | so->so_urgc -= len; |
| 358 | if (so->so_urgc) { |
| 359 | n = sb->sb_wptr - sb->sb_data; |
| 360 | if (n > so->so_urgc) n = so->so_urgc; |
| 361 | memcpy((buff + len), sb->sb_data, n); |
| 362 | so->so_urgc -= n; |
| 363 | len += n; |
| 364 | } |
aliguori | e1c5a2b | 2009-01-08 19:18:21 +0000 | [diff] [blame] | 365 | n = slirp_send(so, buff, len, (MSG_OOB)); /* |MSG_DONTWAIT)); */ |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 366 | #ifdef DEBUG |
| 367 | if (n != len) |
| 368 | DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n")); |
ths | 3b46e62 | 2007-09-17 08:09:54 +0000 | [diff] [blame] | 369 | #endif |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 370 | DEBUG_MISC((dfd, " ---2 sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc)); |
| 371 | } |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 372 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 373 | sb->sb_cc -= n; |
| 374 | sb->sb_rptr += n; |
| 375 | if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen)) |
| 376 | sb->sb_rptr -= sb->sb_datalen; |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 377 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 378 | return n; |
| 379 | } |
| 380 | |
| 381 | /* |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 382 | * Write data from so_rcv to so's socket, |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 383 | * updating all sbuf field as necessary |
| 384 | */ |
| 385 | int |
blueswir1 | 511d2b1 | 2009-03-07 15:32:56 +0000 | [diff] [blame] | 386 | sowrite(struct socket *so) |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 387 | { |
| 388 | int n,nn; |
| 389 | struct sbuf *sb = &so->so_rcv; |
| 390 | int len = sb->sb_cc; |
| 391 | struct iovec iov[2]; |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 392 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 393 | DEBUG_CALL("sowrite"); |
Stefan Weil | ecc804c | 2015-08-29 09:12:35 +0200 | [diff] [blame] | 394 | DEBUG_ARG("so = %p", so); |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 395 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 396 | if (so->so_urgc) { |
| 397 | sosendoob(so); |
| 398 | if (sb->sb_cc == 0) |
| 399 | return 0; |
| 400 | } |
| 401 | |
| 402 | /* |
| 403 | * No need to check if there's something to write, |
| 404 | * sowrite wouldn't have been called otherwise |
| 405 | */ |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 406 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 407 | iov[0].iov_base = sb->sb_rptr; |
blueswir1 | 66029f6 | 2008-10-01 19:39:40 +0000 | [diff] [blame] | 408 | iov[1].iov_base = NULL; |
| 409 | iov[1].iov_len = 0; |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 410 | if (sb->sb_rptr < sb->sb_wptr) { |
| 411 | iov[0].iov_len = sb->sb_wptr - sb->sb_rptr; |
| 412 | /* Should never succeed, but... */ |
| 413 | if (iov[0].iov_len > len) iov[0].iov_len = len; |
| 414 | n = 1; |
| 415 | } else { |
| 416 | iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr; |
| 417 | if (iov[0].iov_len > len) iov[0].iov_len = len; |
| 418 | len -= iov[0].iov_len; |
| 419 | if (len) { |
| 420 | iov[1].iov_base = sb->sb_data; |
| 421 | iov[1].iov_len = sb->sb_wptr - sb->sb_data; |
| 422 | if (iov[1].iov_len > len) iov[1].iov_len = len; |
| 423 | n = 2; |
| 424 | } else |
| 425 | n = 1; |
| 426 | } |
| 427 | /* Check if there's urgent data to send, and if so, send it */ |
| 428 | |
| 429 | #ifdef HAVE_READV |
| 430 | nn = writev(so->s, (const struct iovec *)iov, n); |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 431 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 432 | DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn)); |
| 433 | #else |
aliguori | e1c5a2b | 2009-01-08 19:18:21 +0000 | [diff] [blame] | 434 | nn = slirp_send(so, iov[0].iov_base, iov[0].iov_len,0); |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 435 | #endif |
| 436 | /* This should never happen, but people tell me it does *shrug* */ |
| 437 | if (nn < 0 && (errno == EAGAIN || errno == EINTR)) |
| 438 | return 0; |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 439 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 440 | if (nn <= 0) { |
| 441 | DEBUG_MISC((dfd, " --- sowrite disconnected, so->so_state = %x, errno = %d\n", |
| 442 | so->so_state, errno)); |
| 443 | sofcantsendmore(so); |
| 444 | tcp_sockclosed(sototcpcb(so)); |
| 445 | return -1; |
| 446 | } |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 447 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 448 | #ifndef HAVE_READV |
bellard | 3bc2175 | 2004-11-24 20:39:26 +0000 | [diff] [blame] | 449 | if (n == 2 && nn == iov[0].iov_len) { |
| 450 | int ret; |
aliguori | e1c5a2b | 2009-01-08 19:18:21 +0000 | [diff] [blame] | 451 | ret = slirp_send(so, iov[1].iov_base, iov[1].iov_len,0); |
bellard | 3bc2175 | 2004-11-24 20:39:26 +0000 | [diff] [blame] | 452 | if (ret > 0) |
| 453 | nn += ret; |
| 454 | } |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 455 | DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn)); |
| 456 | #endif |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 457 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 458 | /* Update sbuf */ |
| 459 | sb->sb_cc -= nn; |
| 460 | sb->sb_rptr += nn; |
| 461 | if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen)) |
| 462 | sb->sb_rptr -= sb->sb_datalen; |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 463 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 464 | /* |
| 465 | * If in DRAIN mode, and there's no more data, set |
| 466 | * it CANTSENDMORE |
| 467 | */ |
| 468 | if ((so->so_state & SS_FWDRAIN) && sb->sb_cc == 0) |
| 469 | sofcantsendmore(so); |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 470 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 471 | return nn; |
| 472 | } |
| 473 | |
| 474 | /* |
| 475 | * recvfrom() a UDP socket |
| 476 | */ |
| 477 | void |
blueswir1 | 511d2b1 | 2009-03-07 15:32:56 +0000 | [diff] [blame] | 478 | sorecvfrom(struct socket *so) |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 479 | { |
Guillaume Subiron | eae303f | 2015-12-19 22:24:58 +0100 | [diff] [blame] | 480 | struct sockaddr_storage addr; |
Guillaume Subiron | 5379229 | 2015-12-19 22:24:59 +0100 | [diff] [blame] | 481 | struct sockaddr_storage saddr, daddr; |
Guillaume Subiron | eae303f | 2015-12-19 22:24:58 +0100 | [diff] [blame] | 482 | socklen_t addrlen = sizeof(struct sockaddr_storage); |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 483 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 484 | DEBUG_CALL("sorecvfrom"); |
Stefan Weil | ecc804c | 2015-08-29 09:12:35 +0200 | [diff] [blame] | 485 | DEBUG_ARG("so = %p", so); |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 486 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 487 | if (so->so_type == IPPROTO_ICMP) { /* This is a "ping" reply */ |
| 488 | char buff[256]; |
| 489 | int len; |
ths | 3b46e62 | 2007-09-17 08:09:54 +0000 | [diff] [blame] | 490 | |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 491 | len = recvfrom(so->s, buff, 256, 0, |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 492 | (struct sockaddr *)&addr, &addrlen); |
| 493 | /* XXX Check if reply is "correct"? */ |
ths | 3b46e62 | 2007-09-17 08:09:54 +0000 | [diff] [blame] | 494 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 495 | if(len == -1 || len == 0) { |
| 496 | u_char code=ICMP_UNREACH_PORT; |
| 497 | |
| 498 | if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST; |
| 499 | else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET; |
ths | 3b46e62 | 2007-09-17 08:09:54 +0000 | [diff] [blame] | 500 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 501 | DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n", |
| 502 | errno,strerror(errno))); |
Yann Bordenave | de40abf | 2016-03-15 10:31:19 +0100 | [diff] [blame] | 503 | icmp_send_error(so->so_m, ICMP_UNREACH, code, 0, strerror(errno)); |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 504 | } else { |
| 505 | icmp_reflect(so->so_m); |
blueswir1 | 511d2b1 | 2009-03-07 15:32:56 +0000 | [diff] [blame] | 506 | so->so_m = NULL; /* Don't m_free() it again! */ |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 507 | } |
| 508 | /* No need for this socket anymore, udp_detach it */ |
| 509 | udp_detach(so); |
| 510 | } else { /* A "normal" UDP packet */ |
| 511 | struct mbuf *m; |
Blue Swirl | c5b76b3 | 2009-06-13 08:44:31 +0000 | [diff] [blame] | 512 | int len; |
| 513 | #ifdef _WIN32 |
| 514 | unsigned long n; |
| 515 | #else |
| 516 | int n; |
| 517 | #endif |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 518 | |
Jan Kiszka | 460fec6 | 2009-06-24 14:42:31 +0200 | [diff] [blame] | 519 | m = m_get(so->slirp); |
| 520 | if (!m) { |
| 521 | return; |
| 522 | } |
Guillaume Subiron | 98c6305 | 2016-03-15 10:31:20 +0100 | [diff] [blame] | 523 | switch (so->so_ffamily) { |
| 524 | case AF_INET: |
| 525 | m->m_data += IF_MAXLINKHDR + sizeof(struct udpiphdr); |
| 526 | break; |
| 527 | case AF_INET6: |
| 528 | m->m_data += IF_MAXLINKHDR + sizeof(struct ip6) |
| 529 | + sizeof(struct udphdr); |
| 530 | break; |
| 531 | default: |
| 532 | g_assert_not_reached(); |
| 533 | break; |
| 534 | } |
ths | 3b46e62 | 2007-09-17 08:09:54 +0000 | [diff] [blame] | 535 | |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 536 | /* |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 537 | * XXX Shouldn't FIONREAD packets destined for port 53, |
| 538 | * but I don't know the max packet size for DNS lookups |
| 539 | */ |
| 540 | len = M_FREEROOM(m); |
| 541 | /* if (so->so_fport != htons(53)) { */ |
bellard | 379ff53 | 2004-07-12 22:33:07 +0000 | [diff] [blame] | 542 | ioctlsocket(so->s, FIONREAD, &n); |
ths | 3b46e62 | 2007-09-17 08:09:54 +0000 | [diff] [blame] | 543 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 544 | if (n > len) { |
| 545 | n = (m->m_data - m->m_dat) + m->m_len + n + 1; |
| 546 | m_inc(m, n); |
| 547 | len = M_FREEROOM(m); |
| 548 | } |
| 549 | /* } */ |
ths | 3b46e62 | 2007-09-17 08:09:54 +0000 | [diff] [blame] | 550 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 551 | m->m_len = recvfrom(so->s, m->m_data, len, 0, |
| 552 | (struct sockaddr *)&addr, &addrlen); |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 553 | DEBUG_MISC((dfd, " did recvfrom %d, errno = %d-%s\n", |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 554 | m->m_len, errno,strerror(errno))); |
| 555 | if(m->m_len<0) { |
Guillaume Subiron | 15d62af | 2016-03-15 10:31:20 +0100 | [diff] [blame] | 556 | /* Report error as ICMP */ |
| 557 | switch (so->so_lfamily) { |
| 558 | uint8_t code; |
| 559 | case AF_INET: |
| 560 | code = ICMP_UNREACH_PORT; |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 561 | |
Guillaume Subiron | 15d62af | 2016-03-15 10:31:20 +0100 | [diff] [blame] | 562 | if (errno == EHOSTUNREACH) { |
| 563 | code = ICMP_UNREACH_HOST; |
| 564 | } else if (errno == ENETUNREACH) { |
| 565 | code = ICMP_UNREACH_NET; |
| 566 | } |
ths | 3b46e62 | 2007-09-17 08:09:54 +0000 | [diff] [blame] | 567 | |
Guillaume Subiron | 15d62af | 2016-03-15 10:31:20 +0100 | [diff] [blame] | 568 | DEBUG_MISC((dfd, " rx error, tx icmp ICMP_UNREACH:%i\n", code)); |
| 569 | icmp_send_error(so->so_m, ICMP_UNREACH, code, 0, strerror(errno)); |
| 570 | break; |
| 571 | case AF_INET6: |
| 572 | code = ICMP6_UNREACH_PORT; |
| 573 | |
| 574 | if (errno == EHOSTUNREACH) { |
| 575 | code = ICMP6_UNREACH_ADDRESS; |
| 576 | } else if (errno == ENETUNREACH) { |
| 577 | code = ICMP6_UNREACH_NO_ROUTE; |
| 578 | } |
| 579 | |
| 580 | DEBUG_MISC((dfd, " rx error, tx icmp6 ICMP_UNREACH:%i\n", code)); |
| 581 | icmp6_send_error(so->so_m, ICMP6_UNREACH, code); |
| 582 | break; |
| 583 | default: |
| 584 | g_assert_not_reached(); |
| 585 | break; |
| 586 | } |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 587 | m_free(m); |
| 588 | } else { |
| 589 | /* |
| 590 | * Hack: domain name lookup will be used the most for UDP, |
| 591 | * and since they'll only be used once there's no need |
| 592 | * for the 4 minute (or whatever) timeout... So we time them |
| 593 | * out much quicker (10 seconds for now...) |
| 594 | */ |
| 595 | if (so->so_expire) { |
| 596 | if (so->so_fport == htons(53)) |
| 597 | so->so_expire = curtime + SO_EXPIREFAST; |
| 598 | else |
| 599 | so->so_expire = curtime + SO_EXPIRE; |
| 600 | } |
| 601 | |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 602 | /* |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 603 | * If this packet was destined for CTL_ADDR, |
Guillaume Subiron | 5379229 | 2015-12-19 22:24:59 +0100 | [diff] [blame] | 604 | * make it look like that's where it came from |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 605 | */ |
Guillaume Subiron | 5379229 | 2015-12-19 22:24:59 +0100 | [diff] [blame] | 606 | saddr = addr; |
| 607 | sotranslate_in(so, &saddr); |
| 608 | daddr = so->lhost.ss; |
| 609 | |
Guillaume Subiron | eae303f | 2015-12-19 22:24:58 +0100 | [diff] [blame] | 610 | switch (so->so_ffamily) { |
| 611 | case AF_INET: |
Guillaume Subiron | 5379229 | 2015-12-19 22:24:59 +0100 | [diff] [blame] | 612 | udp_output(so, m, (struct sockaddr_in *) &saddr, |
| 613 | (struct sockaddr_in *) &daddr, |
| 614 | so->so_iptos); |
Guillaume Subiron | eae303f | 2015-12-19 22:24:58 +0100 | [diff] [blame] | 615 | break; |
Guillaume Subiron | 15d62af | 2016-03-15 10:31:20 +0100 | [diff] [blame] | 616 | case AF_INET6: |
| 617 | udp6_output(so, m, (struct sockaddr_in6 *) &saddr, |
| 618 | (struct sockaddr_in6 *) &daddr); |
| 619 | break; |
Guillaume Subiron | eae303f | 2015-12-19 22:24:58 +0100 | [diff] [blame] | 620 | default: |
Guillaume Subiron | 15d62af | 2016-03-15 10:31:20 +0100 | [diff] [blame] | 621 | g_assert_not_reached(); |
Guillaume Subiron | eae303f | 2015-12-19 22:24:58 +0100 | [diff] [blame] | 622 | break; |
| 623 | } |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 624 | } /* rx error */ |
| 625 | } /* if ping packet */ |
| 626 | } |
| 627 | |
| 628 | /* |
| 629 | * sendto() a socket |
| 630 | */ |
| 631 | int |
blueswir1 | 511d2b1 | 2009-03-07 15:32:56 +0000 | [diff] [blame] | 632 | sosendto(struct socket *so, struct mbuf *m) |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 633 | { |
| 634 | int ret; |
Guillaume Subiron | 5379229 | 2015-12-19 22:24:59 +0100 | [diff] [blame] | 635 | struct sockaddr_storage addr; |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 636 | |
| 637 | DEBUG_CALL("sosendto"); |
Stefan Weil | ecc804c | 2015-08-29 09:12:35 +0200 | [diff] [blame] | 638 | DEBUG_ARG("so = %p", so); |
| 639 | DEBUG_ARG("m = %p", m); |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 640 | |
Guillaume Subiron | 5379229 | 2015-12-19 22:24:59 +0100 | [diff] [blame] | 641 | addr = so->fhost.ss; |
| 642 | DEBUG_CALL(" sendto()ing)"); |
| 643 | sotranslate_out(so, &addr); |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 644 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 645 | /* Don't care what port we get */ |
| 646 | ret = sendto(so->s, m->m_data, m->m_len, 0, |
Samuel Thibault | 0d48dfe | 2016-04-28 18:53:08 +0200 | [diff] [blame] | 647 | (struct sockaddr *)&addr, sockaddr_size(&addr)); |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 648 | if (ret < 0) |
| 649 | return -1; |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 650 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 651 | /* |
| 652 | * Kill the socket if there's no reply in 4 minutes, |
| 653 | * but only if it's an expirable socket |
| 654 | */ |
| 655 | if (so->so_expire) |
| 656 | so->so_expire = curtime + SO_EXPIRE; |
Jan Kiszka | f932b6c | 2009-06-24 14:42:29 +0200 | [diff] [blame] | 657 | so->so_state &= SS_PERSISTENT_MASK; |
| 658 | so->so_state |= SS_ISFCONNECTED; /* So that it gets select()ed */ |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 659 | return 0; |
| 660 | } |
| 661 | |
| 662 | /* |
Jan Kiszka | 3c6a058 | 2009-06-24 14:42:28 +0200 | [diff] [blame] | 663 | * Listen for incoming TCP connections |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 664 | */ |
| 665 | struct socket * |
Stefan Weil | b6dce92 | 2010-07-22 22:15:23 +0200 | [diff] [blame] | 666 | tcp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr, |
Jan Kiszka | 460fec6 | 2009-06-24 14:42:31 +0200 | [diff] [blame] | 667 | u_int lport, int flags) |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 668 | { |
| 669 | struct sockaddr_in addr; |
| 670 | struct socket *so; |
balrog | 242acf3 | 2008-05-10 01:49:53 +0000 | [diff] [blame] | 671 | int s, opt = 1; |
| 672 | socklen_t addrlen = sizeof(addr); |
Juha Riihimäki | ab07b98 | 2010-04-13 09:16:55 +0300 | [diff] [blame] | 673 | memset(&addr, 0, addrlen); |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 674 | |
Jan Kiszka | 3c6a058 | 2009-06-24 14:42:28 +0200 | [diff] [blame] | 675 | DEBUG_CALL("tcp_listen"); |
Jan Kiszka | 9f34949 | 2009-06-24 14:42:29 +0200 | [diff] [blame] | 676 | DEBUG_ARG("haddr = %x", haddr); |
| 677 | DEBUG_ARG("hport = %d", hport); |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 678 | DEBUG_ARG("laddr = %x", laddr); |
| 679 | DEBUG_ARG("lport = %d", lport); |
| 680 | DEBUG_ARG("flags = %x", flags); |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 681 | |
Jan Kiszka | 460fec6 | 2009-06-24 14:42:31 +0200 | [diff] [blame] | 682 | so = socreate(slirp); |
| 683 | if (!so) { |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 684 | return NULL; |
| 685 | } |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 686 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 687 | /* Don't tcp_attach... we don't need so_snd nor so_rcv */ |
| 688 | if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) { |
| 689 | free(so); |
| 690 | return NULL; |
| 691 | } |
Jan Kiszka | 460fec6 | 2009-06-24 14:42:31 +0200 | [diff] [blame] | 692 | insque(so, &slirp->tcb); |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 693 | |
| 694 | /* |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 695 | * SS_FACCEPTONCE sockets must time out. |
| 696 | */ |
| 697 | if (flags & SS_FACCEPTONCE) |
| 698 | so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT*2; |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 699 | |
Jan Kiszka | f932b6c | 2009-06-24 14:42:29 +0200 | [diff] [blame] | 700 | so->so_state &= SS_PERSISTENT_MASK; |
| 701 | so->so_state |= (SS_FACCEPTCONN | flags); |
Guillaume Subiron | eae303f | 2015-12-19 22:24:58 +0100 | [diff] [blame] | 702 | so->so_lfamily = AF_INET; |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 703 | so->so_lport = lport; /* Kept in network format */ |
| 704 | so->so_laddr.s_addr = laddr; /* Ditto */ |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 705 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 706 | addr.sin_family = AF_INET; |
Jan Kiszka | 3c6a058 | 2009-06-24 14:42:28 +0200 | [diff] [blame] | 707 | addr.sin_addr.s_addr = haddr; |
| 708 | addr.sin_port = hport; |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 709 | |
Kevin Wolf | 40ff6d7 | 2009-12-02 12:24:42 +0100 | [diff] [blame] | 710 | if (((s = qemu_socket(AF_INET,SOCK_STREAM,0)) < 0) || |
Sebastian Ottlik | aad1239 | 2013-10-02 12:23:15 +0200 | [diff] [blame] | 711 | (socket_set_fast_reuse(s) < 0) || |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 712 | (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) || |
| 713 | (listen(s,1) < 0)) { |
| 714 | int tmperrno = errno; /* Don't clobber the real reason we failed */ |
ths | 3b46e62 | 2007-09-17 08:09:54 +0000 | [diff] [blame] | 715 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 716 | close(s); |
| 717 | sofree(so); |
| 718 | /* Restore the real errno */ |
bellard | 02d2c54 | 2004-10-07 23:27:35 +0000 | [diff] [blame] | 719 | #ifdef _WIN32 |
| 720 | WSASetLastError(tmperrno); |
| 721 | #else |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 722 | errno = tmperrno; |
bellard | 02d2c54 | 2004-10-07 23:27:35 +0000 | [diff] [blame] | 723 | #endif |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 724 | return NULL; |
| 725 | } |
Stefan Weil | 9957fc7 | 2013-03-08 19:58:32 +0100 | [diff] [blame] | 726 | qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 727 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 728 | getsockname(s,(struct sockaddr *)&addr,&addrlen); |
Guillaume Subiron | eae303f | 2015-12-19 22:24:58 +0100 | [diff] [blame] | 729 | so->so_ffamily = AF_INET; |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 730 | so->so_fport = addr.sin_port; |
| 731 | if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr) |
Jan Kiszka | 460fec6 | 2009-06-24 14:42:31 +0200 | [diff] [blame] | 732 | so->so_faddr = slirp->vhost_addr; |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 733 | else |
| 734 | so->so_faddr = addr.sin_addr; |
| 735 | |
| 736 | so->s = s; |
| 737 | return so; |
| 738 | } |
| 739 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 740 | /* |
| 741 | * Various session state calls |
| 742 | * XXX Should be #define's |
| 743 | * The socket state stuff needs work, these often get call 2 or 3 |
| 744 | * times each when only 1 was needed |
| 745 | */ |
| 746 | void |
blueswir1 | 511d2b1 | 2009-03-07 15:32:56 +0000 | [diff] [blame] | 747 | soisfconnecting(struct socket *so) |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 748 | { |
| 749 | so->so_state &= ~(SS_NOFDREF|SS_ISFCONNECTED|SS_FCANTRCVMORE| |
| 750 | SS_FCANTSENDMORE|SS_FWDRAIN); |
| 751 | so->so_state |= SS_ISFCONNECTING; /* Clobber other states */ |
| 752 | } |
| 753 | |
| 754 | void |
blueswir1 | 511d2b1 | 2009-03-07 15:32:56 +0000 | [diff] [blame] | 755 | soisfconnected(struct socket *so) |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 756 | { |
| 757 | so->so_state &= ~(SS_ISFCONNECTING|SS_FWDRAIN|SS_NOFDREF); |
| 758 | so->so_state |= SS_ISFCONNECTED; /* Clobber other states */ |
| 759 | } |
| 760 | |
blueswir1 | 9634d90 | 2007-10-26 19:01:16 +0000 | [diff] [blame] | 761 | static void |
| 762 | sofcantrcvmore(struct socket *so) |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 763 | { |
| 764 | if ((so->so_state & SS_NOFDREF) == 0) { |
| 765 | shutdown(so->s,0); |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 766 | } |
| 767 | so->so_state &= ~(SS_ISFCONNECTING); |
Jan Kiszka | f932b6c | 2009-06-24 14:42:29 +0200 | [diff] [blame] | 768 | if (so->so_state & SS_FCANTSENDMORE) { |
| 769 | so->so_state &= SS_PERSISTENT_MASK; |
| 770 | so->so_state |= SS_NOFDREF; /* Don't select it */ |
| 771 | } else { |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 772 | so->so_state |= SS_FCANTRCVMORE; |
Jan Kiszka | f932b6c | 2009-06-24 14:42:29 +0200 | [diff] [blame] | 773 | } |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 774 | } |
| 775 | |
blueswir1 | 9634d90 | 2007-10-26 19:01:16 +0000 | [diff] [blame] | 776 | static void |
| 777 | sofcantsendmore(struct socket *so) |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 778 | { |
| 779 | if ((so->so_state & SS_NOFDREF) == 0) { |
bellard | 02d2c54 | 2004-10-07 23:27:35 +0000 | [diff] [blame] | 780 | shutdown(so->s,1); /* send FIN to fhost */ |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 781 | } |
| 782 | so->so_state &= ~(SS_ISFCONNECTING); |
Jan Kiszka | f932b6c | 2009-06-24 14:42:29 +0200 | [diff] [blame] | 783 | if (so->so_state & SS_FCANTRCVMORE) { |
| 784 | so->so_state &= SS_PERSISTENT_MASK; |
| 785 | so->so_state |= SS_NOFDREF; /* as above */ |
| 786 | } else { |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 787 | so->so_state |= SS_FCANTSENDMORE; |
Jan Kiszka | f932b6c | 2009-06-24 14:42:29 +0200 | [diff] [blame] | 788 | } |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 789 | } |
| 790 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 791 | /* |
| 792 | * Set write drain mode |
| 793 | * Set CANTSENDMORE once all data has been write()n |
| 794 | */ |
| 795 | void |
blueswir1 | 511d2b1 | 2009-03-07 15:32:56 +0000 | [diff] [blame] | 796 | sofwdrain(struct socket *so) |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 797 | { |
| 798 | if (so->so_rcv.sb_cc) |
| 799 | so->so_state |= SS_FWDRAIN; |
| 800 | else |
| 801 | sofcantsendmore(so); |
| 802 | } |
Guillaume Subiron | 5379229 | 2015-12-19 22:24:59 +0100 | [diff] [blame] | 803 | |
| 804 | /* |
| 805 | * Translate addr in host addr when it is a virtual address |
| 806 | */ |
| 807 | void sotranslate_out(struct socket *so, struct sockaddr_storage *addr) |
| 808 | { |
| 809 | Slirp *slirp = so->slirp; |
| 810 | struct sockaddr_in *sin = (struct sockaddr_in *)addr; |
Guillaume Subiron | 05061d8 | 2016-03-15 10:31:22 +0100 | [diff] [blame] | 811 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr; |
Guillaume Subiron | 5379229 | 2015-12-19 22:24:59 +0100 | [diff] [blame] | 812 | |
| 813 | switch (addr->ss_family) { |
| 814 | case AF_INET: |
| 815 | if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) == |
| 816 | slirp->vnetwork_addr.s_addr) { |
| 817 | /* It's an alias */ |
| 818 | if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) { |
| 819 | if (get_dns_addr(&sin->sin_addr) < 0) { |
| 820 | sin->sin_addr = loopback_addr; |
| 821 | } |
| 822 | } else { |
| 823 | sin->sin_addr = loopback_addr; |
| 824 | } |
| 825 | } |
| 826 | |
| 827 | DEBUG_MISC((dfd, " addr.sin_port=%d, " |
| 828 | "addr.sin_addr.s_addr=%.16s\n", |
| 829 | ntohs(sin->sin_port), inet_ntoa(sin->sin_addr))); |
| 830 | break; |
| 831 | |
Guillaume Subiron | 05061d8 | 2016-03-15 10:31:22 +0100 | [diff] [blame] | 832 | case AF_INET6: |
| 833 | if (in6_equal_net(&so->so_faddr6, &slirp->vprefix_addr6, |
| 834 | slirp->vprefix_len)) { |
| 835 | if (in6_equal(&so->so_faddr6, &slirp->vnameserver_addr6)) { |
Samuel Thibault | ef763fa | 2016-03-20 15:16:21 +0100 | [diff] [blame] | 836 | uint32_t scope_id; |
| 837 | if (get_dns6_addr(&sin6->sin6_addr, &scope_id) >= 0) { |
| 838 | sin6->sin6_scope_id = scope_id; |
| 839 | } else { |
Guillaume Subiron | 05061d8 | 2016-03-15 10:31:22 +0100 | [diff] [blame] | 840 | sin6->sin6_addr = in6addr_loopback; |
Samuel Thibault | 1d17654 | 2016-03-20 15:09:09 +0100 | [diff] [blame] | 841 | } |
Guillaume Subiron | 05061d8 | 2016-03-15 10:31:22 +0100 | [diff] [blame] | 842 | } else { |
| 843 | sin6->sin6_addr = in6addr_loopback; |
| 844 | } |
| 845 | } |
| 846 | break; |
| 847 | |
Guillaume Subiron | 5379229 | 2015-12-19 22:24:59 +0100 | [diff] [blame] | 848 | default: |
| 849 | break; |
| 850 | } |
| 851 | } |
| 852 | |
| 853 | void sotranslate_in(struct socket *so, struct sockaddr_storage *addr) |
| 854 | { |
| 855 | Slirp *slirp = so->slirp; |
| 856 | struct sockaddr_in *sin = (struct sockaddr_in *)addr; |
Guillaume Subiron | 05061d8 | 2016-03-15 10:31:22 +0100 | [diff] [blame] | 857 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr; |
Guillaume Subiron | 5379229 | 2015-12-19 22:24:59 +0100 | [diff] [blame] | 858 | |
| 859 | switch (addr->ss_family) { |
| 860 | case AF_INET: |
| 861 | if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) == |
| 862 | slirp->vnetwork_addr.s_addr) { |
| 863 | uint32_t inv_mask = ~slirp->vnetwork_mask.s_addr; |
| 864 | |
| 865 | if ((so->so_faddr.s_addr & inv_mask) == inv_mask) { |
| 866 | sin->sin_addr = slirp->vhost_addr; |
| 867 | } else if (sin->sin_addr.s_addr == loopback_addr.s_addr || |
| 868 | so->so_faddr.s_addr != slirp->vhost_addr.s_addr) { |
| 869 | sin->sin_addr = so->so_faddr; |
| 870 | } |
| 871 | } |
| 872 | break; |
| 873 | |
Guillaume Subiron | 05061d8 | 2016-03-15 10:31:22 +0100 | [diff] [blame] | 874 | case AF_INET6: |
| 875 | if (in6_equal_net(&so->so_faddr6, &slirp->vprefix_addr6, |
| 876 | slirp->vprefix_len)) { |
| 877 | if (in6_equal(&sin6->sin6_addr, &in6addr_loopback) |
| 878 | || !in6_equal(&so->so_faddr6, &slirp->vhost_addr6)) { |
| 879 | sin6->sin6_addr = so->so_faddr6; |
| 880 | } |
| 881 | } |
| 882 | break; |
| 883 | |
Guillaume Subiron | 5379229 | 2015-12-19 22:24:59 +0100 | [diff] [blame] | 884 | default: |
| 885 | break; |
| 886 | } |
| 887 | } |
| 888 | |
| 889 | /* |
| 890 | * Translate connections from localhost to the real hostname |
| 891 | */ |
| 892 | void sotranslate_accept(struct socket *so) |
| 893 | { |
| 894 | Slirp *slirp = so->slirp; |
| 895 | |
| 896 | switch (so->so_ffamily) { |
| 897 | case AF_INET: |
| 898 | if (so->so_faddr.s_addr == INADDR_ANY || |
| 899 | (so->so_faddr.s_addr & loopback_mask) == |
| 900 | (loopback_addr.s_addr & loopback_mask)) { |
| 901 | so->so_faddr = slirp->vhost_addr; |
| 902 | } |
| 903 | break; |
| 904 | |
Guillaume Subiron | 05061d8 | 2016-03-15 10:31:22 +0100 | [diff] [blame] | 905 | case AF_INET6: |
| 906 | if (in6_equal(&so->so_faddr6, &in6addr_any) || |
| 907 | in6_equal(&so->so_faddr6, &in6addr_loopback)) { |
| 908 | so->so_faddr6 = slirp->vhost_addr6; |
| 909 | } |
| 910 | break; |
| 911 | |
Guillaume Subiron | 5379229 | 2015-12-19 22:24:59 +0100 | [diff] [blame] | 912 | default: |
| 913 | break; |
| 914 | } |
| 915 | } |