Update upstream source from tag 'upstream/0.4.3'
Update to upstream version '0.4.3'
with Debian dir 3ac6c9026e77abcadd0fe9cb4544ce5c06408cd2
Reinhard Tartler
4 years ago
0 | name: Main | |
1 | on: [push, pull_request] | |
2 | jobs: | |
3 | test-main: | |
4 | runs-on: ubuntu-latest | |
5 | steps: | |
6 | - uses: actions/checkout@v1 | |
7 | - run: docker build -t slirp4netns-tests -f Dockerfile.tests . | |
8 | - run: docker run --rm --privileged slirp4netns-tests | |
9 | test-build: | |
10 | runs-on: ubuntu-latest | |
11 | steps: | |
12 | - uses: actions/checkout@v1 | |
13 | - run: DOCKER_BUILDKIT=1 docker build -f Dockerfile.buildtests . | |
14 | artifact: | |
15 | runs-on: ubuntu-latest | |
16 | steps: | |
17 | - uses: actions/checkout@v1 | |
18 | - run: DOCKER_BUILDKIT=1 docker build -o /tmp/artifact --target artifact -f Dockerfile.buildtests . | |
19 | - run: (cd /tmp/artifact; sha256sum *) | |
20 | - uses: actions/upload-artifact@v1 | |
21 | with: | |
22 | name: slirp4netns-x86_64 | |
23 | path: /tmp/artifact/slirp4netns |
0 | name: Release | |
1 | on: | |
2 | push: | |
3 | tags: | |
4 | - 'v*' | |
5 | ||
6 | jobs: | |
7 | release: | |
8 | runs-on: ubuntu-latest | |
9 | steps: | |
10 | - uses: actions/checkout@v1 | |
11 | - run: DOCKER_BUILDKIT=1 docker build -o /tmp/artifact --target artifact -f Dockerfile.buildtests . | |
12 | - run: (cd /tmp/artifact; sha256sum *) | |
13 | - uses: actions/create-release@v1 | |
14 | id: create_release | |
15 | env: | |
16 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
17 | with: | |
18 | tag_name: ${{ github.ref }} | |
19 | release_name: ${{ github.ref }} | |
20 | draft: true | |
21 | - uses: actions/upload-release-asset@v1.0.1 | |
22 | env: | |
23 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
24 | with: | |
25 | upload_url: ${{ steps.create_release.outputs.upload_url }} | |
26 | asset_path: /tmp/artifact/slirp4netns | |
27 | asset_name: slirp4netns-x86_64 | |
28 | asset_content_type: application/octet-stream |
0 | dist: trusty | |
1 | sudo: required | |
2 | ||
3 | services: | |
4 | - docker | |
5 | ||
6 | script: | |
7 | - docker build -t slirp4netns-tests -f Dockerfile.tests . | |
8 | - docker run --security-opt seccomp="unconfined" --rm -v /dev:/dev slirp4netns-tests | |
9 | - docker build -q -f Dockerfile.buildtests . |
43 | 43 | FROM buildtest-opensuse151-common AS buildtest-opensuse151-dynamic |
44 | 44 | RUN ./configure && make && cp -f slirp4netns / |
45 | 45 | |
46 | # artifact for GitHub actions | |
47 | FROM scratch AS artifact | |
48 | COPY --from=buildtest-alpine310-static /slirp4netns /slirp4netns | |
49 | ||
46 | 50 | FROM scratch AS buildtest-final-stage |
47 | 51 | COPY --from=buildtest-alpine310-static /slirp4netns /buildtest-alpine310-static |
48 | 52 | COPY --from=buildtest-ubuntu1804-dynamic /slirp4netns /buildtest-ubuntu1804-dynamic |
1 | 1 | |
2 | 2 | [Org] |
3 | 3 | |
4 | # Approvers (aka Core Maintainers) approve pull requests. | |
4 | # Approvers (aka Core Maintainers) approve pull requests and ship releases. | |
5 | 5 | # GitHub Team: rootless-containers/slirp4netns-approvers |
6 | # | |
7 | # An approver may approve PRs and ship releases without waiting for LGTMs from other approvers. | |
8 | # However, the approver should try to get LGTMs from other approvers for significant changes. | |
9 | # | |
10 | # Release guide (since v0.4.3): | |
11 | # 1. Bump up the version string to `vX.Y.Z` (or `vX.Y.Z-beta.W`) in `configure.ac`. | |
12 | # 2. `git commit -a -s -m vX.Y.Z` | |
13 | # 3. Bump up the version string to `vX.Y.Z+dev` (or `vX.Y.Z-beta.W`+dev) in `configure.ac`. | |
14 | # 4. `git commit -a -s -m vX.Y.Z+dev` | |
15 | # 5. Open a PR and merge it. | |
16 | # 6. Create a tag `v.X.Y.Z` for the `vX.Y.Z` commit, and push the tag to the upstream: `git push upstream vX.Y.Z` | |
17 | # 7. GitHub Actions automatically ships a draft release with a statically compiled binary: https://github.com/rootless-containers/slirp4netns/releases | |
18 | # If it fails, check the GitHub Actions log: https://github.com/rootless-containers/slirp4netns/actions?query=workflow%3ARelease | |
19 | # 8. Add release notes to the draft release and ship the release. | |
6 | 20 | [Org.Approvers] |
7 | 21 | people = [ |
8 | 22 | "akihirosuda", |
15 | 15 | api.h \ |
16 | 16 | sandbox.h \ |
17 | 17 | seccompfilter.h \ |
18 | tests/slirp4netns-no-unmount.sh \ | |
18 | 19 | vendor/libslirp/COPYRIGHT \ |
19 | 20 | vendor/libslirp/README.md \ |
20 | 21 | vendor/libslirp/src/bootp.h \ |
81 | 82 | vendor/libslirp/src/vmstate.c |
82 | 83 | |
83 | 84 | # define specific commit if git available or it was replaced during git-archive creation |
84 | COMMIT := $(shell V=4d38845e2e311b684fc8d1c775c725bfcd5ddc27 ; \ | |
85 | COMMIT := $(shell V=2244b9b6461afeccad1678fac3d6e478c28b4ad6 ; \ | |
85 | 86 | expr match "$$V" ormat: >/dev/null \ |
86 | 87 | && (cd "$$abs_srcdir" && [ -d .git ] && git describe --always --abbrev=0 --dirty --exclude=\* || echo unknown) \ |
87 | 88 | || echo "$$V" ) |
20 | 20 | } |
21 | 21 | memset(&addr, 0, sizeof(addr)); |
22 | 22 | addr.sun_family = AF_UNIX; |
23 | if (strlen(api_socket) >= sizeof(addr.sun_path)) { | |
24 | fprintf(stderr, "the specified API socket path is too long (>= %lu)\n", | |
25 | sizeof(addr.sun_path)); | |
26 | return -1; | |
27 | } | |
23 | 28 | strncpy(addr.sun_path, api_socket, sizeof(addr.sun_path) - 1); |
24 | 29 | if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { |
25 | 30 | perror("api_bindlisten: bind"); |
0 | 0 | AC_PREREQ([2.69]) |
1 | AC_INIT([slirp4netns], [0.4.1], [https://github.com/rootless-containers/slirp4netns/issues]) | |
1 | AC_INIT([slirp4netns], [0.4.3], [https://github.com/rootless-containers/slirp4netns/issues]) | |
2 | 2 | AC_CONFIG_SRCDIR([main.c]) |
3 | 3 | AC_CONFIG_HEADERS([config.h]) |
4 | 4 |
15 | 15 | { |
16 | 16 | int ret; |
17 | 17 | |
18 | ret = mount("", from, "", MS_SLAVE | MS_REC, NULL); | |
19 | if (ret < 0 && errno != EINVAL) { | |
20 | fprintf(stderr, "cannot make mount propagation slave %s\n", from); | |
21 | return ret; | |
22 | } | |
18 | 23 | ret = mount(from, to, "", |
19 | 24 | MS_BIND | MS_REC | MS_SLAVE | MS_NOSUID | MS_NODEV | MS_NOEXEC, |
20 | 25 | NULL); |
21 | 26 | if (ret < 0) { |
22 | 27 | fprintf(stderr, "cannot bind mount %s to %s\n", from, to); |
28 | return ret; | |
29 | } | |
30 | ret = mount("", to, "", MS_SLAVE | MS_REC, NULL); | |
31 | if (ret < 0) { | |
32 | fprintf(stderr, "cannot make mount propagation slave %s\n", to); | |
23 | 33 | return ret; |
24 | 34 | } |
25 | 35 | ret = mount(from, to, "", |
123 | 133 | |
124 | 134 | ret = mount("tmpfs", "/", "tmpfs", MS_REMOUNT | MS_RDONLY, "size=0k"); |
125 | 135 | if (ret < 0) { |
126 | fprintf(stderr, "cannot mount tmpfs on /tmp\n"); | |
127 | return ret; | |
136 | fprintf(stderr, "cannot remount / as read-only\n"); | |
137 | /* error is negligible (#163) */ | |
128 | 138 | } |
129 | 139 | |
130 | 140 | ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); |
0 | #!/bin/bash | |
1 | set -xeuo pipefail | |
2 | ||
3 | . $(dirname $0)/common.sh | |
4 | ||
5 | # it is a part of test-slirp4netns.sh | |
6 | # must run in a new mount namespace | |
7 | ||
8 | mount -t tmpfs tmpfs /run | |
9 | mkdir /run/foo | |
10 | mount -t tmpfs tmpfs /run/foo | |
11 | mount --make-rshared /run | |
12 | ||
13 | unshare -n sleep infinity & | |
14 | child=$! | |
15 | ||
16 | wait_for_network_namespace $child | |
17 | ||
18 | ./slirp4netns --enable-sandbox --netns-type=path /proc/$child/ns/net tun11 & | |
19 | slirp_pid=$! | |
20 | ||
21 | function cleanup { | |
22 | kill -9 $child $slirp_pid | |
23 | } | |
24 | trap cleanup EXIT | |
25 | ||
26 | wait_for_network_device $child tun11 | |
27 | ||
28 | findmnt /run/foo |
9 | 9 | |
10 | 10 | tmpdir=$(mktemp -d /tmp/slirp4netns-bench.XXXXXXXXXX) |
11 | 11 | apisocket=${tmpdir}/slirp4netns.sock |
12 | apisocketlongpath=${tmpdir}/slirp4netns-TOO-LONG-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.sock | |
13 | ||
14 | if slirp4netns -c $child --api-socket $apisocketlongpath tun11; then | |
15 | echo "expected failure with apisocket path too long" >&2 | |
16 | kill -9 $child | |
17 | rm -rf $tmpdir | |
18 | exit 1 | |
19 | fi | |
20 | ||
12 | 21 | slirp4netns -c $child --api-socket $apisocket tun11 & |
13 | 22 | slirp_pid=$! |
14 | 23 |
66 | 66 | |
67 | 67 | nsenter --preserve-credentials -U -n --target=$child ip -a netconf | grep tun11 |
68 | 68 | nsenter --preserve-credentials -U -n --target=$child ip addr show tun11 | grep -v inet |
69 | ||
70 | unshare -rm $(readlink -f $(dirname $0)/slirp4netns-no-unmount.sh) |
0 | 0 | # DO NOT EDIT MANUALLY |
1 | 1 | |
2 | 2 | Vendored components: |
3 | * libslirp: https://gitlab.freedesktop.org/slirp/libslirp.git (`d203c81bc6c861e1671122c3194c21d1a6763641`) | |
3 | * libslirp: https://gitlab.freedesktop.org/slirp/libslirp.git (`6651ba26c4e94f64d6448a2db4991269ce553bd9`) | |
4 | 4 | * parson: https://github.com/kgabis/parson.git (`c5bb9557fe98367aa8e041c65863909f12ee76b2`) |
5 | 5 | |
6 | 6 | Please do not edit the contents under this directory manually. |
70 | 70 | DEBUG_ARG("ip = %s", inet_ntoa((struct in_addr){ .s_addr = ip_addr })); |
71 | 71 | |
72 | 72 | /* If broadcast address */ |
73 | if (ip_addr == 0xffffffff || ip_addr == broadcast_addr) { | |
73 | if (ip_addr == 0 || ip_addr == 0xffffffff || ip_addr == broadcast_addr) { | |
74 | 74 | /* return Ethernet broadcast address */ |
75 | 75 | memset(out_ethaddr, 0xff, ETH_ALEN); |
76 | 76 | return 1; |
237 | 237 | size_t i, num_domains, memreq = 0; |
238 | 238 | uint8_t *result = NULL, *outptr; |
239 | 239 | CompactDomain *domains = NULL; |
240 | const char **nameptr = names; | |
241 | ||
242 | while (*nameptr != NULL) { | |
243 | nameptr++; | |
244 | } | |
245 | ||
246 | num_domains = nameptr - names; | |
240 | ||
241 | num_domains = g_strv_length((GStrv)names); | |
247 | 242 | if (num_domains == 0) { |
248 | 243 | return -2; |
249 | 244 | } |
6 | 6 | #endif |
7 | 7 | |
8 | 8 | #define SLIRP_MAJOR_VERSION 4 |
9 | #define SLIRP_MINOR_VERSION 0 | |
9 | #define SLIRP_MINOR_VERSION 1 | |
10 | 10 | #define SLIRP_MICRO_VERSION 0 |
11 | 11 | |
12 | 12 | #define SLIRP_CHECK_VERSION(major,minor,micro) \ |
167 | 167 | int fork_exec(struct socket *so, const char *ex) |
168 | 168 | { |
169 | 169 | GError *err = NULL; |
170 | char **argv; | |
170 | gint argc = 0; | |
171 | gchar **argv = NULL; | |
171 | 172 | int opt, sp[2]; |
172 | 173 | |
173 | 174 | DEBUG_CALL("fork_exec"); |
178 | 179 | return 0; |
179 | 180 | } |
180 | 181 | |
181 | argv = g_strsplit(ex, " ", -1); | |
182 | if (!g_shell_parse_argv(ex, &argc, &argv, &err)) { | |
183 | g_critical("fork_exec invalid command: %s\nerror: %s", ex, err->message); | |
184 | g_error_free(err); | |
185 | return 0; | |
186 | } | |
187 | ||
182 | 188 | g_spawn_async_with_fds(NULL /* cwd */, argv, NULL /* env */, |
183 | 189 | G_SPAWN_SEARCH_PATH, fork_exec_child_setup, |
184 | 190 | NULL /* data */, NULL /* child_pid */, sp[1], sp[1], |
8 | 8 | |
9 | 9 | void sbfree(struct sbuf *sb) |
10 | 10 | { |
11 | free(sb->sb_data); | |
11 | g_free(sb->sb_data); | |
12 | 12 | } |
13 | 13 | |
14 | bool sbdrop(struct sbuf *sb, int num) | |
14 | bool sbdrop(struct sbuf *sb, size_t num) | |
15 | 15 | { |
16 | 16 | int limit = sb->sb_datalen / 2; |
17 | 17 | |
18 | /* | |
19 | * We can only drop how much we have | |
20 | * This should never succeed | |
21 | */ | |
18 | g_warn_if_fail(num <= sb->sb_cc); | |
22 | 19 | if (num > sb->sb_cc) |
23 | 20 | num = sb->sb_cc; |
21 | ||
24 | 22 | sb->sb_cc -= num; |
25 | 23 | sb->sb_rptr += num; |
26 | 24 | if (sb->sb_rptr >= sb->sb_data + sb->sb_datalen) |
33 | 31 | return false; |
34 | 32 | } |
35 | 33 | |
36 | void sbreserve(struct sbuf *sb, int size) | |
34 | void sbreserve(struct sbuf *sb, size_t size) | |
37 | 35 | { |
38 | if (sb->sb_data) { | |
39 | /* Already alloced, realloc if necessary */ | |
40 | if (sb->sb_datalen != size) { | |
41 | sb->sb_wptr = sb->sb_rptr = sb->sb_data = | |
42 | (char *)realloc(sb->sb_data, size); | |
43 | sb->sb_cc = 0; | |
44 | if (sb->sb_wptr) | |
45 | sb->sb_datalen = size; | |
46 | else | |
47 | sb->sb_datalen = 0; | |
48 | } | |
49 | } else { | |
50 | sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)malloc(size); | |
51 | sb->sb_cc = 0; | |
52 | if (sb->sb_wptr) | |
53 | sb->sb_datalen = size; | |
54 | else | |
55 | sb->sb_datalen = 0; | |
56 | } | |
36 | sb->sb_wptr = sb->sb_rptr = sb->sb_data = g_realloc(sb->sb_data, size); | |
37 | sb->sb_cc = 0; | |
38 | sb->sb_datalen = size; | |
57 | 39 | } |
58 | 40 | |
59 | 41 | /* |
160 | 142 | * Don't update the sbuf rptr, this will be |
161 | 143 | * done in sbdrop when the data is acked |
162 | 144 | */ |
163 | void sbcopy(struct sbuf *sb, int off, int len, char *to) | |
145 | void sbcopy(struct sbuf *sb, size_t off, size_t len, char *to) | |
164 | 146 | { |
165 | 147 | char *from; |
148 | ||
149 | g_assert(len + off <= sb->sb_cc); | |
166 | 150 | |
167 | 151 | from = sb->sb_rptr + off; |
168 | 152 | if (from >= sb->sb_data + sb->sb_datalen) |
169 | 153 | from -= sb->sb_datalen; |
170 | 154 | |
171 | 155 | if (from < sb->sb_wptr) { |
172 | if (len > sb->sb_cc) | |
173 | len = sb->sb_cc; | |
174 | 156 | memcpy(to, from, len); |
175 | 157 | } else { |
176 | 158 | /* re-use off */ |
17 | 17 | char *sb_data; /* Actual data */ |
18 | 18 | }; |
19 | 19 | |
20 | void sbfree(struct sbuf *); | |
21 | bool sbdrop(struct sbuf *, int); | |
22 | void sbreserve(struct sbuf *, int); | |
23 | void sbappend(struct socket *, struct mbuf *); | |
24 | void sbcopy(struct sbuf *, int, int, char *); | |
20 | void sbfree(struct sbuf *sb); | |
21 | bool sbdrop(struct sbuf *sb, size_t len); | |
22 | void sbreserve(struct sbuf *sb, size_t size); | |
23 | void sbappend(struct socket *sb, struct mbuf *mb); | |
24 | void sbcopy(struct sbuf *sb, size_t off, size_t len, char *p); | |
25 | 25 | |
26 | 26 | #endif |
844 | 844 | { |
845 | 845 | const struct ip *iph = (const struct ip *)ifm->m_data; |
846 | 846 | |
847 | if (iph->ip_dst.s_addr == 0) { | |
848 | /* 0.0.0.0 can not be a destination address, something went wrong, | |
849 | * avoid making it worse */ | |
850 | return 1; | |
851 | } | |
852 | 847 | if (!arp_table_search(slirp, iph->ip_dst.s_addr, ethaddr)) { |
853 | 848 | uint8_t arp_req[ETH_HLEN + sizeof(struct slirp_arphdr)]; |
854 | 849 | struct ethhdr *reh = (struct ethhdr *)arp_req; |
265 | 265 | void tcp_sockclosed(struct tcpcb *); |
266 | 266 | int tcp_fconnect(struct socket *, unsigned short af); |
267 | 267 | void tcp_connect(struct socket *); |
268 | int tcp_attach(struct socket *); | |
268 | void tcp_attach(struct socket *); | |
269 | 269 | uint8_t tcp_tos(struct socket *); |
270 | 270 | int tcp_emu(struct socket *, struct mbuf *); |
271 | 271 | int tcp_ctl(struct socket *); |
94 | 94 | remque(so); /* crashes if so is not in a queue */ |
95 | 95 | |
96 | 96 | if (so->so_tcpcb) { |
97 | free(so->so_tcpcb); | |
97 | g_free(so->so_tcpcb); | |
98 | 98 | } |
99 | 99 | g_free(so); |
100 | 100 | } |
194 | 194 | |
195 | 195 | err = errno; |
196 | 196 | if (nn == 0) { |
197 | if (getpeername(so->s, paddr, &alen) < 0) { | |
197 | int shutdown_wr = so->so_state & SS_FCANTSENDMORE; | |
198 | ||
199 | if (!shutdown_wr && getpeername(so->s, paddr, &alen) < 0) { | |
198 | 200 | err = errno; |
199 | 201 | } else { |
200 | 202 | getsockopt(so->s, SOL_SOCKET, SO_ERROR, &err, &elen); |
843 | 845 | } else { |
844 | 846 | sin->sin_addr = loopback_addr; |
845 | 847 | } |
848 | } else if (!slirp->disable_host_loopback && so->so_faddr.s_addr == 0xffffffff) { | |
849 | /* Receive broadcast as well */ | |
850 | sin->sin_addr = loopback_addr; | |
846 | 851 | } |
847 | 852 | break; |
848 | 853 | case AF_INET6: |
862 | 867 | } else { |
863 | 868 | sin6->sin6_addr = in6addr_loopback; |
864 | 869 | } |
870 | } else if (!slirp->disable_host_loopback | |
871 | && in6_equal(&so->so_faddr6, &(struct in6_addr) ALLNODES_MULTICAST)) { | |
872 | sin6->sin6_addr = in6addr_loopback; | |
865 | 873 | } |
866 | 874 | break; |
867 | 875 |
106 | 106 | /* Allocate the buffer space used by the field after the tmp */ |
107 | 107 | sbreserve(tmp->parent, tmp->parent->sb_datalen); |
108 | 108 | |
109 | if (tmp->parent->sb_datalen != requested_len) { | |
110 | return -ENOMEM; | |
111 | } | |
112 | 109 | if (tmp->woff >= requested_len || tmp->roff >= requested_len) { |
113 | 110 | g_critical("invalid sbuf offsets r/w=%u/%u len=%u", tmp->roff, |
114 | 111 | tmp->woff, requested_len); |
158 | 155 | static int slirp_socket_pre_load(void *opaque) |
159 | 156 | { |
160 | 157 | struct socket *so = opaque; |
161 | if (tcp_attach(so) < 0) { | |
162 | return -ENOMEM; | |
163 | } | |
158 | ||
159 | tcp_attach(so); | |
164 | 160 | /* Older versions don't load these fields */ |
165 | 161 | so->so_ffamily = AF_INET; |
166 | 162 | so->so_lfamily = AF_INET; |
407 | 407 | goto dropwithreset; |
408 | 408 | |
409 | 409 | so = socreate(slirp); |
410 | if (tcp_attach(so) < 0) { | |
411 | g_free(so); /* Not sofree (if it failed, it's not insqued) */ | |
412 | goto dropwithreset; | |
413 | } | |
410 | tcp_attach(so); | |
414 | 411 | |
415 | 412 | sbreserve(&so->so_snd, TCP_SNDSPACE); |
416 | 413 | sbreserve(&so->so_rcv, TCP_RCVSPACE); |
254 | 254 | { |
255 | 255 | register struct tcpcb *tp; |
256 | 256 | |
257 | tp = (struct tcpcb *)malloc(sizeof(*tp)); | |
258 | if (tp == NULL) | |
259 | return ((struct tcpcb *)0); | |
260 | ||
261 | memset((char *)tp, 0, sizeof(struct tcpcb)); | |
257 | tp = g_new0(struct tcpcb, 1); | |
262 | 258 | tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp; |
263 | 259 | /* |
264 | 260 | * 40: length of IPv4 header (20) + TCP header (20) |
335 | 331 | remque(tcpiphdr2qlink(tcpiphdr_prev(t))); |
336 | 332 | m_free(m); |
337 | 333 | } |
338 | free(tp); | |
334 | g_free(tp); | |
339 | 335 | so->so_tcpcb = NULL; |
340 | 336 | /* clobber input socket cache if we're closing the cached connection */ |
341 | 337 | if (so == slirp->tcp_last_so) |
376 | 372 | case TCPS_LISTEN: |
377 | 373 | case TCPS_SYN_SENT: |
378 | 374 | tp->t_state = TCPS_CLOSED; |
379 | tp = tcp_close(tp); | |
380 | break; | |
375 | tcp_close(tp); | |
376 | return; | |
381 | 377 | |
382 | 378 | case TCPS_SYN_RECEIVED: |
383 | 379 | case TCPS_ESTABLISHED: |
473 | 469 | so = inso; |
474 | 470 | } else { |
475 | 471 | so = socreate(slirp); |
476 | if (tcp_attach(so) < 0) { | |
477 | g_free(so); /* NOT sofree */ | |
478 | return; | |
479 | } | |
472 | tcp_attach(so); | |
480 | 473 | so->lhost = inso->lhost; |
481 | 474 | so->so_ffamily = inso->so_ffamily; |
482 | 475 | } |
527 | 520 | /* |
528 | 521 | * Attach a TCPCB to a socket. |
529 | 522 | */ |
530 | int tcp_attach(struct socket *so) | |
531 | { | |
532 | if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) | |
533 | return -1; | |
534 | ||
523 | void tcp_attach(struct socket *so) | |
524 | { | |
525 | so->so_tcpcb = tcp_newtcpcb(so); | |
535 | 526 | insque(so, &so->slirp->tcb); |
536 | ||
537 | return 0; | |
538 | 527 | } |
539 | 528 | |
540 | 529 | /* |
320 | 320 | } |
321 | 321 | for (i = 0; i < n_elems; i++) { |
322 | 322 | void *curr_elem = first_elem + size * i; |
323 | ret = 0; | |
324 | 323 | |
325 | 324 | if (field->flags & VMS_ARRAY_OF_POINTER) { |
326 | 325 | assert(curr_elem); |