1 #include "tests.h"
2 #include <stdio.h>
3 #include <sys/socket.h>
4 #include <linux/if_packet.h>
5
6 static const char *errstr;
7
8 static long
packet_mreq_membership(int optname,void * optval,socklen_t len)9 packet_mreq_membership(int optname, void *optval, socklen_t len)
10 {
11 long rc = setsockopt(-1, SOL_PACKET, optname, optval, len);
12 errstr = sprintrc(rc);
13 return rc;
14 }
15
16 static void
test_packet_mreq(const int optname,const char * const optname_str)17 test_packet_mreq(const int optname, const char *const optname_str)
18 {
19 TAIL_ALLOC_OBJECT_CONST_PTR(struct packet_mreq, pmreq);
20 socklen_t len = sizeof(struct packet_mreq);
21
22 /* setsockopt with optname unknown */
23 packet_mreq_membership(-1, NULL, 0);
24 printf("setsockopt(-1, SOL_PACKET, %#x /* PACKET_??? */, NULL, 0) = %s\n",
25 -1, errstr);
26
27 /* setsockopt with mr_type unknown */
28 pmreq->mr_ifindex = 0;
29 pmreq->mr_alen = ARRAY_SIZE(pmreq->mr_address);
30 packet_mreq_membership(optname, pmreq, len);
31 printf("setsockopt(-1, SOL_PACKET, %s, {mr_ifindex=%d,"
32 " mr_type=%#x /* PACKET_MR_??? */, mr_alen=%d, mr_address=",
33 optname_str, pmreq->mr_ifindex, pmreq->mr_type, pmreq->mr_alen);
34 for (unsigned int i = 0; i < ARRAY_SIZE(pmreq->mr_address); i++) {
35 printf("%02x", pmreq->mr_address[i]);
36 }
37 printf("}, %d) = %s\n", len, errstr);
38
39 /* setsockopt with mr_type unknown and mr_alen > sizeof(mr_address) */
40 pmreq->mr_alen = ARRAY_SIZE(pmreq->mr_address) + 1;
41 packet_mreq_membership(optname, pmreq, len);
42 printf("setsockopt(-1, SOL_PACKET, %s, {mr_ifindex=%d,"
43 " mr_type=%#x /* PACKET_MR_??? */, mr_alen=%d, mr_address=",
44 optname_str, pmreq->mr_ifindex, pmreq->mr_type, pmreq->mr_alen);
45 for (unsigned int i = 0; i < ARRAY_SIZE(pmreq->mr_address); i++) {
46 printf("%02x", pmreq->mr_address[i]);
47 }
48 printf("}, %d) = %s\n", len, errstr);
49
50 /* setsockopt with mr_type unknown and mr_alen < sizeof(mr_address) */
51 pmreq->mr_alen = ARRAY_SIZE(pmreq->mr_address) - 1;
52 packet_mreq_membership(optname, pmreq, len);
53 printf("setsockopt(-1, SOL_PACKET, %s, {mr_ifindex=%d,"
54 " mr_type=%#x /* PACKET_MR_??? */, mr_alen=%d, mr_address=",
55 optname_str, pmreq->mr_ifindex, pmreq->mr_type, pmreq->mr_alen);
56 for (unsigned int i = 0; i < pmreq->mr_alen; i++) {
57 printf("%02x", pmreq->mr_address[i]);
58 }
59 printf("}, %d) = %s\n", len, errstr);
60
61 /* setsockopt with valid mr_type */
62 pmreq->mr_alen = ARRAY_SIZE(pmreq->mr_address);
63 static const struct {
64 unsigned short type;
65 const char *const type_str;
66 } a[] = {
67 { ARG_STR(PACKET_MR_MULTICAST) },
68 { ARG_STR(PACKET_MR_PROMISC) },
69 { ARG_STR(PACKET_MR_ALLMULTI) },
70 #ifdef PACKET_MR_UNICAST
71 { ARG_STR(PACKET_MR_UNICAST) },
72 #endif
73 };
74
75 for (unsigned int i = 0; i < ARRAY_SIZE(a); i++) {
76 pmreq->mr_type = a[i].type;
77 packet_mreq_membership(optname, pmreq, len);
78 printf("setsockopt(-1, SOL_PACKET, %s, {mr_ifindex=%d,"
79 " mr_type=%s, mr_alen=%d, mr_address=",
80 optname_str, pmreq->mr_ifindex, a[i].type_str, pmreq->mr_alen);
81 for (unsigned int i = 0; i < pmreq->mr_alen; i++) {
82 printf("%02x", pmreq->mr_address[i]);
83 }
84 printf("}, %d) = %s\n", len, errstr);
85 }
86
87 /* setsockopt with optlen larger than usual */
88 len = len + 1;
89 packet_mreq_membership(optname, pmreq, len);
90 printf("setsockopt(-1, SOL_PACKET, %s, %p,"
91 " %d) = %s\n", optname_str, pmreq, len, errstr);
92 }
93
94 int
main(void)95 main(void)
96 {
97 test_packet_mreq(ARG_STR(PACKET_ADD_MEMBERSHIP));
98 test_packet_mreq(ARG_STR(PACKET_DROP_MEMBERSHIP));
99
100 puts("+++ exited with 0 +++");
101 return 0;
102 }
103