• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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