Path: blob/main/tools/regression/sockets/so_setfib/so_setfib.c
48254 views
/*-1* Copyright (c) 2012 Cisco Systems, Inc.2* All rights reserved.3*4* This software was developed by Bjoern Zeeb under contract to5* Cisco Systems, Inc..6*7* Redistribution and use in source and binary forms, with or without8* modification, are permitted provided that the following conditions9* are met:10* 1. Redistributions of source code must retain the above copyright11* notice, this list of conditions and the following disclaimer.12* 2. Redistributions in binary form must reproduce the above copyright13* notice, this list of conditions and the following disclaimer in the14* documentation and/or other materials provided with the distribution.15*16* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND17* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE18* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE19* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE20* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL21* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS22* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)23* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT24* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY25* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF26* SUCH DAMAGE.27*/2829/*30* Regression test on SO_SETFIB setsockopt(2).31*32* Check that the expected domain(9) families all handle the socket option33* correctly and do proper bounds checks.34*35* Test plan:36* 1. Get system wide number of FIBs from sysctl and convert to index (-= 1).37* 2. For each protocol family (INET, INET6, ROUTE and LOCAL) open socketes of38* type (STREAM, DGRAM and RAW) as supported.39* 3. Do a sequence of -2, -1, 0, .. n, n+1, n+2 SO_SETFIB sockopt calls,40* expecting the first two and last two to fail (valid 0 ... n).41* 4. Try 3 random numbers. Calculate result based on valid range.42* 5. Repeat for next domain family and type from (2) on.43*/4445#include <sys/param.h>46#include <sys/types.h>47#include <sys/socket.h>48#include <sys/sysctl.h>4950#include <err.h>51#include <errno.h>52#include <stdio.h>53#include <stdlib.h>54#include <string.h>55#include <unistd.h>5657static struct t_dom {58int domain;59const char *name;60} t_dom[] = {61#ifdef INET662{ .domain = PF_INET6, .name = "PF_INET6" },63#endif64#ifdef INET65{ .domain = PF_INET, .name = "PF_INET" },66#endif67{ .domain = PF_ROUTE, .name = "PF_ROUTE" },68{ .domain = PF_LOCAL, .name = "PF_LOCAL" },69};7071static struct t_type {72int type;73const char *name;74} t_type[] = {75{ .type = SOCK_STREAM, .name = "SOCK_STREAM" },76{ .type = SOCK_DGRAM, .name = "SOCK_DGRAM" },77{ .type = SOCK_RAW, .name = "SOCK_RAW" },78};7980/*81* Number of FIBs as read from net.fibs sysctl - 1. Initialize to clear out of82* bounds value to not accidentally run on a limited range.83*/84static int rt_numfibs = -42;8586/* Number of test case. */87static int testno = 1;888990/*91* Try the setsockopt with given FIB number i on socket s.92* Handle result given on error and valid range and errno.93*/94static void95so_setfib(int s, int i, u_int dom, u_int type)96{97int error;9899error = setsockopt(s, SOL_SOCKET, SO_SETFIB, &i, sizeof(i));100/* For out of bounds we expect an error. */101if (error == -1 && (i < 0 || i > rt_numfibs))102printf("ok %d %s_%s_%d\n", testno, t_dom[dom].name,103t_type[type].name, i);104else if (error != -1 && (i < 0 || i > rt_numfibs))105printf("not ok %d %s_%s_%d # setsockopt(%d, SOL_SOCKET, "106"SO_SETFIB, %d, ..) unexpectedly succeeded\n", testno,107t_dom[dom].name, t_type[type].name, i, s, i);108else if (error == 0)109printf("ok %d %s_%s_%d\n", testno, t_dom[dom].name,110t_type[type].name, i);111else if (errno != EINVAL)112printf("not ok %d %s_%s_%d # setsockopt(%d, SOL_SOCKET, "113"SO_SETFIB, %d, ..) unexpected error: %s\n", testno,114t_dom[dom].name, t_type[type].name, i, s, i,115strerror(errno));116else117printf("not ok %d %s_%s_%d\n", testno, t_dom[dom].name,118t_type[type].name, i);119120/* Test run done, next please. */121testno++;122}123124/*125* Main test. Open socket given domain family and type. For each FIB, out of126* bounds FIB numbers and 3 random FIB numbers set the socket option.127*/128static void129t(u_int dom, u_int type)130{131int i, s;132133/* PF_ROUTE only supports RAW socket types, while PF_LOCAL does not. */134if (t_dom[dom].domain == PF_ROUTE && t_type[type].type != SOCK_RAW)135return;136if (t_dom[dom].domain == PF_LOCAL && t_type[type].type == SOCK_RAW)137return;138139/* Open socket for given combination. */140s = socket(t_dom[dom].domain, t_type[type].type, 0);141if (s == -1) {142printf("not ok %d %s_%s # socket(): %s\n", testno,143t_dom[dom].name, t_type[type].name, strerror(errno));144testno++;145return;146}147148/* Test FIBs -2, -1, 0, .. n, n + 1, n + 2. */149for (i = -2; i <= (rt_numfibs + 2); i++)150so_setfib(s, i, dom, type);151152/* Test 3 random FIB numbers. */153for (i = 0; i < 3; i++)154so_setfib(s, (int)random(), dom, type);155156/* Close socket. */157close(s);158}159160/*161* Returns 0 if no program error, 1 on sysctlbyname error.162* Test results are communicated by printf("[not ]ok <n> ..").163*/164int165main(int argc __unused, char *argv[] __unused)166{167u_int i, j;168size_t s;169170if (geteuid() != 0) {171printf("1..0 # SKIP: must be root\n");172return (0);173}174175/* Initialize randomness. */176srandomdev();177178/* Get number of FIBs supported by kernel. */179s = sizeof(rt_numfibs);180if (sysctlbyname("net.fibs", &rt_numfibs, &s, NULL, 0) == -1)181err(1, "sysctlbyname(net.fibs, ..)");182183printf("1..%lu\n",184(nitems(t_dom) - 1) * nitems(t_type) * (2 + rt_numfibs + 2 + 3));185186/* Adjust from number to index. */187rt_numfibs -= 1;188189/* Run tests. */190for (i = 0; i < sizeof(t_dom) / sizeof(struct t_dom); i++)191for (j = 0; j < sizeof(t_type) / sizeof(struct t_type); j++)192t(i, j);193194return (0);195}196197/* end */198199200