1136384Srwatson/*- 2136384Srwatson * Copyright (c) 2004 Robert N. M. Watson 3136384Srwatson * All rights reserved. 4136384Srwatson * 5136384Srwatson * Redistribution and use in source and binary forms, with or without 6136384Srwatson * modification, are permitted provided that the following conditions 7136384Srwatson * are met: 8136384Srwatson * 1. Redistributions of source code must retain the above copyright 9136384Srwatson * notice, this list of conditions and the following disclaimer. 10136384Srwatson * 2. Redistributions in binary form must reproduce the above copyright 11136384Srwatson * notice, this list of conditions and the following disclaimer in the 12136384Srwatson * documentation and/or other materials provided with the distribution. 13136384Srwatson * 14136384Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15136384Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16136384Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17136384Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18136384Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19136384Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20136384Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21136384Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22136384Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23136384Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24136384Srwatson * SUCH DAMAGE. 25136384Srwatson * 26136384Srwatson * $FreeBSD$ 27136384Srwatson */ 28136384Srwatson 29136384Srwatson#include <sys/types.h> 30136384Srwatson#include <sys/socket.h> 31136384Srwatson 32136384Srwatson#include <netinet/in.h> 33136384Srwatson#include <netinet/in_systm.h> 34136384Srwatson#include <netinet/ip.h> 35166437Sbms#include <arpa/inet.h> 36136384Srwatson 37136384Srwatson#include <err.h> 38136384Srwatson#include <errno.h> 39166437Sbms#include <getopt.h> 40136384Srwatson#include <stdio.h> 41136384Srwatson#include <stdlib.h> 42136384Srwatson#include <string.h> 43136384Srwatson#include <unistd.h> 44136384Srwatson 45166437Sbmsstatic int dorandom = 0; 46166437Sbmsstatic int nmcastgroups = IP_MAX_MEMBERSHIPS; 47166437Sbmsstatic int verbose = 0; 48166437Sbms 49136384Srwatson/* 50136384Srwatson * The test tool exercises IP-level socket options by interrogating the 51136384Srwatson * getsockopt()/setsockopt() APIs. It does not currently test that the 52136384Srwatson * intended semantics of each option are implemented (i.e., that setting IP 53136384Srwatson * options on the socket results in packets with the desired IP options in 54136384Srwatson * it). 55136384Srwatson */ 56136384Srwatson 57136384Srwatson/* 58136390Srwatson * get_socket() is a wrapper function that returns a socket of the specified 59136390Srwatson * type, and created with or without restored root privilege (if running 60136390Srwatson * with a real uid of root and an effective uid of some other user). This 61136390Srwatson * us to test whether the same rights are granted using a socket with a 62136390Srwatson * privileged cached credential vs. a socket with a regular credential. 63136390Srwatson */ 64136390Srwatson#define PRIV_ASIS 0 65136390Srwatson#define PRIV_GETROOT 1 66136390Srwatsonstatic int 67136390Srwatsonget_socket_unpriv(int type) 68136390Srwatson{ 69136390Srwatson 70136390Srwatson return (socket(PF_INET, type, 0)); 71136390Srwatson} 72136390Srwatson 73136390Srwatsonstatic int 74136390Srwatsonget_socket_priv(int type) 75136390Srwatson{ 76136390Srwatson uid_t olduid; 77136390Srwatson int sock; 78136390Srwatson 79136390Srwatson if (getuid() != 0) 80136390Srwatson errx(-1, "get_sock_priv: running without real uid 0"); 81136390Srwatson 82136390Srwatson olduid = geteuid(); 83136390Srwatson if (seteuid(0) < 0) 84136390Srwatson err(-1, "get_sock_priv: seteuid(0)"); 85136390Srwatson 86136390Srwatson sock = socket(PF_INET, type, 0); 87136390Srwatson 88136390Srwatson if (seteuid(olduid) < 0) 89136390Srwatson err(-1, "get_sock_priv: seteuid(%d)", olduid); 90136390Srwatson 91136390Srwatson return (sock); 92136390Srwatson} 93136390Srwatson 94136390Srwatsonstatic int 95136390Srwatsonget_socket(int type, int priv) 96136390Srwatson{ 97136390Srwatson 98136390Srwatson if (priv) 99136390Srwatson return (get_socket_priv(type)); 100136390Srwatson else 101136390Srwatson return (get_socket_unpriv(type)); 102136390Srwatson} 103136390Srwatson 104136390Srwatson/* 105136384Srwatson * Exercise the IP_OPTIONS socket option. Confirm the following properties: 106136384Srwatson * 107136384Srwatson * - That there is no initial set of options (length returned is 0). 108136384Srwatson * - That if we set a specific set of options, we can read it back. 109136384Srwatson * - That if we then reset the options, they go away. 110136384Srwatson * 111136384Srwatson * Use a UDP socket for this. 112136384Srwatson */ 113136384Srwatsonstatic void 114136390Srwatsontest_ip_options(int sock, const char *socktypename) 115136384Srwatson{ 116136384Srwatson u_int32_t new_options, test_options[2]; 117136384Srwatson socklen_t len; 118136384Srwatson 119136384Srwatson /* 120136384Srwatson * Start off by confirming the default IP options on a socket are to 121136384Srwatson * have no options set. 122136384Srwatson */ 123136384Srwatson len = sizeof(test_options); 124136384Srwatson if (getsockopt(sock, IPPROTO_IP, IP_OPTIONS, test_options, &len) < 0) 125136390Srwatson err(-1, "test_ip_options(%s): initial getsockopt()", 126136390Srwatson socktypename); 127136384Srwatson 128136384Srwatson if (len != 0) 129136390Srwatson errx(-1, "test_ip_options(%s): initial getsockopt() returned " 130136390Srwatson "%d bytes", socktypename, len); 131136384Srwatson 132136384Srwatson#define TEST_MAGIC 0xc34e4212 133136384Srwatson#define NEW_OPTIONS htonl(IPOPT_EOL | (IPOPT_NOP << 8) | (IPOPT_NOP << 16) \ 134136384Srwatson | (IPOPT_NOP << 24)) 135136384Srwatson 136136384Srwatson /* 137136384Srwatson * Write some new options into the socket. 138136384Srwatson */ 139136384Srwatson new_options = NEW_OPTIONS; 140136384Srwatson if (setsockopt(sock, IPPROTO_IP, IP_OPTIONS, &new_options, 141136384Srwatson sizeof(new_options)) < 0) 142136390Srwatson err(-1, "test_ip_options(%s): setsockopt(NOP|NOP|NOP|EOL)", 143136390Srwatson socktypename); 144136384Srwatson 145136384Srwatson /* 146136384Srwatson * Store some random cruft in a local variable and retrieve the 147136384Srwatson * options to make sure they set. Note that we pass in an array 148136384Srwatson * of u_int32_t's so that if whatever ended up in the option was 149136384Srwatson * larger than what we put in, we find out about it here. 150136384Srwatson */ 151136384Srwatson test_options[0] = TEST_MAGIC; 152136384Srwatson test_options[1] = TEST_MAGIC; 153136384Srwatson len = sizeof(test_options); 154136384Srwatson if (getsockopt(sock, IPPROTO_IP, IP_OPTIONS, test_options, &len) < 0) 155136390Srwatson err(-1, "test_ip_options(%s): getsockopt() after set", 156136390Srwatson socktypename); 157136384Srwatson 158136384Srwatson /* 159136384Srwatson * Getting the right amount back is important. 160136384Srwatson */ 161136384Srwatson if (len != sizeof(new_options)) 162136390Srwatson errx(-1, "test_ip_options(%s): getsockopt() after set " 163136390Srwatson "returned %d bytes of data", socktypename, len); 164136384Srwatson 165136384Srwatson /* 166136384Srwatson * One posible failure mode is that the call succeeds but neglects to 167136384Srwatson * copy out the data. 168136384Srwatson */ 169136384Srwatson if (test_options[0] == TEST_MAGIC) 170136390Srwatson errx(-1, "test_ip_options(%s): getsockopt() after set didn't " 171136390Srwatson "return data", socktypename); 172136384Srwatson 173136384Srwatson /* 174136384Srwatson * Make sure we get back what we wrote on. 175136384Srwatson */ 176136384Srwatson if (new_options != test_options[0]) 177136390Srwatson errx(-1, "test_ip_options(%s): getsockopt() after set " 178136390Srwatson "returned wrong options (%08x, %08x)", socktypename, 179136390Srwatson new_options, test_options[0]); 180136384Srwatson 181136384Srwatson /* 182136384Srwatson * Now we reset the value to make sure clearing works. 183136384Srwatson */ 184136384Srwatson if (setsockopt(sock, IPPROTO_IP, IP_OPTIONS, NULL, 0) < 0) 185136390Srwatson err(-1, "test_ip_options(%s): setsockopt() to reset", 186136390Srwatson socktypename); 187136384Srwatson 188136384Srwatson /* 189136384Srwatson * Make sure it was really cleared. 190136384Srwatson */ 191136384Srwatson test_options[0] = TEST_MAGIC; 192136384Srwatson test_options[1] = TEST_MAGIC; 193136384Srwatson len = sizeof(test_options); 194136384Srwatson if (getsockopt(sock, IPPROTO_IP, IP_OPTIONS, test_options, &len) < 0) 195136390Srwatson err(-1, "test_ip_options(%s): getsockopt() after reset", 196136390Srwatson socktypename); 197136384Srwatson 198136384Srwatson if (len != 0) 199136390Srwatson errx(-1, "test_ip_options(%s): getsockopt() after reset " 200136390Srwatson "returned %d bytes", socktypename, len); 201136384Srwatson} 202136384Srwatson 203136384Srwatson/* 204136384Srwatson * This test checks the behavior of the IP_HDRINCL socket option, which 205136384Srwatson * allows users with privilege to specify the full header on an IP raw 206136384Srwatson * socket. We test that the option can only be used with raw IP sockets, not 207136384Srwatson * with UDP or TCP sockets. We also confirm that the raw socket is only 208136384Srwatson * available to a privileged user (subject to the UID when called). We 209136384Srwatson * confirm that it defaults to off 210136390Srwatson * 211136390Srwatson * Unlike other tests, doesn't use caller-provided socket. Probably should 212136390Srwatson * be fixed. 213136384Srwatson */ 214136384Srwatsonstatic void 215136384Srwatsontest_ip_hdrincl(void) 216136384Srwatson{ 217136384Srwatson int flag[2], sock; 218136384Srwatson socklen_t len; 219136384Srwatson 220136384Srwatson /* 221136384Srwatson * Try to receive or set the IP_HDRINCL flag on a TCP socket. 222136384Srwatson */ 223136384Srwatson sock = socket(PF_INET, SOCK_STREAM, 0); 224136390Srwatson if (sock == -1) 225136390Srwatson err(-1, "test_ip_hdrincl(): socket(SOCK_STREAM)"); 226136384Srwatson 227136384Srwatson flag[0] = -1; 228136384Srwatson len = sizeof(flag[0]); 229136390Srwatson if (getsockopt(sock, IPPROTO_IP, IP_HDRINCL, flag, &len) == 0) 230136390Srwatson err(-1, "test_ip_hdrincl(): initial getsockopt(IP_HDRINCL)"); 231136384Srwatson 232136390Srwatson if (errno != ENOPROTOOPT) 233136390Srwatson errx(-1, "test_ip_hdrincl(): initial getsockopt(IP_HDRINC) " 234136390Srwatson "returned %d (%s) not ENOPROTOOPT", errno, 235136390Srwatson strerror(errno)); 236136384Srwatson 237136384Srwatson flag[0] = 1; 238136384Srwatson if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, flag, sizeof(flag[0])) 239136390Srwatson == 0) 240136390Srwatson err(-1,"test_ip_hdrincl(): setsockopt(IP_HDRINCL) on TCP " 241136390Srwatson "succeeded\n"); 242136384Srwatson 243136390Srwatson if (errno != ENOPROTOOPT) 244136390Srwatson errx(-1, "test_ip_hdrincl(): setsockopt(IP_HDRINCL) on TCP " 245136390Srwatson "returned %d (%s) not ENOPROTOOPT\n", errno, 246136390Srwatson strerror(errno)); 247136384Srwatson 248136384Srwatson close(sock); 249136384Srwatson 250136384Srwatson /* 251136384Srwatson * Try to receive or set the IP_HDRINCL flag on a UDP socket. 252136384Srwatson */ 253136384Srwatson sock = socket(PF_INET, SOCK_DGRAM, 0); 254136390Srwatson if (sock == -1) 255136390Srwatson err(-1, "test_ip_hdrincl(): socket(SOCK_DGRAM"); 256136384Srwatson 257136384Srwatson flag[0] = -1; 258136384Srwatson len = sizeof(flag[0]); 259136390Srwatson if (getsockopt(sock, IPPROTO_IP, IP_HDRINCL, flag, &len) == 0) 260136390Srwatson err(-1, "test_ip_hdrincl(): getsockopt(IP_HDRINCL) on UDP " 261136390Srwatson "succeeded\n"); 262136384Srwatson 263136390Srwatson if (errno != ENOPROTOOPT) 264136390Srwatson errx(-1, "test_ip_hdrincl(): getsockopt(IP_HDRINCL) on UDP " 265136390Srwatson "returned %d (%s) not ENOPROTOOPT\n", errno, 266136390Srwatson strerror(errno)); 267136384Srwatson 268136384Srwatson if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, flag, sizeof(flag[0])) 269136390Srwatson == 0) 270136390Srwatson err(-1, "test_ip_hdrincl(): setsockopt(IP_HDRINCL) on UDP " 271136390Srwatson "succeeded\n"); 272136384Srwatson 273136390Srwatson if (errno != ENOPROTOOPT) 274136390Srwatson errx(-1, "test_ip_hdrincl(): setsockopt(IP_HDRINCL) on UDP " 275136390Srwatson "returned %d (%s) not ENOPROTOOPT\n", errno, 276136390Srwatson strerror(errno)); 277136384Srwatson 278136384Srwatson close(sock); 279136384Srwatson 280136384Srwatson /* 281136384Srwatson * Now try on a raw socket. Access ontrol should prevent non-root 282136384Srwatson * users from creating the raw socket, so check that here based on 283136384Srwatson * geteuid(). If we're non-root, we just return assuming the socket 284136384Srwatson * create fails since the remainder of the tests apply only on a raw 285136384Srwatson * socket. 286136384Srwatson */ 287136384Srwatson sock = socket(PF_INET, SOCK_RAW, 0); 288136384Srwatson if (geteuid() != 0) { 289136384Srwatson if (sock != -1) 290136384Srwatson errx(-1, "test_ip_hdrincl: created raw socket as " 291136384Srwatson "uid %d", geteuid()); 292136384Srwatson return; 293136384Srwatson } 294136390Srwatson if (sock == -1) 295136390Srwatson err(-1, "test_ip_hdrincl(): socket(PF_INET, SOCK_RAW)"); 296136384Srwatson 297136384Srwatson /* 298136384Srwatson * Make sure the initial value of the flag is 0 (disabled). 299136384Srwatson */ 300136384Srwatson flag[0] = -1; 301136384Srwatson flag[1] = -1; 302136384Srwatson len = sizeof(flag); 303136390Srwatson if (getsockopt(sock, IPPROTO_IP, IP_HDRINCL, flag, &len) < 0) 304136390Srwatson err(-1, "test_ip_hdrincl(): getsockopt(IP_HDRINCL) on raw " 305136390Srwatson "socket"); 306136384Srwatson 307136390Srwatson if (len != sizeof(flag[0])) 308136390Srwatson errx(-1, "test_ip_hdrincl(): %d bytes returned on " 309136384Srwatson "initial get\n", len); 310136384Srwatson 311136390Srwatson if (flag[0] != 0) 312136390Srwatson errx(-1, "test_ip_hdrincl(): initial flag value of %d\n", 313136384Srwatson flag[0]); 314136384Srwatson 315136384Srwatson /* 316136384Srwatson * Enable the IP_HDRINCL flag. 317136384Srwatson */ 318136384Srwatson flag[0] = 1; 319136384Srwatson if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, flag, sizeof(flag[0])) 320136390Srwatson < 0) 321136390Srwatson err(-1, "test_ip_hdrincl(): setsockopt(IP_HDRINCL, 1)"); 322136384Srwatson 323136384Srwatson /* 324136384Srwatson * Check that the IP_HDRINCL flag was set. 325136384Srwatson */ 326136384Srwatson flag[0] = -1; 327136384Srwatson flag[1] = -1; 328136384Srwatson len = sizeof(flag); 329136390Srwatson if (getsockopt(sock, IPPROTO_IP, IP_HDRINCL, flag, &len) < 0) 330136390Srwatson err(-1, "test_ip_hdrincl(): getsockopt(IP_HDRINCL) after " 331136390Srwatson "set"); 332136384Srwatson 333136390Srwatson if (flag[0] == 0) 334136390Srwatson errx(-1, "test_ip_hdrincl(): getsockopt(IP_HDRINCL) " 335136384Srwatson "after set had flag of %d\n", flag[0]); 336136384Srwatson 337136384Srwatson#define HISTORICAL_INP_HDRINCL 8 338136390Srwatson if (flag[0] != HISTORICAL_INP_HDRINCL) 339136390Srwatson warnx("test_ip_hdrincl(): WARNING: getsockopt(IP_H" 340136384Srwatson "DRINCL) after set had non-historical value of %d\n", 341136384Srwatson flag[0]); 342136384Srwatson 343136384Srwatson /* 344136384Srwatson * Reset the IP_HDRINCL flag to 0. 345136384Srwatson */ 346136384Srwatson flag[0] = 0; 347136384Srwatson if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, flag, sizeof(flag[0])) 348136390Srwatson < 0) 349136390Srwatson err(-1, "test_ip_hdrincl(): setsockopt(IP_HDRINCL, 0)"); 350136384Srwatson 351136384Srwatson /* 352136384Srwatson * Check that the IP_HDRINCL flag was reset to 0. 353136384Srwatson */ 354136384Srwatson flag[0] = -1; 355136384Srwatson flag[1] = -1; 356136384Srwatson len = sizeof(flag); 357136390Srwatson if (getsockopt(sock, IPPROTO_IP, IP_HDRINCL, flag, &len) < 0) 358136390Srwatson err(-1, "test_ip_hdrincl(): getsockopt(IP_HDRINCL) after " 359136390Srwatson "reset"); 360136384Srwatson 361136390Srwatson if (flag[0] != 0) 362136390Srwatson errx(-1, "test_ip_hdrincl(): getsockopt(IP_HDRINCL) " 363136384Srwatson "after set had flag of %d\n", flag[0]); 364136384Srwatson 365136384Srwatson close(sock); 366136384Srwatson} 367136384Srwatson 368136384Srwatson/* 369136384Srwatson * As with other non-int or larger sized socket options, the IP_TOS and 370136384Srwatson * IP_TTL fields in kernel is stored as an 8-bit value, reflecting the IP 371136384Srwatson * header fields, but useful I/O to the field occurs using 32-bit integers. 372136384Srwatson * The FreeBSD kernel will permit writes from variables at least an int in 373136384Srwatson * size (and ignore additional bytes), and will permit a read to buffers 1 374136384Srwatson * byte or larger (but depending on endianness, may truncate out useful 375136384Srwatson * values if the caller provides less room). 376136384Srwatson * 377136384Srwatson * Given the limitations of the API, use a UDP socket to confirm that the 378136384Srwatson * following are true: 379136384Srwatson * 380136384Srwatson * - We can read the IP_TOS/IP_TTL options. 381136384Srwatson * - The initial value of the TOS option is 0, TTL is 64. 382136384Srwatson * - That if we provide more than 32 bits of storage, we get back only 32 383136384Srwatson * bits of data. 384136384Srwatson * - When we set it to a non-zero value expressible with a u_char, we can 385136384Srwatson * read that value back. 386136384Srwatson * - When we reset it back to zero, we can read it as 0. 387136384Srwatson * - When we set it to a value >255, the value is truncated to something less 388136384Srwatson * than 255. 389136384Srwatson */ 390136384Srwatsonstatic void 391136390Srwatsontest_ip_uchar(int sock, const char *socktypename, int option, 392136390Srwatson const char *optionname, int initial) 393136384Srwatson{ 394136390Srwatson int val[2]; 395136384Srwatson socklen_t len; 396136384Srwatson 397136384Srwatson /* 398136384Srwatson * Check that the initial value is 0, and that the size is one 399136384Srwatson * u_char; 400136384Srwatson */ 401136384Srwatson val[0] = -1; 402136384Srwatson val[1] = -1; 403136384Srwatson len = sizeof(val); 404136384Srwatson if (getsockopt(sock, IPPROTO_IP, option, val, &len) < 0) 405136390Srwatson err(-1, "test_ip_uchar(%s, %s): initial getsockopt()", 406136390Srwatson socktypename, optionname); 407136384Srwatson 408136384Srwatson if (len != sizeof(val[0])) 409136390Srwatson errx(-1, "test_ip_uchar(%s, %s): initial getsockopt() " 410136390Srwatson "returned %d bytes", socktypename, optionname, len); 411136384Srwatson 412136384Srwatson if (val[0] == -1) 413136390Srwatson errx(-1, "test_ip_uchar(%s, %s): initial getsockopt() didn't " 414136390Srwatson "return data", socktypename, optionname); 415136384Srwatson 416136384Srwatson if (val[0] != initial) 417136390Srwatson errx(-1, "test_ip_uchar(%s, %s): initial getsockopt() " 418136390Srwatson "returned value of %d, not %d", socktypename, optionname, 419136390Srwatson val[0], initial); 420136384Srwatson 421136384Srwatson /* 422136384Srwatson * Set the field to a valid value. 423136384Srwatson */ 424136384Srwatson val[0] = 128; 425136384Srwatson val[1] = -1; 426136384Srwatson if (setsockopt(sock, IPPROTO_IP, option, val, sizeof(val[0])) < 0) 427136390Srwatson err(-1, "test_ip_uchar(%s, %s): setsockopt(128)", 428136390Srwatson socktypename, optionname); 429136384Srwatson 430136384Srwatson /* 431136384Srwatson * Check that when we read back the field, we get the same value. 432136384Srwatson */ 433136384Srwatson val[0] = -1; 434136384Srwatson val[1] = -1; 435136384Srwatson len = sizeof(val); 436136384Srwatson if (getsockopt(sock, IPPROTO_IP, option, val, &len) < 0) 437136390Srwatson err(-1, "test_ip_uchar(%s, %s): getsockopt() after set to " 438136390Srwatson "128", socktypename, optionname); 439136384Srwatson 440136384Srwatson if (len != sizeof(val[0])) 441136390Srwatson errx(-1, "test_ip_uchar(%s, %s): getsockopt() after set to " 442136390Srwatson "128 returned %d bytes", socktypename, optionname, len); 443136384Srwatson 444136384Srwatson if (val[0] == -1) 445136390Srwatson errx(-1, "test_ip_uchar(%s, %s): getsockopt() after set to " 446136390Srwatson "128 didn't return data", socktypename, optionname); 447136384Srwatson 448136384Srwatson if (val[0] != 128) 449136390Srwatson errx(-1, "test_ip_uchar(%s, %s): getsockopt() after set to " 450136390Srwatson "128 returned %d", socktypename, optionname, val[0]); 451136384Srwatson 452136384Srwatson /* 453136384Srwatson * Reset the value to 0, check that it was reset. 454136384Srwatson */ 455136384Srwatson val[0] = 0; 456136384Srwatson val[1] = 0; 457136384Srwatson if (setsockopt(sock, IPPROTO_IP, option, val, sizeof(val[0])) < 0) 458136390Srwatson err(-1, "test_ip_uchar(%s, %s): setsockopt() to reset from " 459136390Srwatson "128", socktypename, optionname); 460136384Srwatson 461136384Srwatson if (len != sizeof(val[0])) 462136390Srwatson errx(-1, "test_ip_uchar(%s, %s): getsockopt() after reset " 463136390Srwatson "from 128 returned %d bytes", socktypename, optionname, 464136390Srwatson len); 465136384Srwatson 466136384Srwatson if (val[0] == -1) 467136390Srwatson errx(-1, "test_ip_uchar(%s, %s): getsockopt() after reset " 468136390Srwatson "from 128 didn't return data", socktypename, optionname); 469136384Srwatson 470136384Srwatson if (val[0] != 0) 471136390Srwatson errx(-1, "test_ip_uchar(%s, %s): getsockopt() after reset " 472136390Srwatson "from 128 returned %d", socktypename, optionname, 473136390Srwatson val[0]); 474136384Srwatson 475136384Srwatson /* 476136384Srwatson * Set the value to something out of range and check that it comes 477136384Srwatson * back truncated, or that we get EINVAL back. Traditional u_char 478136384Srwatson * IP socket options truncate, but newer ones (such as multicast 479136384Srwatson * socket options) will return EINVAL. 480136384Srwatson */ 481136384Srwatson val[0] = 32000; 482136384Srwatson val[1] = -1; 483136384Srwatson if (setsockopt(sock, IPPROTO_IP, option, val, sizeof(val[0])) < 0) { 484136384Srwatson /* 485136384Srwatson * EINVAL is a fine outcome, no need to run the truncation 486136384Srwatson * tests. 487136384Srwatson */ 488136390Srwatson if (errno == EINVAL) 489136384Srwatson return; 490136390Srwatson err(-1, "test_ip_uchar(%s, %s): getsockopt(32000)", 491136390Srwatson socktypename, optionname); 492136384Srwatson } 493136384Srwatson 494136384Srwatson val[0] = -1; 495136384Srwatson val[1] = -1; 496136384Srwatson len = sizeof(val); 497136384Srwatson if (getsockopt(sock, IPPROTO_IP, option, val, &len) < 0) 498136390Srwatson err(-1, "test_ip_uchar(%s, %s): getsockopt() after set to " 499136390Srwatson "32000", socktypename, optionname); 500136384Srwatson 501136384Srwatson if (len != sizeof(val[0])) 502136390Srwatson errx(-1, "test_ip_uchar(%s, %s): getsockopt() after set to " 503136390Srwatson "32000 returned %d bytes", socktypename, optionname, 504136390Srwatson len); 505136384Srwatson 506136384Srwatson if (val[0] == -1) 507136390Srwatson errx(-1, "test_ip_uchar(%s, %s): getsockopt() after set to " 508136390Srwatson "32000 didn't return data", socktypename, optionname); 509136384Srwatson 510136384Srwatson if (val[0] == 32000) 511136390Srwatson errx(-1, "test_ip_uchar(%s, %s): getsockopt() after set to " 512136390Srwatson "32000 returned 32000: failed to truncate", socktypename, 513136390Srwatson optionname); 514136384Srwatson} 515136384Srwatson 516136384Srwatson/* 517136384Srwatson * Generic test for a boolean socket option. Caller provides the option 518136384Srwatson * number, string name, expected default (initial) value, and whether or not 519136384Srwatson * the option is root-only. For each option, test: 520136384Srwatson * 521136384Srwatson * - That we can read the option. 522136384Srwatson * - That the initial value is as expected. 523136384Srwatson * - That we can modify the value. 524136384Srwatson * - That on modification, the new value can be read back. 525136384Srwatson * - That we can reset the value. 526136384Srwatson * - that on reset, the new value can be read back. 527136384Srwatson */ 528136384Srwatson#define BOOLEAN_ANYONE 1 529136384Srwatson#define BOOLEAN_ROOTONLY 1 530136384Srwatsonstatic void 531136390Srwatsontest_ip_boolean(int sock, const char *socktypename, int option, 532136390Srwatson char *optionname, int initial, int rootonly) 533136384Srwatson{ 534136390Srwatson int newvalue, val[2]; 535136384Srwatson socklen_t len; 536136384Srwatson 537136384Srwatson /* 538136384Srwatson * The default for a boolean might be true or false. If it's false, 539136384Srwatson * we will try setting it to true (but using a non-1 value of true). 540136384Srwatson * If it's true, we'll set it to false. 541136384Srwatson */ 542136384Srwatson if (initial == 0) 543136384Srwatson newvalue = 0xff; 544136384Srwatson else 545136384Srwatson newvalue = 0; 546136384Srwatson 547136384Srwatson val[0] = -1; 548136384Srwatson val[1] = -1; 549136384Srwatson len = sizeof(val); 550136384Srwatson if (getsockopt(sock, IPPROTO_IP, option, val, &len) < 0) 551136384Srwatson err(-1, "test_ip_boolean: initial getsockopt()"); 552136384Srwatson 553136384Srwatson if (len != sizeof(val[0])) 554136390Srwatson errx(-1, "test_ip_boolean(%s, %s): initial getsockopt() " 555136390Srwatson "returned %d bytes", socktypename, optionname, len); 556136384Srwatson 557136384Srwatson if (val[0] == -1) 558136390Srwatson errx(-1, "test_ip_boolean(%s, %s): initial getsockopt() " 559136390Srwatson "didn't return data", socktypename, optionname); 560136384Srwatson 561136384Srwatson if (val[0] != initial) 562136390Srwatson errx(-1, "test_ip_boolean(%s, %s): initial getsockopt() " 563136390Srwatson "returned %d (expected %d)", socktypename, optionname, 564136390Srwatson val[0], initial); 565136384Srwatson 566136384Srwatson /* 567136384Srwatson * Set the socket option to a new non-default value. 568136384Srwatson */ 569136384Srwatson if (setsockopt(sock, IPPROTO_IP, option, &newvalue, sizeof(newvalue)) 570136384Srwatson < 0) 571136390Srwatson err(-1, "test_ip_boolean(%s, %s): setsockopt() to %d", 572136390Srwatson socktypename, optionname, newvalue); 573136384Srwatson 574136384Srwatson /* 575136384Srwatson * Read the value back and see if it is not the default (note: will 576136384Srwatson * not be what we set it to, as we set it to 0xff above). 577136384Srwatson */ 578136384Srwatson val[0] = -1; 579136384Srwatson val[1] = -1; 580136384Srwatson len = sizeof(val); 581136384Srwatson if (getsockopt(sock, IPPROTO_IP, option, val, &len) < 0) 582136390Srwatson err(-1, "test_ip_boolean(%s, %s): getsockopt() after set to " 583136390Srwatson "%d", socktypename, optionname, newvalue); 584136384Srwatson 585136384Srwatson if (len != sizeof(val[0])) 586136390Srwatson errx(-1, "test_ip_boolean(%s, %s): getsockopt() after set " 587136390Srwatson "to %d returned %d bytes", socktypename, optionname, 588136390Srwatson newvalue, len); 589136384Srwatson 590136384Srwatson if (val[0] == -1) 591136390Srwatson errx(-1, "test_ip_boolean(%s, %s): getsockopt() after set " 592136390Srwatson "to %d didn't return data", socktypename, optionname, 593136390Srwatson newvalue); 594136384Srwatson 595136384Srwatson /* 596136384Srwatson * If we set it to true, check for '1', otherwise '0. 597136384Srwatson */ 598136384Srwatson if (val[0] != (newvalue ? 1 : 0)) 599136390Srwatson errx(-1, "test_ip_boolean(%s, %s): getsockopt() after set " 600136390Srwatson "to %d returned %d", socktypename, optionname, newvalue, 601136390Srwatson val[0]); 602136384Srwatson 603136384Srwatson /* 604136384Srwatson * Reset to initial value. 605136384Srwatson */ 606136384Srwatson newvalue = initial; 607136384Srwatson if (setsockopt(sock, IPPROTO_IP, option, &newvalue, sizeof(newvalue)) 608136384Srwatson < 0) 609136390Srwatson err(-1, "test_ip_boolean(%s, %s): setsockopt() to reset", 610136390Srwatson socktypename, optionname); 611136384Srwatson 612136384Srwatson /* 613136384Srwatson * Check reset version. 614136384Srwatson */ 615136384Srwatson val[0] = -1; 616136384Srwatson val[1] = -1; 617136384Srwatson len = sizeof(val); 618136384Srwatson if (getsockopt(sock, IPPROTO_IP, option, val, &len) < 0) 619136390Srwatson err(-1, "test_ip_boolean(%s, %s): getsockopt() after reset", 620136390Srwatson socktypename, optionname); 621136384Srwatson 622136384Srwatson if (len != sizeof(val[0])) 623136390Srwatson errx(-1, "test_ip_boolean(%s, %s): getsockopt() after reset " 624136390Srwatson "returned %d bytes", socktypename, optionname, len); 625136384Srwatson 626136384Srwatson if (val[0] == -1) 627136390Srwatson errx(-1, "test_ip_boolean(%s, %s): getsockopt() after reset " 628136390Srwatson "didn't return data", socktypename, optionname); 629136384Srwatson 630136384Srwatson if (val[0] != newvalue) 631136390Srwatson errx(-1, "test_ip_boolean(%s, %s): getsockopt() after reset " 632136390Srwatson "returned %d", socktypename, optionname, newvalue); 633136384Srwatson} 634136384Srwatson 635136384Srwatson/* 636158561Sbms * Test the IP_ADD_MEMBERSHIP socket option, and the dynamic allocator 637158561Sbms * for the imo_membership vector which now hangs off struct ip_moptions. 638158561Sbms * We then call IP_DROP_MEMBERSHIP for each group so joined. 639158561Sbms */ 640158561Sbmsstatic void 641158561Sbmstest_ip_multicast_membership(int sock, const char *socktypename) 642158561Sbms{ 643166437Sbms char addrbuf[16]; 644158561Sbms struct ip_mreq mreq; 645158561Sbms uint32_t basegroup; 646158561Sbms uint16_t i; 647158561Sbms int sotype; 648158561Sbms socklen_t sotypelen; 649158561Sbms 650158561Sbms sotypelen = sizeof(sotype); 651158561Sbms if (getsockopt(sock, SOL_SOCKET, SO_TYPE, &sotype, &sotypelen) < 0) 652158561Sbms err(-1, "test_ip_multicast_membership(%s): so_type getsockopt()", 653158561Sbms socktypename); 654158561Sbms /* 655158561Sbms * Do not perform the test for SOCK_STREAM sockets, as this makes 656158561Sbms * no sense. 657158561Sbms */ 658158561Sbms if (sotype == SOCK_STREAM) 659158561Sbms return; 660158561Sbms /* 661166437Sbms * The 224/8 range is administratively scoped and has special meaning, 662166437Sbms * therefore it is not used for this test. 663166437Sbms * If we were not told to be non-deterministic: 664166437Sbms * Join multicast groups from 238.1.1.0 up to nmcastgroups. 665166437Sbms * Otherwise, pick a multicast group ID in subnet 238/5 with 11 random 666166437Sbms * bits in the middle, and join groups in linear order up to nmcastgroups. 667158561Sbms */ 668166437Sbms if (dorandom) { 669166437Sbms /* be non-deterministic (for interactive operation; a fuller test) */ 670166437Sbms srandomdev(); 671166437Sbms basegroup = 0xEE000000; /* 238.0.0.0 */ 672166437Sbms basegroup |= ((random() % ((1 << 11) - 1)) << 16); /* 11 bits */ 673166437Sbms } else { 674166437Sbms /* be deterministic (for automated operation) */ 675166437Sbms basegroup = 0xEE010100; /* 238.1.1.0 */ 676166437Sbms } 677158561Sbms /* 678158561Sbms * Join the multicast group(s) on the default multicast interface; 679158561Sbms * this usually maps to the interface to which the default 680158561Sbms * route is pointing. 681158561Sbms */ 682170613Sbms for (i = 1; i < nmcastgroups+1; i++) { 683168548Sbms mreq.imr_multiaddr.s_addr = htonl((basegroup + i)); 684158561Sbms mreq.imr_interface.s_addr = INADDR_ANY; 685166437Sbms inet_ntop(AF_INET, &mreq.imr_multiaddr, addrbuf, sizeof(addrbuf)); 686166437Sbms if (verbose) 687166437Sbms fprintf(stderr, "IP_ADD_MEMBERSHIP %s INADDR_ANY\n", addrbuf); 688158561Sbms if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, 689158561Sbms sizeof(mreq)) < 0) { 690158561Sbms err(-1, 691158561Sbms"test_ip_multicast_membership(%d, %s): failed IP_ADD_MEMBERSHIP (%s, %s)", 692166437Sbms sock, socktypename, addrbuf, "INADDR_ANY"); 693158561Sbms } 694158561Sbms } 695170613Sbms for (i = 1; i < nmcastgroups+1; i++) { 696168548Sbms mreq.imr_multiaddr.s_addr = htonl((basegroup + i)); 697158561Sbms mreq.imr_interface.s_addr = INADDR_ANY; 698166437Sbms inet_ntop(AF_INET, &mreq.imr_multiaddr, addrbuf, sizeof(addrbuf)); 699166437Sbms if (verbose) 700166437Sbms fprintf(stderr, "IP_DROP_MEMBERSHIP %s INADDR_ANY\n", addrbuf); 701158561Sbms if (setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, 702158561Sbms sizeof(mreq)) < 0) { 703158561Sbms err(-1, 704158561Sbms"test_ip_multicast_membership(%d, %s): failed IP_DROP_MEMBERSHIP (%s, %s)", 705166437Sbms sock, socktypename, addrbuf, "INADDR_ANY"); 706158561Sbms } 707158561Sbms } 708158561Sbms} 709158561Sbms 710158561Sbms/* 711136384Srwatson * XXX: For now, nothing here. 712136384Srwatson */ 713136384Srwatsonstatic void 714136390Srwatsontest_ip_multicast_if(int sock, const char *socktypename) 715136384Srwatson{ 716136384Srwatson 717136384Srwatson /* 718136384Srwatson * It's probably worth trying INADDR_ANY and INADDR_LOOPBACK here 719136384Srwatson * to see what happens. 720136384Srwatson */ 721136384Srwatson} 722136384Srwatson 723136384Srwatson/* 724136384Srwatson * XXX: For now, nothing here. 725136384Srwatson */ 726136384Srwatsonstatic void 727136390Srwatsontest_ip_multicast_vif(int sock, const char *socktypename) 728136384Srwatson{ 729136384Srwatson 730136384Srwatson /* 731136384Srwatson * This requires some knowledge of the number of virtual interfaces, 732136384Srwatson * and what is valid. 733136384Srwatson */ 734136384Srwatson} 735136384Srwatson 736136384Srwatsonstatic void 737136390Srwatsontestsuite(int priv) 738136384Srwatson{ 739136390Srwatson const char *socktypenameset[] = {"SOCK_DGRAM", "SOCK_STREAM", 740136390Srwatson "SOCK_RAW"}; 741136390Srwatson int socktypeset[] = {SOCK_DGRAM, SOCK_STREAM, SOCK_RAW}; 742136390Srwatson const char *socktypename; 743136390Srwatson int i, sock, socktype; 744136384Srwatson 745136390Srwatson test_ip_hdrincl(); 746136384Srwatson 747136390Srwatson for (i = 0; i < sizeof(socktypeset)/sizeof(int); i++) { 748136390Srwatson socktype = socktypeset[i]; 749136390Srwatson socktypename = socktypenameset[i]; 750136384Srwatson 751136390Srwatson /* 752136390Srwatson * If we can't acquire root privilege, we can't open raw 753136390Srwatson * sockets, so don't actually try. 754136390Srwatson */ 755136390Srwatson if (getuid() != 0 && socktype == SOCK_RAW) 756136390Srwatson continue; 757136391Srwatson if (geteuid() != 0 && !priv && socktype == SOCK_RAW) 758136391Srwatson continue; 759136384Srwatson 760136390Srwatson /* 761136390Srwatson * XXXRW: On 5.3, this seems not to work for SOCK_RAW. 762136390Srwatson */ 763136390Srwatson sock = get_socket(socktype, priv); 764136390Srwatson if (sock == -1) 765136390Srwatson err(-1, "get_socket(%s, %d) for test_ip_uchar(IP_TOS)", 766136390Srwatson socktypename, priv); 767136390Srwatson test_ip_uchar(sock, socktypename, IP_TOS, "IP_TOS", 0); 768136390Srwatson close(sock); 769136384Srwatson 770136390Srwatson sock = get_socket(socktype, priv); 771136390Srwatson if (sock == -1) 772136390Srwatson err(-1, "get_socket(%s %d) for test_ip_uchar(IP_TTL)", 773136390Srwatson socktypename, priv); 774136390Srwatson test_ip_uchar(sock, socktypename, IP_TTL, "IP_TTL", 64); 775136390Srwatson close(sock); 776136384Srwatson 777136390Srwatson sock = get_socket(socktype, priv); 778136390Srwatson if (sock == -1) 779136390Srwatson err(-1, "get_socket(%s, %d) for test_ip_boolean" 780136390Srwatson "(IP_RECVOPTS)", socktypename, priv); 781136390Srwatson test_ip_boolean(sock, socktypename, IP_RECVOPTS, 782136390Srwatson "IP_RECVOPTS", 0, BOOLEAN_ANYONE); 783136390Srwatson close(sock); 784136384Srwatson 785136390Srwatson sock = get_socket(socktype, priv); 786136390Srwatson if (sock == -1) 787136390Srwatson err(-1, "get_socket(%s, %d) for test_ip_boolean" 788136390Srwatson "(IP_RECVRETOPTS)", socktypename, priv); 789136390Srwatson test_ip_boolean(sock, socktypename, IP_RECVRETOPTS, 790136390Srwatson "IP_RECVRETOPTS", 0, BOOLEAN_ANYONE); 791136390Srwatson close(sock); 792136384Srwatson 793136390Srwatson sock = get_socket(socktype, priv); 794136390Srwatson if (sock == -1) 795136390Srwatson err(-1, "get_socket(%s, %d) for test_ip_boolean" 796136390Srwatson "(IP_RECVDSTADDR)", socktypename, priv); 797136390Srwatson test_ip_boolean(sock, socktypename, IP_RECVDSTADDR, 798136390Srwatson "IP_RECVDSTADDR", 0, BOOLEAN_ANYONE); 799136390Srwatson close(sock); 800136384Srwatson 801136390Srwatson sock = get_socket(socktype, priv); 802136390Srwatson if (sock == -1) 803136390Srwatson err(-1, "get_socket(%s, %d) for test_ip_boolean" 804136390Srwatson "(IP_RECVTTL)", socktypename, priv); 805136390Srwatson test_ip_boolean(sock, socktypename, IP_RECVTTL, "IP_RECVTTL", 806136390Srwatson 0, BOOLEAN_ANYONE); 807136390Srwatson close(sock); 808136384Srwatson 809136390Srwatson sock = get_socket(socktype, priv); 810136390Srwatson if (sock == -1) 811136390Srwatson err(-1, "get_socket(%s, %d) for test_ip_boolean" 812136390Srwatson "(IP_RECVIF)", socktypename, priv); 813136390Srwatson test_ip_boolean(sock, socktypename, IP_RECVIF, "IP_RECVIF", 814136390Srwatson 0, BOOLEAN_ANYONE); 815136390Srwatson close(sock); 816136384Srwatson 817136390Srwatson sock = get_socket(socktype, priv); 818136390Srwatson if (sock == -1) 819136390Srwatson err(-1, "get_socket(%s, %d) for test_ip_boolean" 820136390Srwatson "(IP_FAITH)", socktypename, priv); 821136390Srwatson test_ip_boolean(sock, socktypename, IP_FAITH, "IP_FAITH", 0, 822136390Srwatson BOOLEAN_ANYONE); 823136390Srwatson close(sock); 824136390Srwatson 825136390Srwatson sock = get_socket(socktype, priv); 826136390Srwatson if (sock == -1) 827136390Srwatson err(-1, "get_socket(%s, %d) for test_ip_boolean" 828136390Srwatson "(IP_ONESBCAST)", socktypename, priv); 829136390Srwatson test_ip_boolean(sock, socktypename, IP_ONESBCAST, 830136390Srwatson "IP_ONESBCAST", 0, BOOLEAN_ANYONE); 831136390Srwatson close(sock); 832136390Srwatson 833136390Srwatson /* 834136390Srwatson * Test the multicast TTL exactly as we would the regular 835136390Srwatson * TTL, only expect a different default. 836136390Srwatson */ 837136390Srwatson sock = get_socket(socktype, priv); 838136390Srwatson if (sock == -1) 839136390Srwatson err(-1, "get_socket(%s, %d) for IP_MULTICAST_TTL", 840136390Srwatson socktypename, priv); 841136390Srwatson test_ip_uchar(sock, socktypename, IP_MULTICAST_TTL, 842136390Srwatson "IP_MULTICAST_TTL", 1); 843136390Srwatson close(sock); 844136390Srwatson 845136390Srwatson /* 846136390Srwatson * The multicast loopback flag can be tested using our 847136390Srwatson * boolean tester, but only because the FreeBSD API is a bit 848136390Srwatson * more flexible than earlir APIs and will accept an int as 849136390Srwatson * well as a u_char. Loopback is enabled by default. 850136390Srwatson */ 851136390Srwatson sock = get_socket(socktype, priv); 852136390Srwatson if (sock == -1) 853136390Srwatson err(-1, "get_socket(%s, %d) for IP_MULTICAST_LOOP", 854136390Srwatson socktypename, priv); 855136390Srwatson test_ip_boolean(sock, socktypename, IP_MULTICAST_LOOP, 856136390Srwatson "IP_MULTICAST_LOOP", 1, BOOLEAN_ANYONE); 857136390Srwatson close(sock); 858136390Srwatson 859136390Srwatson sock = get_socket(socktype, priv); 860136390Srwatson if (sock == -1) 861136390Srwatson err(-1, "get_socket(%s, %d) for test_ip_options", 862136390Srwatson socktypename, priv); 863136390Srwatson //test_ip_options(sock, socktypename); 864136390Srwatson close(sock); 865136390Srwatson 866158561Sbms sock = get_socket(socktype, priv); 867158561Sbms if (sock == -1) 868158561Sbms err(-1, "get_socket(%s, %d) for test_ip_options", 869158561Sbms socktypename, priv); 870158561Sbms test_ip_multicast_membership(sock, socktypename); 871158561Sbms close(sock); 872158561Sbms 873136390Srwatson test_ip_multicast_if(0, NULL); 874136390Srwatson test_ip_multicast_vif(0, NULL); 875136390Srwatson /* 876136390Srwatson * XXX: Still need to test: 877136390Srwatson * IP_PORTRANGE 878136390Srwatson * IP_IPSEC_POLICY? 879136390Srwatson */ 880136390Srwatson } 881136384Srwatson} 882136384Srwatson 883166437Sbmsstatic void 884166437Sbmsusage() 885166437Sbms{ 886166437Sbms 887166437Sbms fprintf(stderr, "usage: ipsockopt [-M ngroups] [-r] [-v]\n"); 888166437Sbms exit(EXIT_FAILURE); 889166437Sbms} 890166437Sbms 891136384Srwatson/* 892136384Srwatson * Very simply exercise that we can get and set each option. If we're running 893136384Srwatson * as root, run it also as nobody. If not as root, complain about that. 894136384Srwatson */ 895136384Srwatsonint 896136384Srwatsonmain(int argc, char *argv[]) 897136384Srwatson{ 898166437Sbms int ch; 899136384Srwatson 900166437Sbms while ((ch = getopt(argc, argv, "M:rv")) != -1) { 901166437Sbms switch (ch) { 902166437Sbms case 'M': 903166437Sbms nmcastgroups = atoi(optarg); 904166437Sbms break; 905166437Sbms case 'r': 906166437Sbms dorandom = 1; /* introduce non-determinism */ 907166437Sbms break; 908166437Sbms case 'v': 909166437Sbms verbose = 1; 910166437Sbms break; 911166437Sbms default: 912166437Sbms usage(); 913166437Sbms } 914166437Sbms } 915166437Sbms 916137587Snik printf("1..1\n"); 917166437Sbms 918136384Srwatson if (geteuid() != 0) { 919136390Srwatson warnx("Not running as root, can't run tests as root"); 920136384Srwatson fprintf(stderr, "\n"); 921136390Srwatson fprintf(stderr, 922136390Srwatson "Running tests with uid %d sock uid %d\n", geteuid(), 923136390Srwatson geteuid()); 924136390Srwatson testsuite(PRIV_ASIS); 925136384Srwatson } else { 926136390Srwatson fprintf(stderr, 927136390Srwatson "Running tests with ruid %d euid %d sock uid 0\n", 928136390Srwatson getuid(), geteuid()); 929136390Srwatson testsuite(PRIV_ASIS); 930136390Srwatson if (seteuid(65534) != 0) 931136390Srwatson err(-1, "seteuid(65534)"); 932136390Srwatson fprintf(stderr, 933136391Srwatson "Running tests with ruid %d euid %d sock uid 65534\n", 934136391Srwatson getuid(), geteuid()); 935136391Srwatson testsuite(PRIV_ASIS); 936136391Srwatson fprintf(stderr, 937136390Srwatson "Running tests with ruid %d euid %d sock uid 0\n", 938136390Srwatson getuid(), geteuid()); 939136390Srwatson testsuite(PRIV_GETROOT); 940136384Srwatson } 941137587Snik printf("ok 1 - ipsockopt\n"); 942136384Srwatson exit(0); 943136384Srwatson} 944