Subject: Re: unregister_netdevice: waiting for lo to become free. Usage count = 1

From: Andrei Vagin <[email-masked]>
Date: Fri, 23 Jun 2017 15:00:41 -0700

On Fri, Jun 23, 2017 at 02:49:58PM -0700, Andrei Vagin wrote:
> Hello Everyone,
> 
> Today I've met a problem, when any attempts to create a new network
> namespace hang up.
> I see that one of previous namespaces can't be destroyed, because a
> usage count for one
> of its devices isn't zero. To reproduce the problem, you need to
> executed an attached program
> in a separate network namespace:
> 
> [root@fc24 net]# cat run.sh
> ip link set up dev lo
> ./tcp-bug
> [root@fc24 net]# unshare -n sh run.sh

If this program is executed in a new user, pid, mnt, and net namespaces,
the kernel reports a bug:

[root@fc24 net]# unshare -Urmfpn sh run.sh
[root@fc24 net]# unshare -Urmfpn sh run.sh
^C

[   30.592295] unregister_netdevice: waiting for lo to become free. Usage count = 1
[   37.958180] =============================================================================
[   37.963675] BUG kmalloc-1024 (Not tainted): Poison overwritten
[   37.966160] -----------------------------------------------------------------------------

[   37.969497] Disabling lock debugging due to kernel taint
[   37.971181] INFO: 0xffff93eef8bc3760-0xffff93eef8bc3760. First byte 0x38 instead of 0x6b
[   37.973066] INFO: Slab 0xffffe69fc1e2f000 objects=15 used=15 fp=0x          (null) flags=0x1fffc000008100
[   37.974902] INFO: Object 0xffff93eef8bc35a8 @offset=13736 fp=0xffff93eef8bc1088

[   37.976618] Redzone ffff93eef8bc35a0: bb bb bb bb bb bb bb bb                          ........
[   37.978355] Object ffff93eef8bc35a8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   37.980239] Object ffff93eef8bc35b8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   37.982209] Object ffff93eef8bc35c8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   37.984072] Object ffff93eef8bc35d8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   37.985729] Object ffff93eef8bc35e8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   37.987273] Object ffff93eef8bc35f8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   37.988930] Object ffff93eef8bc3608: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   37.990582] Object ffff93eef8bc3618: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   37.991921] Object ffff93eef8bc3628: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   37.993541] Object ffff93eef8bc3638: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   37.994922] Object ffff93eef8bc3648: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   37.996745] Object ffff93eef8bc3658: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   37.998135] Object ffff93eef8bc3668: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   37.999350] Object ffff93eef8bc3678: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.000656] Object ffff93eef8bc3688: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.001920] Object ffff93eef8bc3698: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.003142] Object ffff93eef8bc36a8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.004549] Object ffff93eef8bc36b8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.005925] Object ffff93eef8bc36c8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.007296] Object ffff93eef8bc36d8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.008852] Object ffff93eef8bc36e8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.010375] Object ffff93eef8bc36f8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.011686] Object ffff93eef8bc3708: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.012967] Object ffff93eef8bc3718: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.014244] Object ffff93eef8bc3728: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.015513] Object ffff93eef8bc3738: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.016796] Object ffff93eef8bc3748: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.018101] Object ffff93eef8bc3758: 6b 6b 6b 6b 6b 6b 6b 6b 38 6b 6b 6b 6b 6b 6b 6b  kkkkkkkk8kkkkkkk
[   38.019151] Object ffff93eef8bc3768: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.020349] Object ffff93eef8bc3778: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.021622] Object ffff93eef8bc3788: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.022931] Object ffff93eef8bc3798: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.024223] Object ffff93eef8bc37a8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.025443] Object ffff93eef8bc37b8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.026741] Object ffff93eef8bc37c8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.028013] Object ffff93eef8bc37d8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.029277] Object ffff93eef8bc37e8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.030549] Object ffff93eef8bc37f8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.031861] Object ffff93eef8bc3808: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.033624] Object ffff93eef8bc3818: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.035191] Object ffff93eef8bc3828: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.036293] Object ffff93eef8bc3838: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.037468] Object ffff93eef8bc3848: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.038772] Object ffff93eef8bc3858: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.040272] Object ffff93eef8bc3868: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.041721] Object ffff93eef8bc3878: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.043095] Object ffff93eef8bc3888: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.044513] Object ffff93eef8bc3898: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.045920] Object ffff93eef8bc38a8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.047164] Object ffff93eef8bc38b8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.048417] Object ffff93eef8bc38c8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.049652] Object ffff93eef8bc38d8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.050974] Object ffff93eef8bc38e8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.052494] Object ffff93eef8bc38f8: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.053808] Object ffff93eef8bc3908: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.055004] Object ffff93eef8bc3918: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.056275] Object ffff93eef8bc3928: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.057578] Object ffff93eef8bc3938: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.058885] Object ffff93eef8bc3948: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.059926] Object ffff93eef8bc3958: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.060832] Object ffff93eef8bc3968: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.061992] Object ffff93eef8bc3978: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.063182] Object ffff93eef8bc3988: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b  kkkkkkkkkkkkkkkk
[   38.064431] Object ffff93eef8bc3998: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b a5  kkkkkkkkkkkkkkk.
[   38.065729] Redzone ffff93eef8bc39a8: bb bb bb bb bb bb bb bb                          ........
[   38.066917] Padding ffff93eef8bc39b8: 5a 5a 5a 5a 5a 5a 5a 5a                          ZZZZZZZZ
[   38.068062] CPU: 0 PID: 359 Comm: systemd-hostnam Tainted: G    B           4.12.0-rc6-00102-ga38371c-dirty #284
[   38.069374] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.9.3-1.fc25 04/01/2014
[   38.070525] Call Trace:
[   38.071085]  dump_stack+0x86/0xcf
[   38.071778]  print_trailer+0x144/0x220
[   38.072439]  check_bytes_and_report+0xc1/0x100
[   38.073074]  check_object+0x250/0x2a0
[   38.073569]  ? __alloc_skb+0x87/0x1d0
[   38.074109]  alloc_debug_processing+0x10a/0x1b0
[   38.074776]  ___slab_alloc+0x583/0x5f0
[   38.075440]  ? __alloc_skb+0x87/0x1d0
[   38.076230]  ? __alloc_skb+0x87/0x1d0
[   38.076779]  __slab_alloc+0x51/0x90
[   38.077218]  ? __slab_alloc+0x51/0x90
[   38.077824]  __kmalloc_node_track_caller+0xdf/0x3d0
[   38.078426]  ? __alloc_skb+0x87/0x1d0
[   38.078932]  __kmalloc_reserve.isra.34+0x31/0x90
[   38.079572]  ? __alloc_skb+0x5b/0x1d0
[   38.080048]  __alloc_skb+0x87/0x1d0
[   38.080480]  ? _raw_spin_unlock_irqrestore+0x5b/0x60
[   38.081357]  alloc_skb_with_frags+0x5a/0x1d0
[   38.081950]  ? lock_acquire+0xe3/0x1d0
[   38.082433]  sock_alloc_send_pskb+0x1f0/0x220
[   38.083005]  unix_dgram_sendmsg+0x17d/0x700
[   38.083547]  ? rw_copy_check_uvector+0x91/0x140
[   38.084120]  sock_sendmsg+0x38/0x50
[   38.084592]  ___sys_sendmsg+0x2d6/0x2f0
[   38.085284]  ? seccomp_run_filters+0x52/0xb0
[   38.085905]  ? __might_fault+0x85/0x90
[   38.086432]  ? __seccomp_filter+0x37/0x250
[   38.087000]  __sys_sendmsg+0x54/0x90
[   38.087485]  ? __sys_sendmsg+0x54/0x90
[   38.088018]  SyS_sendmsg+0x12/0x20
[   38.088472]  do_syscall_64+0x6c/0x1c0
[   38.089125]  entry_SYSCALL64_slow_path+0x25/0x25
[   38.089756] RIP: 0033:0x7f6870f24367
[   38.090226] RSP: 002b:00007ffecc05dfa8 EFLAGS: 00000246 ORIG_RAX: 000000000000002e
[   38.091228] RAX: ffffffffffffffda RBX: 00007ffecc05dfb0 RCX: 00007f6870f24367
[   38.092191] RDX: 0000000000004000 RSI: 00007ffecc05dfb0 RDI: 0000000000000003
[   38.093188] RBP: 00007ffecc05e870 R08: 000000000000fefe R09: 0000000000000097
[   38.094116] R10: 0000000000000073 R11: 0000000000000246 R12: 00007ffecc05e030
[   38.094985] R13: 00007ffecc05ea60 R14: 0000000000000000 R15: 00007ffecc05dff0
[   38.096058] FIX kmalloc-1024: Restoring 0xffff93eef8bc3760-0xffff93eef8bc3760=0x6b

[   38.097845] FIX kmalloc-1024: Marking all objects used
[   40.840195] unregister_netdevice: waiting for lo to become free. Usage count = 1
[   51.080197] unregister_netdevice: waiting for lo to become free. Usage count = 1

> [root@fc24 net]# echo $?
> 0
> [root@fc24 ~]# cat /proc/40/stack
> [<ffffffffa211989e>] msleep+0x3e/0x50
> [<ffffffffa2786eea>] netdev_run_todo+0x12a/0x320
> [<ffffffffa279542e>] rtnl_unlock+0xe/0x10
> [<ffffffffa277d56a>] default_device_exit_batch+0x14a/0x170
> [<ffffffffa2772d12>] ops_exit_list.isra.6+0x52/0x60
> [<ffffffffa277402e>] cleanup_net+0x1ee/0x2f0
> [<ffffffffa20ac9f5>] process_one_work+0x205/0x620
> [<ffffffffa20ace5e>] worker_thread+0x4e/0x3b0
> [<ffffffffa20b4344>] kthread+0x114/0x150
> [<ffffffffa29619fa>] ret_from_fork+0x2a/0x40
> [<ffffffffffffffff>] 0xffffffffffffffff
> [root@fc24 ~]# dmesg | tail
> [   97.071533] unregister_netdevice: waiting for lo to become free.
> Usage count = 1
> [   97.079561] systemd-journald[180]: Sent WATCHDOG=1 notification.
> [  107.319260] unregister_netdevice: waiting for lo to become free.
> Usage count = 1
> [  117.567180] unregister_netdevice: waiting for lo to become free.
> Usage count = 1
> [  127.807401] unregister_netdevice: waiting for lo to become free.
> Usage count = 1
> [  138.055324] unregister_netdevice: waiting for lo to become free.
> Usage count = 1
> [  148.303308] unregister_netdevice: waiting for lo to become free.
> Usage count = 1
> [  158.559118] unregister_netdevice: waiting for lo to become free.
> Usage count = 1
> [  168.807423] unregister_netdevice: waiting for lo to become free.
> Usage count = 1
> [  179.055590] unregister_netdevice: waiting for lo to become free.
> Usage count = 1
> 
> This program creates a server tcp socket, then it creates a pair of
> connected tcp sockets
> and then it does actions which trigger this problem. It calls
> connect() with AF_UNSPEC
> for one of connected sockets and then call connect() with the address
> of the server socket.
> 
> 
> Thanks,
> Andrei

> #include <string.h>
> #include <sys/socket.h>
> #include <arpa/inet.h>  /* for sockaddr_in and inet_ntoa() */
> 
> #include <stdio.h>
> #include <sys/types.h>
> #include <unistd.h>
> #include <string.h>
> #include <errno.h>
> #include <stdlib.h>
> #include <signal.h>
> #include <netinet/tcp.h>
> #include <arpa/inet.h>
> 
> 
> #define pr_err(fmt, ...)                                           \
>         printf("Error: " fmt, ##__VA_ARGS__)
> 
> #define pr_perror(fmt, ...)                                             \
>         pr_err(fmt ": %s\n", ##__VA_ARGS__, strerror(errno))
> 
> #define fail(fmt, ...)                                             \
>         pr_err(fmt ": %s\n", ##__VA_ARGS__, strerror(errno))
> 
> union sockaddr_inet {
> 	struct sockaddr addr;
> 	struct sockaddr_in v4;
> 	struct sockaddr_in6 v6;
> };
> 
> int tcp_init_server(int family, int *port)
> {
> 	union sockaddr_inet addr;
> 	int sock;
> 	int yes = 1, ret;
> 
> 	memset(&addr,0,sizeof(addr));
> 	if (family == AF_INET) {
> 		addr.v4.sin_family = family;
> 		inet_pton(family, "0.0.0.0", &(addr.v4.sin_addr));
> 	} else if (family == AF_INET6){
> 		addr.v6.sin6_family = family;
> 		inet_pton(family, "::0", &(addr.v6.sin6_addr));
> 	} else
> 		return -1;
> 
> 	sock = socket(family, SOCK_STREAM, IPPROTO_TCP);
> 	if (sock == -1) {
> 		pr_perror("socket() failed");
> 		return -1;
> 	}
> 
> 	if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1 ) {
> 		pr_perror("setsockopt() error");
> 		return -1;
> 	}
> 
> 	while (1) {
> 		if (family == AF_INET)
> 			addr.v4.sin_port = htons(*port);
> 		else if (family == AF_INET6)
> 			addr.v6.sin6_port = htons(*port);
> 
> 		ret = bind(sock, (struct sockaddr *) &addr, sizeof(addr));
> 
> 		/* criu doesn't restore sock opts, so we need this hack */
> 		if (ret == -1 && errno == EADDRINUSE) {
> 			(*port)++;
> 			continue;
> 		}
> 		break;
> 	}
> 
> 	if (ret == -1) {
> 		pr_perror("bind() failed");
> 		return -1;
> 	}
> 
> 	if (listen(sock, 1) == -1) {
> 		pr_perror("listen() failed");
> 		return -1;
> 	}
> 	return sock;
> }
> 
> int tcp_accept_server(int sock)
> {
> 	struct sockaddr_in maddr;
> 	int sock2;
> 	socklen_t addrlen;
> #ifdef DEBUG
> 	test_msg ("Waiting for connection..........\n");
> #endif
> 	addrlen = sizeof(maddr);
> 	sock2 = accept(sock,(struct sockaddr *) &maddr, &addrlen);
> 
> 	if (sock2 == -1) {
> 		pr_perror("accept() failed");
> 		return -1;
> 	}
> 
> #ifdef DEBUG
> 	test_msg ("Connection!!\n");
> #endif
> 	return sock2;
> }
> 
> int __tcp_init_client(int sock, int family, char *servIP, unsigned short servPort)
> {
> 	union sockaddr_inet servAddr;
> 
> 	/* Construct the server address structure */
> 	memset(&servAddr, 0, sizeof(servAddr));
> 	if (family == AF_INET) {
> 		servAddr.v4.sin_family      = AF_INET;
> 		servAddr.v4.sin_port        = htons(servPort);
> 		inet_pton(AF_INET, servIP, &servAddr.v4.sin_addr);
> 	} else {
> 		servAddr.v6.sin6_family      = AF_INET6;
> 		servAddr.v6.sin6_port        = htons(servPort);
> 		inet_pton(AF_INET6, servIP, &servAddr.v6.sin6_addr);
> 	}
> 	if (connect(sock, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0) {
> 		pr_perror("can't connect to server");
> 		return -1;
> 	}
> 	return sock;
> }
> 
> int tcp_init_client(int family, char *servIP, unsigned short servPort)
> {
> 	int sock;
> 
> 	if ((sock = socket(family, SOCK_STREAM, IPPROTO_TCP)) < 0) {
> 		pr_perror("can't create socket");
> 		return -1;
> 	}
> 	return __tcp_init_client(sock, family, servIP, servPort);
> }
> 
> #ifdef ZDTM_IPV6
> #define ZDTM_FAMILY AF_INET6
> #else
> #define ZDTM_FAMILY AF_INET
> #endif
> static int port = 8880;
> 
> int main(int argc, char **argv)
> {
> 	int fd, fd_s, clt, sk;
> 	union sockaddr_inet src_addr, dst_addr, addr;
> 	socklen_t aux;
> 	char c = 5;
> 
> 	sk = socket(ZDTM_FAMILY, SOCK_STREAM, 0);
> 	if (sk < 0) {
> 		pr_perror("socket");
> 		return 1;
> 	}
> 
> 	if ((fd_s = tcp_init_server(ZDTM_FAMILY, &port)) < 0) {
> 		pr_err("initializing server failed\n");
> 		return 1;
> 	}
> 
> 	clt = tcp_init_client(ZDTM_FAMILY, "localhost", port);
> 	if (clt < 0)
> 		return 1;
> 
> 	/*
> 	 * parent is server of TCP connection
> 	 */
> 	fd = tcp_accept_server(fd_s);
> 	if (fd < 0) {
> 		pr_err("can't accept client connection\n");
> 		return 1;
> 	}
> 
> 	shutdown(clt, SHUT_WR);
> 
> 	{
> 		union sockaddr_inet addr;
> 		int fd1;
> 
> 		memset(&addr, 0, sizeof(addr));
> 		addr.v4.sin_family      = AF_UNSPEC;
> 		if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)))
> 			return 1;
> 
> 		if (__tcp_init_client(fd, ZDTM_FAMILY, "localhost", port) < 0)
> 			return 1;
> 
> 		return 0;
> 		fd1 = tcp_accept_server(fd_s);
> 		if (fd1 < 0) {
> 			pr_err("can't accept client connection\n");
> 			return 1;
> 		}
> 	}
> 
> 	return 0;
> }