Branch data Line data Source code
1 : : #include <sys/types.h>
2 : : #include <sys/socket.h>
3 : : #include <linux/netlink.h>
4 : : #include <linux/rtnetlink.h>
5 : : #include <sys/mman.h>
6 : : #include <unistd.h>
7 : : #include <netinet/tcp.h>
8 : : #include <arpa/inet.h>
9 : : #include <string.h>
10 : : #include <stdlib.h>
11 : :
12 : : #include "asm/types.h"
13 : : #include "libnetlink.h"
14 : : #include "cr_options.h"
15 : : #include "fdset.h"
16 : : #include "inet_diag.h"
17 : : #include "files.h"
18 : : #include "image.h"
19 : : #include "log.h"
20 : : #include "util.h"
21 : : #include "sockets.h"
22 : : #include "sk-inet.h"
23 : :
24 : : #define PB_ALEN_INET 1
25 : : #define PB_ALEN_INET6 4
26 : :
27 : : static LIST_HEAD(inet_ports);
28 : :
29 : : struct inet_port {
30 : : int port;
31 : : int type;
32 : : futex_t users;
33 : : struct list_head list;
34 : : };
35 : :
36 : 182 : static struct inet_port *port_add(int type, int port)
37 : : {
38 : : struct inet_port *e;
39 : :
40 [ + + ]: 224 : list_for_each_entry(e, &inet_ports, list)
41 [ + - ][ + + ]: 86 : if (e->type == type && e->port == port) {
42 : : futex_inc(&e->users);
43 : 44 : return e;
44 : : }
45 : :
46 : 138 : e = shmalloc(sizeof(*e));
47 [ - + ]: 138 : if (e == NULL) {
48 : 0 : pr_err("Not enough memory\n");
49 : 0 : return NULL;
50 : : }
51 : :
52 : 138 : e->port = port;
53 : 138 : e->type = type;
54 : : futex_init(&e->users);
55 : : futex_inc(&e->users);
56 : :
57 : 138 : list_add(&e->list, &inet_ports);
58 : :
59 : 138 : return e;
60 : : }
61 : :
62 : 21114 : static void show_one_inet(const char *act, const struct inet_sk_desc *sk)
63 : : {
64 : 21114 : char src_addr[INET_ADDR_LEN] = "<unknown>";
65 : :
66 [ - + ]: 21114 : if (inet_ntop(sk->sd.family, (void *)sk->src_addr, src_addr,
67 : : INET_ADDR_LEN) == NULL) {
68 : 0 : pr_perror("Failed to translate address");
69 : : }
70 : :
71 : 21114 : pr_debug("\t%s: ino 0x%8x family %4d type %4d port %8d "
72 : : "state %2d src_addr %s\n",
73 : : act, sk->sd.ino, sk->sd.family, sk->type, sk->src_port,
74 : : sk->state, src_addr);
75 : 21114 : }
76 : :
77 : 148 : static void show_one_inet_img(const char *act, const InetSkEntry *e)
78 : : {
79 : 148 : char src_addr[INET_ADDR_LEN] = "<unknown>";
80 : :
81 [ - + ]: 148 : if (inet_ntop(e->family, (void *)e->src_addr, src_addr,
82 : : INET_ADDR_LEN) == NULL) {
83 : 0 : pr_perror("Failed to translate address");
84 : : }
85 : :
86 : 148 : pr_debug("\t%s: family %d type %d proto %d port %d "
87 : : "state %d src_addr %s\n",
88 : : act, e->family, e->type, e->proto, e->src_port,
89 : : e->state, src_addr);
90 : 148 : }
91 : :
92 : 86 : static int can_dump_inet_sk(const struct inet_sk_desc *sk, int proto)
93 : : {
94 [ - + ]: 86 : BUG_ON((sk->sd.family != AF_INET) && (sk->sd.family != AF_INET6));
95 : :
96 [ - + ]: 86 : if (sk->shutdown) {
97 : 0 : pr_err("Can't dump shutdown inet socket %x\n",
98 : : sk->sd.ino);
99 : 0 : return 0;
100 : : }
101 : :
102 [ + + ]: 86 : if (sk->type == SOCK_DGRAM) {
103 [ - + ]: 28 : if (sk->wqlen != 0) {
104 : 0 : pr_err("Can't dump corked dgram socket %x\n",
105 : : sk->sd.ino);
106 : 0 : return 0;
107 : : }
108 : :
109 [ - + ]: 28 : if (sk->rqlen)
110 : 0 : pr_warn("Read queue is dropped for socket %x\n",
111 : : sk->sd.ino);
112 : :
113 : : return 1;
114 : : }
115 : :
116 [ - + ]: 58 : if (sk->type != SOCK_STREAM) {
117 : 0 : pr_err("Can't dump %d inet socket %x. "
118 : : "Only can stream and dgram.\n",
119 : : sk->type, sk->sd.ino);
120 : 0 : return 0;
121 : : }
122 : :
123 [ + + - + ]: 58 : switch (sk->state) {
124 : : case TCP_LISTEN:
125 [ - + ]: 22 : if (sk->rqlen != 0) {
126 : : /*
127 : : * Currently the ICONS nla reports the conn
128 : : * requests for listen sockets. Need to pick
129 : : * those up and fix the connect job respectively
130 : : */
131 : 0 : pr_err("In-flight connection (l) for %x\n",
132 : : sk->sd.ino);
133 : 0 : return 0;
134 : : }
135 : : break;
136 : : case TCP_ESTABLISHED:
137 [ - + ]: 24 : if (!opts.tcp_established_ok) {
138 : 0 : pr_err("Connected TCP socket, consider using %s option.\n",
139 : : SK_EST_PARAM);
140 : 0 : return 0;
141 : : }
142 : : break;
143 : : case TCP_CLOSE:
144 : : /* Trivial case, we just need to create a socket on restore */
145 : : break;
146 : : default:
147 : 0 : pr_err("Unknown inet socket %x state %d\n", sk->sd.ino, sk->state);
148 : 0 : return 0;
149 : : }
150 : :
151 : : /* Make sure it's a proto we support */
152 [ - + ]: 58 : switch (proto) {
153 : : case IPPROTO_IP:
154 : : case IPPROTO_TCP:
155 : : case IPPROTO_UDP:
156 : : case IPPROTO_UDPLITE:
157 : : break;
158 : : default:
159 : 0 : pr_err("Unsupported proto %d for socket %x\n", proto, sk->sd.ino);
160 : 0 : return 0;
161 : : }
162 : :
163 : : return 1;
164 : : }
165 : :
166 : 16 : static struct inet_sk_desc *gen_uncon_sk(int lfd, const struct fd_parms *p, int proto)
167 : : {
168 : : struct inet_sk_desc *sk;
169 : : char address;
170 : : socklen_t aux;
171 : : int ret;
172 : :
173 [ - + ]: 16 : sk = xzalloc(sizeof(*sk));
174 [ + - ]: 16 : if (!sk)
175 : : goto err;
176 : :
177 : : /* It should has no peer name */
178 : 16 : aux = sizeof(address);
179 : 16 : ret = getsockopt(lfd, SOL_SOCKET, SO_PEERNAME, &address, &aux);
180 [ + - ]: 16 : if (ret < 0) {
181 [ - + ]: 16 : if (errno != ENOTCONN) {
182 : 0 : pr_perror("Unexpected error returned from unconnected socket");
183 : : goto err;
184 : : }
185 [ # # ]: 0 : } else if (ret == 0) {
186 : 0 : pr_err("Name resolved on unconnected socket\n");
187 : : goto err;
188 : : }
189 : :
190 : 16 : sk->sd.ino = p->stat.st_ino;
191 : :
192 : 16 : ret = do_dump_opt(lfd, SOL_SOCKET, SO_DOMAIN, &sk->sd.family, sizeof(sk->sd.family));
193 : 16 : ret |= do_dump_opt(lfd, SOL_SOCKET, SO_TYPE, &sk->type, sizeof(sk->type));
194 [ + - ]: 16 : if (ret)
195 : : goto err;
196 : :
197 [ + + ]: 16 : if (proto == IPPROTO_TCP) {
198 : : struct tcp_info info;
199 : :
200 : 12 : aux = sizeof(info);
201 : 12 : ret = getsockopt(lfd, SOL_TCP, TCP_INFO, &info, &aux);
202 [ - + ]: 12 : if (ret) {
203 : 0 : pr_perror("Failed to obtain TCP_INFO");
204 : 0 : goto err;
205 : : }
206 : :
207 [ - + ]: 12 : if (info.tcpi_state != TCP_CLOSE) {
208 : 0 : pr_err("Socket state %d obtained but expected %d\n",
209 : : info.tcpi_state, TCP_CLOSE);
210 : : goto err;
211 : : }
212 : :
213 : 12 : sk->wqlen = info.tcpi_backoff;
214 : : }
215 : :
216 : 16 : sk->state = TCP_CLOSE;
217 : :
218 : 16 : sk_collect_one(sk->sd.ino, sk->sd.family, &sk->sd);
219 : :
220 : : return sk;
221 : : err:
222 [ # # ]: 0 : xfree(sk);
223 : : return NULL;
224 : : }
225 : :
226 : 86 : static int do_dump_one_inet_fd(int lfd, u32 id, const struct fd_parms *p, int family)
227 : : {
228 : : struct inet_sk_desc *sk;
229 : 86 : InetSkEntry ie = INET_SK_ENTRY__INIT;
230 : 86 : SkOptsEntry skopts = SK_OPTS_ENTRY__INIT;
231 : : int ret = -1, err = -1, proto;
232 : :
233 : 86 : ret = do_dump_opt(lfd, SOL_SOCKET, SO_PROTOCOL,
234 : : &proto, sizeof(proto));
235 [ + - ]: 86 : if (ret)
236 : : goto err;
237 : :
238 : 86 : sk = (struct inet_sk_desc *)lookup_socket(p->stat.st_ino, family, proto);
239 [ + - ]: 86 : if (IS_ERR(sk))
240 : : goto err;
241 [ + + ]: 86 : if (!sk) {
242 : 16 : sk = gen_uncon_sk(lfd, p, proto);
243 [ + - ]: 16 : if (!sk)
244 : : goto err;
245 : : }
246 : :
247 [ + - ]: 86 : if (!can_dump_inet_sk(sk, proto))
248 : : goto err;
249 : :
250 [ - + ]: 86 : BUG_ON(sk->sd.already_dumped);
251 : :
252 : 86 : ie.id = id;
253 : 86 : ie.ino = sk->sd.ino;
254 : 86 : ie.family = family;
255 : 86 : ie.proto = proto;
256 : 86 : ie.type = sk->type;
257 : 86 : ie.state = sk->state;
258 : 86 : ie.src_port = sk->src_port;
259 : 86 : ie.dst_port = sk->dst_port;
260 : 86 : ie.backlog = sk->wqlen;
261 : 86 : ie.flags = p->flags;
262 : :
263 : 86 : ie.fown = (FownEntry *)&p->fown;
264 : 86 : ie.opts = &skopts;
265 : :
266 : 86 : ie.n_src_addr = PB_ALEN_INET;
267 : 86 : ie.n_dst_addr = PB_ALEN_INET;
268 [ + + ]: 86 : if (ie.family == AF_INET6) {
269 : : int val;
270 : :
271 : 26 : ie.n_src_addr = PB_ALEN_INET6;
272 : 26 : ie.n_dst_addr = PB_ALEN_INET6;
273 : :
274 : 26 : ret = dump_opt(lfd, SOL_IPV6, IPV6_V6ONLY, &val);
275 [ + - ]: 26 : if (ret < 0)
276 : : goto err;
277 : :
278 : 26 : ie.v6only = val ? true : false;
279 : 26 : ie.has_v6only = true;
280 : : }
281 : :
282 [ - + ]: 86 : ie.src_addr = xmalloc(pb_repeated_size(&ie, src_addr));
283 [ - + ]: 86 : ie.dst_addr = xmalloc(pb_repeated_size(&ie, dst_addr));
284 : :
285 [ + - ][ + - ]: 86 : if (!ie.src_addr || !ie.dst_addr)
286 : : goto err;
287 : :
288 : 86 : memcpy(ie.src_addr, sk->src_addr, pb_repeated_size(&ie, src_addr));
289 : 86 : memcpy(ie.dst_addr, sk->dst_addr, pb_repeated_size(&ie, dst_addr));
290 : :
291 [ + - ]: 86 : if (dump_socket_opts(lfd, &skopts))
292 : : goto err;
293 : :
294 [ + - ]: 86 : if (pb_write_one(fdset_fd(glob_fdset, CR_FD_INETSK), &ie, PB_INET_SK))
295 : : goto err;
296 : :
297 : 86 : pr_info("Dumping inet socket at %d\n", p->fd);
298 : 86 : show_one_inet("Dumping", sk);
299 : 86 : show_one_inet_img("Dumped", &ie);
300 : 86 : sk->sd.already_dumped = 1;
301 : 86 : sk->cpt_reuseaddr = skopts.reuseaddr;
302 : :
303 [ + + ]: 86 : switch (proto) {
304 : : case IPPROTO_TCP:
305 : 58 : err = dump_one_tcp(lfd, sk);
306 : 58 : break;
307 : : default:
308 : : err = 0;
309 : : break;
310 : : }
311 : : err:
312 : 86 : release_skopts(&skopts);
313 [ + - ]: 86 : xfree(ie.src_addr);
314 [ + - ]: 86 : xfree(ie.dst_addr);
315 : 86 : return err;
316 : : }
317 : :
318 : 60 : static int dump_one_inet_fd(int lfd, u32 id, const struct fd_parms *p)
319 : : {
320 : 60 : return do_dump_one_inet_fd(lfd, id, p, PF_INET);
321 : : }
322 : :
323 : : const struct fdtype_ops inet_dump_ops = {
324 : : .type = FD_TYPES__INETSK,
325 : : .dump = dump_one_inet_fd,
326 : : };
327 : :
328 : 26 : static int dump_one_inet6_fd(int lfd, u32 id, const struct fd_parms *p)
329 : : {
330 : 26 : return do_dump_one_inet_fd(lfd, id, p, PF_INET6);
331 : : }
332 : :
333 : : const struct fdtype_ops inet6_dump_ops = {
334 : : .type = FD_TYPES__INETSK,
335 : : .dump = dump_one_inet6_fd,
336 : : };
337 : :
338 : 21028 : int inet_collect_one(struct nlmsghdr *h, int family, int type)
339 : : {
340 : : struct inet_sk_desc *d;
341 : : struct inet_diag_msg *m = NLMSG_DATA(h);
342 : : struct rtattr *tb[INET_DIAG_MAX+1];
343 : : int ret;
344 : :
345 : 21028 : parse_rtattr(tb, INET_DIAG_MAX, (struct rtattr *)(m + 1),
346 : 21028 : h->nlmsg_len - NLMSG_LENGTH(sizeof(*m)));
347 : :
348 [ - + ]: 21028 : d = xzalloc(sizeof(*d));
349 [ + - ]: 21028 : if (!d)
350 : : return -1;
351 : :
352 : 21028 : d->type = type;
353 [ - + ]: 21028 : d->src_port = ntohs(m->id.idiag_sport);
354 [ - + ]: 21028 : d->dst_port = ntohs(m->id.idiag_dport);
355 : 21028 : d->state = m->idiag_state;
356 : 21028 : d->rqlen = m->idiag_rqueue;
357 : 21028 : d->wqlen = m->idiag_wqueue;
358 : 21028 : memcpy(d->src_addr, m->id.idiag_src, sizeof(u32) * 4);
359 : 21028 : memcpy(d->dst_addr, m->id.idiag_dst, sizeof(u32) * 4);
360 : :
361 [ + - ]: 21028 : if (tb[INET_DIAG_SHUTDOWN])
362 : 21028 : d->shutdown = *(u8 *)RTA_DATA(tb[INET_DIAG_SHUTDOWN]);
363 : : else
364 [ # # ]: 0 : pr_err_once("Can't check shutdown state of inet socket\n");
365 : :
366 : 21028 : ret = sk_collect_one(m->idiag_inode, family, &d->sd);
367 : :
368 : 21028 : show_one_inet("Collected", d);
369 : :
370 : 21028 : return ret;
371 : : }
372 : :
373 : : static int open_inet_sk(struct file_desc *d);
374 : : static int post_open_inet_sk(struct file_desc *d, int sk);
375 : :
376 : : static struct file_desc_ops inet_desc_ops = {
377 : : .type = FD_TYPES__INETSK,
378 : : .open = open_inet_sk,
379 : : .post_open = post_open_inet_sk,
380 : : };
381 : :
382 : : static inline int tcp_connection(InetSkEntry *ie)
383 : : {
384 : 306 : return (ie->proto == IPPROTO_TCP) && (ie->state == TCP_ESTABLISHED);
385 : : }
386 : :
387 : 182 : static int collect_one_inetsk(void *o, ProtobufCMessage *base)
388 : : {
389 : : struct inet_sk_info *ii = o;
390 : :
391 : 182 : ii->ie = pb_msg(base, InetSkEntry);
392 [ + + ]: 182 : if (tcp_connection(ii->ie))
393 : 56 : tcp_locked_conn_add(ii);
394 : :
395 : : /*
396 : : * A socket can reuse addr only if all previous sockets allow that,
397 : : * so a value of SO_REUSEADDR can be restored after restoring all
398 : : * sockets.
399 : : */
400 : 182 : ii->port = port_add(ii->ie->type, ii->ie->src_port);
401 [ + - ]: 182 : if (ii->port == NULL)
402 : : return -1;
403 : :
404 : 182 : return file_desc_add(&ii->d, ii->ie->id, &inet_desc_ops);
405 : : }
406 : :
407 : : struct collect_image_info inet_sk_cinfo = {
408 : : .fd_type = CR_FD_INETSK,
409 : : .pb_type = PB_INET_SK,
410 : : .priv_size = sizeof(struct inet_sk_info),
411 : : .collect = collect_one_inetsk,
412 : : };
413 : :
414 : 1012 : int collect_inet_sockets(void)
415 : : {
416 : 1012 : return collect_image(&inet_sk_cinfo);
417 : : }
418 : :
419 : 62 : static int inet_validate_address(InetSkEntry *ie)
420 : : {
421 [ + + ][ + - ]: 62 : if ((ie->family == AF_INET) &&
422 : : /* v0.1 had 4 in ipv4 addr len */
423 [ - + ]: 42 : (ie->n_src_addr >= PB_ALEN_INET) &&
424 : 42 : (ie->n_dst_addr >= PB_ALEN_INET))
425 : : return 0;
426 : :
427 [ + - ][ + - ]: 20 : if ((ie->family == AF_INET6) &&
428 [ - + ]: 20 : (ie->n_src_addr == PB_ALEN_INET6) &&
429 : 20 : (ie->n_dst_addr == PB_ALEN_INET6))
430 : : return 0;
431 : :
432 : 0 : pr_err("Addr len mismatch f %d ss %zu ds %zu\n", ie->family,
433 : : pb_repeated_size(ie, src_addr),
434 : : pb_repeated_size(ie, dst_addr));
435 : :
436 : 0 : return -1;
437 : : }
438 : :
439 : 62 : static int post_open_inet_sk(struct file_desc *d, int sk)
440 : : {
441 : : struct inet_sk_info *ii;
442 : : int val;
443 : :
444 : : ii = container_of(d, struct inet_sk_info, d);
445 : :
446 : : /*
447 : : * TCP sockets are handled at the last moment
448 : : * after unlocking connections.
449 : : */
450 [ + + ]: 62 : if (tcp_connection(ii->ie)) {
451 [ + - ]: 24 : if (rst_tcp_socks_add(sk, ii->ie->opts->reuseaddr))
452 : : return -1;
453 : :
454 : 24 : return 0;
455 : : }
456 : :
457 : : /* SO_REUSEADDR is set for all sockets */
458 [ + + ]: 38 : if (ii->ie->opts->reuseaddr)
459 : : return 0;
460 : :
461 : 20 : futex_wait_until(&ii->port->users, 0);
462 : :
463 : 20 : val = ii->ie->opts->reuseaddr;
464 [ + - ]: 20 : if (restore_opt(sk, SOL_SOCKET, SO_REUSEADDR, &val))
465 : : return -1;
466 : :
467 : 20 : return 0;
468 : : }
469 : :
470 : 62 : static int open_inet_sk(struct file_desc *d)
471 : : {
472 : : struct inet_sk_info *ii;
473 : : InetSkEntry *ie;
474 : 62 : int sk, yes = 1;
475 : :
476 : 62 : ii = container_of(d, struct inet_sk_info, d);
477 : 62 : ie = ii->ie;
478 : :
479 : 62 : show_one_inet_img("Restore", ie);
480 : :
481 [ - + ]: 62 : if (ie->family != AF_INET && ie->family != AF_INET6) {
482 : 0 : pr_err("Unsupported socket family: %d\n", ie->family);
483 : 0 : return -1;
484 : : }
485 : :
486 [ - + ]: 62 : if ((ie->type != SOCK_STREAM) && (ie->type != SOCK_DGRAM)) {
487 : 0 : pr_err("Unsupported socket type: %d\n", ie->type);
488 : 0 : return -1;
489 : : }
490 : :
491 [ + - ]: 62 : if (inet_validate_address(ie))
492 : : return -1;
493 : :
494 : 62 : sk = socket(ie->family, ie->type, ie->proto);
495 [ - + ]: 62 : if (sk < 0) {
496 : 0 : pr_perror("Can't create inet socket");
497 : 0 : return -1;
498 : : }
499 : :
500 [ + + ]: 62 : if (ie->v6only) {
501 [ + - ]: 4 : if (restore_opt(sk, SOL_IPV6, IPV6_V6ONLY, &yes) == -1)
502 : : return -1;
503 : : }
504 : :
505 : : /*
506 : : * Set SO_REUSEADDR, because some sockets can be bound to one addr.
507 : : * The origin value of SO_REUSEADDR will be restored in post_open.
508 : : */
509 [ + - ]: 62 : if (restore_opt(sk, SOL_SOCKET, SO_REUSEADDR, &yes))
510 : : return -1;
511 : :
512 [ + + ]: 62 : if (tcp_connection(ie)) {
513 [ - + ]: 24 : if (!opts.tcp_established_ok) {
514 : 0 : pr_err("Connected TCP socket in image\n");
515 : 0 : goto err;
516 : : }
517 : :
518 [ + - ]: 24 : if (restore_one_tcp(sk, ii))
519 : : goto err;
520 : :
521 : : goto done;
522 : : }
523 : :
524 : : /*
525 : : * Listen sockets are easiest ones -- simply
526 : : * bind() and listen(), and that's all.
527 : : */
528 : :
529 [ + + ]: 38 : if (ie->src_port) {
530 [ + - ]: 30 : if (inet_bind(sk, ii))
531 : : goto err;
532 : : }
533 : :
534 [ + + ]: 38 : if (ie->state == TCP_LISTEN) {
535 [ - + ]: 18 : if (ie->proto != IPPROTO_TCP) {
536 : 0 : pr_err("Wrong socket in listen state %d\n", ie->proto);
537 : 0 : goto err;
538 : : }
539 : :
540 [ - + ]: 18 : if (listen(sk, ie->backlog) == -1) {
541 : 0 : pr_perror("Can't listen on a socket");
542 : 0 : goto err;
543 : : }
544 : : }
545 : :
546 [ + + + - ]: 44 : if (ie->state == TCP_ESTABLISHED &&
547 : 6 : inet_connect(sk, ii))
548 : : goto err;
549 : : done:
550 : 62 : futex_dec(&ii->port->users);
551 : :
552 [ + - ]: 62 : if (rst_file_params(sk, ie->fown, ie->flags))
553 : : goto err;
554 : :
555 [ + - ]: 62 : if (restore_socket_opts(sk, ie->opts))
556 : : return -1;
557 : :
558 : 62 : return sk;
559 : :
560 : : err:
561 : 0 : close(sk);
562 : 0 : return -1;
563 : : }
564 : :
565 : : union sockaddr_inet {
566 : : struct sockaddr_in v4;
567 : : struct sockaddr_in6 v6;
568 : : };
569 : :
570 : 84 : static int restore_sockaddr(union sockaddr_inet *sa,
571 : : int family, u32 pb_port, u32 *pb_addr)
572 : : {
573 : : BUILD_BUG_ON(sizeof(sa->v4.sin_addr.s_addr) > PB_ALEN_INET * sizeof(u32));
574 : : BUILD_BUG_ON(sizeof(sa->v6.sin6_addr.s6_addr) > PB_ALEN_INET6 * sizeof(u32));
575 : :
576 : : memzero(sa, sizeof(*sa));
577 : :
578 [ + + ]: 84 : if (family == AF_INET) {
579 : 54 : sa->v4.sin_family = AF_INET;
580 [ - + ]: 54 : sa->v4.sin_port = htons(pb_port);
581 : 54 : memcpy(&sa->v4.sin_addr.s_addr, pb_addr, sizeof(sa->v4.sin_addr.s_addr));
582 : 54 : return sizeof(sa->v4);
583 : : }
584 : :
585 [ + - ]: 30 : if (family == AF_INET6) {
586 : 30 : sa->v6.sin6_family = AF_INET6;
587 [ - + ]: 30 : sa->v6.sin6_port = htons(pb_port);
588 : 30 : memcpy(sa->v6.sin6_addr.s6_addr, pb_addr, sizeof(sa->v6.sin6_addr.s6_addr));
589 : 30 : return sizeof(sa->v6);
590 : : }
591 : :
592 : 0 : BUG();
593 : 0 : return -1;
594 : : }
595 : :
596 : 54 : int inet_bind(int sk, struct inet_sk_info *ii)
597 : : {
598 : : union sockaddr_inet addr;
599 : : int addr_size;
600 : :
601 : 54 : addr_size = restore_sockaddr(&addr, ii->ie->family,
602 : 54 : ii->ie->src_port, ii->ie->src_addr);
603 : :
604 [ - + ]: 54 : if (bind(sk, (struct sockaddr *)&addr, addr_size) == -1) {
605 : 0 : pr_perror("Can't bind inet socket");
606 : 0 : return -1;
607 : : }
608 : :
609 : : return 0;
610 : : }
611 : :
612 : 30 : int inet_connect(int sk, struct inet_sk_info *ii)
613 : : {
614 : : union sockaddr_inet addr;
615 : : int addr_size;
616 : :
617 : 30 : addr_size = restore_sockaddr(&addr, ii->ie->family,
618 : 30 : ii->ie->dst_port, ii->ie->dst_addr);
619 : :
620 [ - + ]: 30 : if (connect(sk, (struct sockaddr *)&addr, addr_size) == -1) {
621 : 0 : pr_perror("Can't connect inet socket back");
622 : 0 : return -1;
623 : : }
624 : :
625 : : return 0;
626 : : }
|