1 /* $NetBSD: t_pktinfo.c,v 1.2 2013/10/19 17:45:01 christos Exp $ */
4 * Copyright (c) 2013 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
31 #include <sys/cdefs.h>
32 __RCSID("$NetBSD: t_pktinfo.c,v 1.2 2013/10/19 17:45:01 christos Exp $");
34 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <netinet/in.h>
37 #include <arpa/inet.h>
44 static const char traffic
[] = "foo";
48 #define ERR(msg) err(EXIT_FAILURE, msg)
49 #define ERRX(msg, a) errx(EXIT_FAILURE, msg, a)
50 #define ERRX2(msg, a1, a2) errx(EXIT_FAILURE, msg, a1, a2)
53 #define ERR(msg) ATF_REQUIRE_MSG(0, "%s: %s", msg, strerror(errno))
54 #define ERRX(msg, a) ATF_REQUIRE_MSG(0, msg, a)
55 #define ERRX2(msg, a1, a2) ATF_REQUIRE_MSG(0, msg, a1, a2)
59 server(struct sockaddr_in
*sin
) {
61 socklen_t len
= sizeof(*sin
);
63 if ((s
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
)) == -1)
67 sin
->sin_family
= AF_INET
;
70 sin
->sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
72 if (bind(s
, (const struct sockaddr
*)sin
, len
) == -1)
75 if (getsockname(s
, (struct sockaddr
*)sin
, &len
) == -1)
79 if (setsockopt(s
, IPPROTO_IP
, IP_PKTINFO
, &one
, sizeof(one
)) == -1)
81 if (setsockopt(s
, IPPROTO_IP
, IP_RECVPKTINFO
, &one
, sizeof(one
)) == -1)
88 client(struct sockaddr_in
*sin
) {
91 if ((s
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
)) == -1)
93 if (sendto(s
, traffic
, sizeof(traffic
), 0,
94 (const struct sockaddr
*)sin
, sizeof(*sin
)) == -1)
102 struct cmsghdr
*cmsg
;
104 char buf
[sizeof(traffic
)];
105 struct in_pktinfo
*ipi
;
106 char control
[CMSG_SPACE(sizeof(*ipi
)) * 2];
108 memset(&msg
, 0, sizeof(msg
));
112 memset(&iov
, 0, sizeof(iov
));
114 iov
.iov_len
= sizeof(buf
);
116 msg
.msg_control
= control
;
117 msg
.msg_controllen
= sizeof(control
);
120 if (recvmsg(s
, &msg
, 0) == -1)
123 for (cmsg
= CMSG_FIRSTHDR(&msg
); cmsg
!= NULL
;
124 cmsg
= CMSG_NXTHDR(&msg
, cmsg
)) {
125 if (cmsg
->cmsg_level
!= IPPROTO_IP
)
126 ERRX("bad level %d", cmsg
->cmsg_level
);
128 switch (cmsg
->cmsg_type
) {
137 ERRX("bad type %d", cmsg
->cmsg_type
);
139 ipi
= (void *)CMSG_DATA(cmsg
);
141 printf("%s message received on address %s at interface %d\n",
142 m
, inet_ntoa(ipi
->ipi_addr
), ipi
->ipi_ifindex
);
145 ATF_REQUIRE_MSG(ipi
->ipi_addr
.s_addr
== htonl(INADDR_LOOPBACK
),
146 "address 0x%x != 0x%x", ipi
->ipi_addr
.s_addr
,
147 htonl(INADDR_LOOPBACK
));
151 if (strcmp(traffic
, buf
) != 0)
152 ERRX2("Bad message '%s' != '%s'", buf
, traffic
);
158 struct sockaddr_in sin
;
169 ATF_TC_HEAD(pktinfo
, tc
)
172 atf_tc_set_md_var(tc
, "descr", "Check that IP_PKTINFO and "
173 "IP_RECVPKTINFO work");
176 ATF_TC_BODY(pktinfo
, tc
)
184 ATF_TP_ADD_TC(tp
, pktinfo
);
185 return atf_no_error();
190 main(int argc
, char *argv
[]) {