1140109Ssobomax/*-
2140109Ssobomax * Copyright (c) 2005 Maxim Sobolev
3140109Ssobomax * All rights reserved.
4140109Ssobomax *
5140109Ssobomax * Redistribution and use in source and binary forms, with or without
6140109Ssobomax * modification, are permitted provided that the following conditions
7140109Ssobomax * are met:
8140109Ssobomax * 1. Redistributions of source code must retain the above copyright
9140109Ssobomax *    notice, this list of conditions and the following disclaimer.
10140109Ssobomax * 2. Redistributions in binary form must reproduce the above copyright
11140109Ssobomax *    notice, this list of conditions and the following disclaimer in the
12140109Ssobomax *    documentation and/or other materials provided with the distribution.
13140109Ssobomax *
14140109Ssobomax * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15140109Ssobomax * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16140109Ssobomax * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17140109Ssobomax * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18140109Ssobomax * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19140109Ssobomax * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20140109Ssobomax * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21140109Ssobomax * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22140109Ssobomax * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23140109Ssobomax * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24140109Ssobomax * SUCH DAMAGE.
25140109Ssobomax *
26140109Ssobomax * $FreeBSD: releng/10.3/tools/regression/sockets/reconnect/reconnect.c 294486 2016-01-21 05:59:33Z ngie $
27140109Ssobomax */
28140109Ssobomax
29140109Ssobomax/*
30140109Ssobomax * The reconnect regression test is designed to catch kernel bug that may
31140109Ssobomax * prevent changing association of already associated datagram unix domain
32140109Ssobomax * socket when server side of connection has been closed.
33140109Ssobomax */
34140109Ssobomax
35140109Ssobomax#include <sys/types.h>
36140109Ssobomax#include <sys/socket.h>
37140109Ssobomax#include <sys/uio.h>
38140109Ssobomax#include <sys/un.h>
39140109Ssobomax#include <err.h>
40140109Ssobomax#include <errno.h>
41140109Ssobomax#include <fcntl.h>
42140109Ssobomax#include <stdio.h>
43140109Ssobomax#include <stdlib.h>
44140109Ssobomax#include <signal.h>
45140109Ssobomax#include <string.h>
46140109Ssobomax#include <unistd.h>
47140109Ssobomax
48281974Sngiestatic char uds_name1[] = "reconnect.XXXXXXXX";
49281974Sngiestatic char uds_name2[] = "reconnect.XXXXXXXX";
50140109Ssobomax
51140109Ssobomax#define	sstosa(ss)	((struct sockaddr *)(ss))
52140109Ssobomax
53281974Sngiestatic void
54140109Ssobomaxprepare_ifsun(struct sockaddr_un *ifsun, const char *path)
55140109Ssobomax{
56140109Ssobomax
57140109Ssobomax    memset(ifsun, '\0', sizeof(*ifsun));
58140109Ssobomax#if !defined(__linux__) && !defined(__solaris__)
59140109Ssobomax    ifsun->sun_len = strlen(path);
60140109Ssobomax#endif
61140109Ssobomax    ifsun->sun_family = AF_LOCAL;
62140109Ssobomax    strcpy(ifsun->sun_path, path);
63140109Ssobomax}
64140109Ssobomax
65281974Sngiestatic int
66140109Ssobomaxcreate_uds_server(const char *path)
67140109Ssobomax{
68140109Ssobomax    struct sockaddr_un ifsun;
69140109Ssobomax    int sock;
70140109Ssobomax
71140109Ssobomax    prepare_ifsun(&ifsun, path);
72140109Ssobomax
73140109Ssobomax    unlink(ifsun.sun_path);
74140109Ssobomax
75140109Ssobomax    sock = socket(PF_LOCAL, SOCK_DGRAM, 0);
76140109Ssobomax    if (sock == -1)
77140109Ssobomax        err(1, "can't create socket");
78140109Ssobomax    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &sock, sizeof(sock));
79140109Ssobomax    if (bind(sock, sstosa(&ifsun), sizeof(ifsun)) < 0)
80140109Ssobomax        err(1, "can't bind to a socket");
81140109Ssobomax
82140109Ssobomax    return sock;
83140109Ssobomax}
84140109Ssobomax
85281974Sngiestatic void
86140109Ssobomaxconnect_uds_server(int sock, const char *path)
87140109Ssobomax{
88140109Ssobomax    struct sockaddr_un ifsun;
89140109Ssobomax    int e;
90140109Ssobomax
91140109Ssobomax    prepare_ifsun(&ifsun, path);
92140109Ssobomax
93140109Ssobomax    e = connect(sock, sstosa(&ifsun), sizeof(ifsun));
94140109Ssobomax    if (e < 0)
95140109Ssobomax        err(1, "can't connect to a socket");
96140109Ssobomax}
97140109Ssobomax
98281974Sngiestatic void
99140109Ssobomaxcleanup(void)
100140109Ssobomax{
101140109Ssobomax
102281974Sngie    unlink(uds_name1);
103281974Sngie    unlink(uds_name2);
104140109Ssobomax}
105140109Ssobomax
106140109Ssobomaxint
107294486Sngiemain(void)
108140109Ssobomax{
109140109Ssobomax    int s_sock1, s_sock2, c_sock;
110140109Ssobomax
111140109Ssobomax    atexit(cleanup);
112140109Ssobomax
113281974Sngie    if (mkstemp(uds_name1) == -1)
114281974Sngie	err(1, "mkstemp");
115281974Sngie    unlink(uds_name1);
116140109Ssobomax    s_sock1 = create_uds_server(uds_name1);
117140109Ssobomax
118281974Sngie    if (mkstemp(uds_name2) == -1)
119281974Sngie        err(1, "mkstemp");
120281974Sngie    unlink(uds_name2);
121140109Ssobomax    s_sock2 = create_uds_server(uds_name2);
122140109Ssobomax
123140109Ssobomax    c_sock = socket(PF_LOCAL, SOCK_DGRAM, 0);
124140109Ssobomax    if (c_sock < 0)
125140109Ssobomax        err(1, "can't create socket");
126140109Ssobomax
127140109Ssobomax    connect_uds_server(c_sock, uds_name1);
128140109Ssobomax    close(s_sock1);
129140109Ssobomax    connect_uds_server(c_sock, uds_name2);
130294486Sngie    close(s_sock2);
131140109Ssobomax
132140109Ssobomax    exit (0);
133140109Ssobomax}
134