Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Test IPV6_FLOWINFO_MGR */
0003 
0004 #define _GNU_SOURCE
0005 
0006 #include <arpa/inet.h>
0007 #include <error.h>
0008 #include <errno.h>
0009 #include <limits.h>
0010 #include <linux/in6.h>
0011 #include <stdbool.h>
0012 #include <stdio.h>
0013 #include <stdint.h>
0014 #include <stdlib.h>
0015 #include <string.h>
0016 #include <sys/socket.h>
0017 #include <sys/stat.h>
0018 #include <sys/time.h>
0019 #include <sys/types.h>
0020 #include <sys/wait.h>
0021 #include <unistd.h>
0022 
0023 /* uapi/glibc weirdness may leave this undefined */
0024 #ifndef IPV6_FLOWLABEL_MGR
0025 #define IPV6_FLOWLABEL_MGR  32
0026 #endif
0027 
0028 /* from net/ipv6/ip6_flowlabel.c */
0029 #define FL_MIN_LINGER       6
0030 
0031 #define explain(x)                          \
0032     do { if (cfg_verbose) fprintf(stderr, "       " x "\n"); } while (0)
0033 
0034 #define __expect(x)                         \
0035     do {                                \
0036         if (!(x))                       \
0037             fprintf(stderr, "[OK]   " #x "\n");     \
0038         else                            \
0039             error(1, 0, "[ERR]  " #x " (line %d)", __LINE__); \
0040     } while (0)
0041 
0042 #define expect_pass(x)  __expect(x)
0043 #define expect_fail(x)  __expect(!(x))
0044 
0045 static bool cfg_long_running;
0046 static bool cfg_verbose;
0047 
0048 static int flowlabel_get(int fd, uint32_t label, uint8_t share, uint16_t flags)
0049 {
0050     struct in6_flowlabel_req req = {
0051         .flr_action = IPV6_FL_A_GET,
0052         .flr_label = htonl(label),
0053         .flr_flags = flags,
0054         .flr_share = share,
0055     };
0056 
0057     /* do not pass IPV6_ADDR_ANY or IPV6_ADDR_MAPPED */
0058     req.flr_dst.s6_addr[0] = 0xfd;
0059     req.flr_dst.s6_addr[15] = 0x1;
0060 
0061     return setsockopt(fd, SOL_IPV6, IPV6_FLOWLABEL_MGR, &req, sizeof(req));
0062 }
0063 
0064 static int flowlabel_put(int fd, uint32_t label)
0065 {
0066     struct in6_flowlabel_req req = {
0067         .flr_action = IPV6_FL_A_PUT,
0068         .flr_label = htonl(label),
0069     };
0070 
0071     return setsockopt(fd, SOL_IPV6, IPV6_FLOWLABEL_MGR, &req, sizeof(req));
0072 }
0073 
0074 static void run_tests(int fd)
0075 {
0076     int wstatus;
0077     pid_t pid;
0078 
0079     explain("cannot get non-existent label");
0080     expect_fail(flowlabel_get(fd, 1, IPV6_FL_S_ANY, 0));
0081 
0082     explain("cannot put non-existent label");
0083     expect_fail(flowlabel_put(fd, 1));
0084 
0085     explain("cannot create label greater than 20 bits");
0086     expect_fail(flowlabel_get(fd, 0x1FFFFF, IPV6_FL_S_ANY,
0087                   IPV6_FL_F_CREATE));
0088 
0089     explain("create a new label (FL_F_CREATE)");
0090     expect_pass(flowlabel_get(fd, 1, IPV6_FL_S_ANY, IPV6_FL_F_CREATE));
0091     explain("can get the label (without FL_F_CREATE)");
0092     expect_pass(flowlabel_get(fd, 1, IPV6_FL_S_ANY, 0));
0093     explain("can get it again with create flag set, too");
0094     expect_pass(flowlabel_get(fd, 1, IPV6_FL_S_ANY, IPV6_FL_F_CREATE));
0095     explain("cannot get it again with the exclusive (FL_FL_EXCL) flag");
0096     expect_fail(flowlabel_get(fd, 1, IPV6_FL_S_ANY,
0097                      IPV6_FL_F_CREATE | IPV6_FL_F_EXCL));
0098     explain("can now put exactly three references");
0099     expect_pass(flowlabel_put(fd, 1));
0100     expect_pass(flowlabel_put(fd, 1));
0101     expect_pass(flowlabel_put(fd, 1));
0102     expect_fail(flowlabel_put(fd, 1));
0103 
0104     explain("create a new exclusive label (FL_S_EXCL)");
0105     expect_pass(flowlabel_get(fd, 2, IPV6_FL_S_EXCL, IPV6_FL_F_CREATE));
0106     explain("cannot get it again in non-exclusive mode");
0107     expect_fail(flowlabel_get(fd, 2, IPV6_FL_S_ANY,  IPV6_FL_F_CREATE));
0108     explain("cannot get it again in exclusive mode either");
0109     expect_fail(flowlabel_get(fd, 2, IPV6_FL_S_EXCL, IPV6_FL_F_CREATE));
0110     expect_pass(flowlabel_put(fd, 2));
0111 
0112     if (cfg_long_running) {
0113         explain("cannot reuse the label, due to linger");
0114         expect_fail(flowlabel_get(fd, 2, IPV6_FL_S_ANY,
0115                       IPV6_FL_F_CREATE));
0116         explain("after sleep, can reuse");
0117         sleep(FL_MIN_LINGER * 2 + 1);
0118         expect_pass(flowlabel_get(fd, 2, IPV6_FL_S_ANY,
0119                       IPV6_FL_F_CREATE));
0120     }
0121 
0122     explain("create a new user-private label (FL_S_USER)");
0123     expect_pass(flowlabel_get(fd, 3, IPV6_FL_S_USER, IPV6_FL_F_CREATE));
0124     explain("cannot get it again in non-exclusive mode");
0125     expect_fail(flowlabel_get(fd, 3, IPV6_FL_S_ANY, 0));
0126     explain("cannot get it again in exclusive mode");
0127     expect_fail(flowlabel_get(fd, 3, IPV6_FL_S_EXCL, 0));
0128     explain("can get it again in user mode");
0129     expect_pass(flowlabel_get(fd, 3, IPV6_FL_S_USER, 0));
0130     explain("child process can get it too, but not after setuid(nobody)");
0131     pid = fork();
0132     if (pid == -1)
0133         error(1, errno, "fork");
0134     if (!pid) {
0135         expect_pass(flowlabel_get(fd, 3, IPV6_FL_S_USER, 0));
0136         if (setuid(USHRT_MAX))
0137             fprintf(stderr, "[INFO] skip setuid child test\n");
0138         else
0139             expect_fail(flowlabel_get(fd, 3, IPV6_FL_S_USER, 0));
0140         exit(0);
0141     }
0142     if (wait(&wstatus) == -1)
0143         error(1, errno, "wait");
0144     if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus) != 0)
0145         error(1, errno, "wait: unexpected child result");
0146 
0147     explain("create a new process-private label (FL_S_PROCESS)");
0148     expect_pass(flowlabel_get(fd, 4, IPV6_FL_S_PROCESS, IPV6_FL_F_CREATE));
0149     explain("can get it again");
0150     expect_pass(flowlabel_get(fd, 4, IPV6_FL_S_PROCESS, 0));
0151     explain("child process cannot can get it");
0152     pid = fork();
0153     if (pid == -1)
0154         error(1, errno, "fork");
0155     if (!pid) {
0156         expect_fail(flowlabel_get(fd, 4, IPV6_FL_S_PROCESS, 0));
0157         exit(0);
0158     }
0159     if (wait(&wstatus) == -1)
0160         error(1, errno, "wait");
0161     if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus) != 0)
0162         error(1, errno, "wait: unexpected child result");
0163 }
0164 
0165 static void parse_opts(int argc, char **argv)
0166 {
0167     int c;
0168 
0169     while ((c = getopt(argc, argv, "lv")) != -1) {
0170         switch (c) {
0171         case 'l':
0172             cfg_long_running = true;
0173             break;
0174         case 'v':
0175             cfg_verbose = true;
0176             break;
0177         default:
0178             error(1, 0, "%s: parse error", argv[0]);
0179         }
0180     }
0181 }
0182 
0183 int main(int argc, char **argv)
0184 {
0185     int fd;
0186 
0187     parse_opts(argc, argv);
0188 
0189     fd = socket(PF_INET6, SOCK_DGRAM, 0);
0190     if (fd == -1)
0191         error(1, errno, "socket");
0192 
0193     run_tests(fd);
0194 
0195     if (close(fd))
0196         error(1, errno, "close");
0197 
0198     return 0;
0199 }