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