2 * Check decoding of getsockopt and setsockopt for SOL_NETLINK level.
4 * Copyright (c) 2017-2018 Dmitry V. Levin <ldv@altlinux.org>
7 * SPDX-License-Identifier: GPL-2.0-or-later
15 # define SOL_NETLINK 270
19 static const char *errstr;
22 get_sockopt(int fd, int name, void *val, socklen_t *len)
24 rc = getsockopt(fd, SOL_NETLINK, name, val, len);
25 errstr = sprintrc(rc);
30 set_sockopt(int fd, int name, void *val, socklen_t len)
32 rc = setsockopt(fd, SOL_NETLINK, name, val, len);
33 errstr = sprintrc(rc);
44 #ifdef NETLINK_ADD_MEMBERSHIP
45 { ARG_STR(NETLINK_ADD_MEMBERSHIP) },
47 #ifdef NETLINK_DROP_MEMBERSHIP
48 { ARG_STR(NETLINK_DROP_MEMBERSHIP) },
50 #ifdef NETLINK_PKTINFO
51 { ARG_STR(NETLINK_PKTINFO) },
53 #ifdef NETLINK_BROADCAST_ERROR
54 { ARG_STR(NETLINK_BROADCAST_ERROR) },
56 #ifdef NETLINK_NO_ENOBUFS
57 { ARG_STR(NETLINK_NO_ENOBUFS) },
59 #ifdef NETLINK_RX_RING
60 { ARG_STR(NETLINK_RX_RING) },
62 #ifdef NETLINK_TX_RING
63 { ARG_STR(NETLINK_TX_RING) },
65 #ifdef NETLINK_LISTEN_ALL_NSID
66 { ARG_STR(NETLINK_LISTEN_ALL_NSID) },
68 #ifdef NETLINK_LIST_MEMBERSHIPS
69 { ARG_STR(NETLINK_LIST_MEMBERSHIPS) },
71 #ifdef NETLINK_CAP_ACK
72 { ARG_STR(NETLINK_CAP_ACK) },
74 #ifdef NETLINK_EXT_ACK
75 { ARG_STR(NETLINK_EXT_ACK) },
79 TAIL_ALLOC_OBJECT_CONST_PTR(int, val);
80 TAIL_ALLOC_OBJECT_CONST_PTR(socklen_t, len);
81 void *const efault = val + 1;
82 int fd = socket(AF_NETLINK, SOCK_RAW, 0);
84 perror_msg_and_skip("socket AF_NETLINK SOCK_RAW");
87 for (i = 0; i < ARRAY_SIZE(names); ++i) {
92 get_sockopt(fd, names[i].val, val, len);
93 printf("getsockopt(%d, SOL_NETLINK, %s, ", fd, names[i].str);
98 printf(", [%d]) = %s\n", *len, errstr);
100 /* optlen larger than necessary - shortened */
101 *len = sizeof(*val) + 1;
102 get_sockopt(fd, names[i].val, val, len);
103 printf("getsockopt(%d, SOL_NETLINK, %s, ", fd, names[i].str);
107 printf("[%d]", *val);
108 printf(", [%d", (int) sizeof(*val) + 1);
109 if ((int) sizeof(*val) + 1 != *len)
110 printf("->%d", *len);
111 printf("]) = %s\n", errstr);
113 /* zero optlen - print returned optlen */
115 get_sockopt(fd, names[i].val, NULL, len);
116 printf("getsockopt(%d, SOL_NETLINK, %s, NULL, [0",
119 printf("->%d", *len);
120 printf("]) = %s\n", errstr);
122 #ifdef NETLINK_LIST_MEMBERSHIPS
123 if (names[i].val != NETLINK_LIST_MEMBERSHIPS) {
125 /* optlen shorter than necessary - print address */
126 *len = sizeof(*val) - 1;
127 get_sockopt(fd, names[i].val, val, len);
128 printf("getsockopt(%d, SOL_NETLINK, %s, %p, [%d",
129 fd, names[i].str, val, (int) sizeof(*val) - 1);
130 if ((int) sizeof(*val) - 1 != *len)
131 printf("->%d", *len);
132 printf("]) = %s\n", errstr);
133 #ifdef NETLINK_LIST_MEMBERSHIPS
135 /* optlen shorter than required for the first element */
136 *len = sizeof(*val) - 1;
137 get_sockopt(fd, names[i].val, efault, len);
138 printf("getsockopt(%d, SOL_NETLINK, %s, ",
141 printf("%p", efault);
144 printf(", [%d", (int) sizeof(*val) - 1);
145 if ((int) sizeof(*val) - 1 != *len)
146 printf("->%d", *len);
147 printf("]) = %s\n", errstr);
151 /* optval EFAULT - print address */
153 get_sockopt(fd, names[i].val, efault, len);
154 printf("getsockopt(%d, SOL_NETLINK, %s, %p, [%d]) = %s\n",
155 fd, names[i].str, efault, *len, errstr);
157 /* optlen EFAULT - print address */
158 get_sockopt(fd, names[i].val, val, len + 1);
159 printf("getsockopt(%d, SOL_NETLINK, %s, %p, %p) = %s\n",
160 fd, names[i].str, val, len + 1, errstr);
166 set_sockopt(fd, names[i].val, val, sizeof(*val));
167 printf("setsockopt(%d, SOL_NETLINK, %s, [%d], %d) = %s\n",
168 fd, names[i].str, *val, (int) sizeof(*val), errstr);
170 /* optlen larger than necessary - shortened */
171 set_sockopt(fd, names[i].val, val, sizeof(*val) + 1);
172 printf("setsockopt(%d, SOL_NETLINK, %s, [%d], %d) = %s\n",
173 fd, names[i].str, *val, (int) sizeof(*val) + 1, errstr);
175 /* optlen < 0 - print address */
176 set_sockopt(fd, names[i].val, val, -1U);
177 printf("setsockopt(%d, SOL_NETLINK, %s, %p, -1) = %s\n",
178 fd, names[i].str, val, errstr);
180 /* optlen smaller than necessary - print address */
181 set_sockopt(fd, names[i].val, val, sizeof(*val) - 1);
182 printf("setsockopt(%d, SOL_NETLINK, %s, %p, %d) = %s\n",
183 fd, names[i].str, val, (int) sizeof(*val) - 1, errstr);
185 /* optval EFAULT - print address */
186 set_sockopt(fd, names[i].val, efault, sizeof(*val));
187 printf("setsockopt(%d, SOL_NETLINK, %s, %p, %d) = %s\n",
188 fd, names[i].str, efault, (int) sizeof(*val), errstr);
191 puts("+++ exited with 0 +++");