17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 50f1702c5SYu Xiangning * Common Development and Distribution License (the "License"). 60f1702c5SYu Xiangning * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 223e95bd4aSAnders Persson * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. 23*19581f84SAlexander Eremin * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include <ctype.h> 27d2b5b2d3SAnders Persson #include <dirent.h> 28d2b5b2d3SAnders Persson #include <errno.h> 297c478bd9Sstevel@tonic-gate #include <locale.h> 30d2b5b2d3SAnders Persson #include <stdio.h> 31d2b5b2d3SAnders Persson #include <stdlib.h> 32d2b5b2d3SAnders Persson #include <string.h> 333e95bd4aSAnders Persson #include <sys/socket.h> 343e95bd4aSAnders Persson #include <sys/socketvar.h> 35d2b5b2d3SAnders Persson #include <sys/stat.h> 36d2b5b2d3SAnders Persson #include <unistd.h> 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate #define MAXLINELEN 4096 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate /* 417c478bd9Sstevel@tonic-gate * Usage: 42d2b5b2d3SAnders Persson * soconfig -d <dir> 43d2b5b2d3SAnders Persson * Reads input from files in dir. 44d2b5b2d3SAnders Persson * 45d2b5b2d3SAnders Persson * soconfig -f <file> 467c478bd9Sstevel@tonic-gate * Reads input from file. The file is structured as 470f1702c5SYu Xiangning * <fam> <type> <protocol> <path|module> 487c478bd9Sstevel@tonic-gate * <fam> <type> <protocol> 497c478bd9Sstevel@tonic-gate * with the first line registering and the second line 507c478bd9Sstevel@tonic-gate * deregistering. 517c478bd9Sstevel@tonic-gate * 520f1702c5SYu Xiangning * soconfig <fam> <type> <protocol> <path|module> 537c478bd9Sstevel@tonic-gate * registers 547c478bd9Sstevel@tonic-gate * 557c478bd9Sstevel@tonic-gate * soconfig <fam> <type> <protocol> 567c478bd9Sstevel@tonic-gate * deregisters 573e95bd4aSAnders Persson * 58*19581f84SAlexander Eremin * soconfig -l 59*19581f84SAlexander Eremin * print the in-kernel socket configuration table 60*19581f84SAlexander Eremin * 613e95bd4aSAnders Persson * Filter Operations (Consolidation Private): 623e95bd4aSAnders Persson * 633e95bd4aSAnders Persson * soconfig -F <name> <modname> {auto [top | bottom | before:filter | 643e95bd4aSAnders Persson * after:filter] | prog} <fam>:<type>:<proto>,... 653e95bd4aSAnders Persson * configure filter 663e95bd4aSAnders Persson * 673e95bd4aSAnders Persson * soconfig -F <name> 683e95bd4aSAnders Persson * unconfigures filter 697c478bd9Sstevel@tonic-gate */ 707c478bd9Sstevel@tonic-gate 71d2b5b2d3SAnders Persson static int parse_files_in_dir(const char *dir); 72d2b5b2d3SAnders Persson 737c478bd9Sstevel@tonic-gate static int parse_file(char *filename); 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate static int split_line(char *line, char *argvec[], int maxargvec); 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate static int parse_params(char *famstr, char *typestr, char *protostr, 78d2b5b2d3SAnders Persson char *path, const char *file, int line); 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate static int parse_int(char *str); 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate static void usage(void); 837c478bd9Sstevel@tonic-gate 843e95bd4aSAnders Persson static int parse_filter_params(int argc, char **argv); 853e95bd4aSAnders Persson 86*19581f84SAlexander Eremin static int print_socktable(); 87*19581f84SAlexander Eremin 887c478bd9Sstevel@tonic-gate int 897c478bd9Sstevel@tonic-gate main(argc, argv) 907c478bd9Sstevel@tonic-gate int argc; 917c478bd9Sstevel@tonic-gate char *argv[]; 927c478bd9Sstevel@tonic-gate { 937c478bd9Sstevel@tonic-gate int ret; 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate argc--; argv++; 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 987c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 997c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 1007c478bd9Sstevel@tonic-gate #endif 1017c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 1027c478bd9Sstevel@tonic-gate 103*19581f84SAlexander Eremin if (argc == 1 && strcmp(argv[0], "-l") == 0) { 104*19581f84SAlexander Eremin ret = print_socktable(); 105*19581f84SAlexander Eremin exit(ret); 106*19581f84SAlexander Eremin } 107*19581f84SAlexander Eremin 1083e95bd4aSAnders Persson if (argc >= 2 && strcmp(argv[0], "-F") == 0) { 1093e95bd4aSAnders Persson argc--; argv++; 1103e95bd4aSAnders Persson ret = parse_filter_params(argc, argv); 1113e95bd4aSAnders Persson exit(ret); 1123e95bd4aSAnders Persson } 113d2b5b2d3SAnders Persson if (argc == 2 && strcmp(argv[0], "-d") == 0) { 114d2b5b2d3SAnders Persson ret = parse_files_in_dir(argv[1]); 115d2b5b2d3SAnders Persson exit(ret); 116d2b5b2d3SAnders Persson } 1177c478bd9Sstevel@tonic-gate if (argc == 2 && strcmp(argv[0], "-f") == 0) { 1187c478bd9Sstevel@tonic-gate ret = parse_file(argv[1]); 1197c478bd9Sstevel@tonic-gate exit(ret); 1207c478bd9Sstevel@tonic-gate } 1217c478bd9Sstevel@tonic-gate if (argc == 3) { 122d2b5b2d3SAnders Persson ret = parse_params(argv[0], argv[1], argv[2], NULL, NULL, -1); 1237c478bd9Sstevel@tonic-gate exit(ret); 1247c478bd9Sstevel@tonic-gate } 1257c478bd9Sstevel@tonic-gate if (argc == 4) { 126d2b5b2d3SAnders Persson ret = parse_params(argv[0], argv[1], argv[2], argv[3], 127d2b5b2d3SAnders Persson NULL, -1); 1287c478bd9Sstevel@tonic-gate exit(ret); 1297c478bd9Sstevel@tonic-gate } 1307c478bd9Sstevel@tonic-gate usage(); 1317c478bd9Sstevel@tonic-gate exit(1); 1327c478bd9Sstevel@tonic-gate /* NOTREACHED */ 1337c478bd9Sstevel@tonic-gate } 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate static void 1367c478bd9Sstevel@tonic-gate usage(void) 1377c478bd9Sstevel@tonic-gate { 1387c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 139d2b5b2d3SAnders Persson "Usage: soconfig -d <dir>\n" 140d2b5b2d3SAnders Persson "\tsoconfig -f <file>\n" 1410f1702c5SYu Xiangning "\tsoconfig <fam> <type> <protocol> <path|module>\n" 142*19581f84SAlexander Eremin "\tsoconfig <fam> <type> <protocol>\n" 143*19581f84SAlexander Eremin "\tsoconfig -l\n")); 1447c478bd9Sstevel@tonic-gate } 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate /* 147d2b5b2d3SAnders Persson * Parse all files in the given directory. 148d2b5b2d3SAnders Persson */ 149d2b5b2d3SAnders Persson static int 150d2b5b2d3SAnders Persson parse_files_in_dir(const char *dirname) 151d2b5b2d3SAnders Persson { 152d2b5b2d3SAnders Persson DIR *dp; 153d2b5b2d3SAnders Persson struct dirent *dirp; 154d2b5b2d3SAnders Persson struct stat stats; 155d2b5b2d3SAnders Persson char buf[MAXPATHLEN]; 156d2b5b2d3SAnders Persson 157d2b5b2d3SAnders Persson if ((dp = opendir(dirname)) == NULL) { 158d2b5b2d3SAnders Persson fprintf(stderr, gettext("failed to open directory '%s': %s\n"), 159d2b5b2d3SAnders Persson dirname, strerror(errno)); 160d2b5b2d3SAnders Persson return (1); 161d2b5b2d3SAnders Persson } 162d2b5b2d3SAnders Persson 163d2b5b2d3SAnders Persson while ((dirp = readdir(dp)) != NULL) { 164d2b5b2d3SAnders Persson if (dirp->d_name[0] == '.') 165d2b5b2d3SAnders Persson continue; 166d2b5b2d3SAnders Persson 167d2b5b2d3SAnders Persson if (snprintf(buf, sizeof (buf), "%s/%s", dirname, 168d2b5b2d3SAnders Persson dirp->d_name) >= sizeof (buf)) { 169d2b5b2d3SAnders Persson fprintf(stderr, 170d2b5b2d3SAnders Persson gettext("path name is too long: %s/%s\n"), 171d2b5b2d3SAnders Persson dirname, dirp->d_name); 172d2b5b2d3SAnders Persson continue; 173d2b5b2d3SAnders Persson } 174d2b5b2d3SAnders Persson if (stat(buf, &stats) == -1) { 175d2b5b2d3SAnders Persson fprintf(stderr, 176d2b5b2d3SAnders Persson gettext("failed to stat '%s': %s\n"), buf, 177d2b5b2d3SAnders Persson strerror(errno)); 178d2b5b2d3SAnders Persson continue; 179d2b5b2d3SAnders Persson } 180d2b5b2d3SAnders Persson if (!S_ISREG(stats.st_mode)) 181d2b5b2d3SAnders Persson continue; 182d2b5b2d3SAnders Persson 183d2b5b2d3SAnders Persson (void) parse_file(buf); 184d2b5b2d3SAnders Persson } 185d2b5b2d3SAnders Persson 186d2b5b2d3SAnders Persson closedir(dp); 187d2b5b2d3SAnders Persson 188d2b5b2d3SAnders Persson return (0); 189d2b5b2d3SAnders Persson } 190d2b5b2d3SAnders Persson 191d2b5b2d3SAnders Persson /* 1927c478bd9Sstevel@tonic-gate * Open the specified file and parse each line. Skip comments (everything 1937c478bd9Sstevel@tonic-gate * after a '#'). Return 1 if at least one error was encountered; otherwise 0. 1947c478bd9Sstevel@tonic-gate */ 1957c478bd9Sstevel@tonic-gate static int 1967c478bd9Sstevel@tonic-gate parse_file(char *filename) 1977c478bd9Sstevel@tonic-gate { 1987c478bd9Sstevel@tonic-gate char line[MAXLINELEN]; 1997c478bd9Sstevel@tonic-gate char pline[MAXLINELEN]; 2007c478bd9Sstevel@tonic-gate int argcount; 2017c478bd9Sstevel@tonic-gate char *argvec[20]; 2027c478bd9Sstevel@tonic-gate FILE *fp; 2037c478bd9Sstevel@tonic-gate int linecount = 0; 2047c478bd9Sstevel@tonic-gate int numerror = 0; 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate fp = fopen(filename, "r"); 2077c478bd9Sstevel@tonic-gate if (fp == NULL) { 2087c478bd9Sstevel@tonic-gate perror("soconfig: open"); 2097c478bd9Sstevel@tonic-gate fprintf(stderr, "\n"); 2107c478bd9Sstevel@tonic-gate usage(); 2117c478bd9Sstevel@tonic-gate return (1); 2127c478bd9Sstevel@tonic-gate } 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate while (fgets(line, sizeof (line) - 1, fp) != NULL) { 2157c478bd9Sstevel@tonic-gate linecount++; 2167c478bd9Sstevel@tonic-gate strcpy(pline, line); 2177c478bd9Sstevel@tonic-gate argcount = split_line(pline, argvec, 2187c478bd9Sstevel@tonic-gate sizeof (argvec) / sizeof (argvec[0])); 2197c478bd9Sstevel@tonic-gate #ifdef DEBUG 2207c478bd9Sstevel@tonic-gate { 2217c478bd9Sstevel@tonic-gate int i; 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate printf("scanned %d args\n", argcount); 2247c478bd9Sstevel@tonic-gate for (i = 0; i < argcount; i++) 2257c478bd9Sstevel@tonic-gate printf("arg[%d]: %s\n", i, argvec[i]); 2267c478bd9Sstevel@tonic-gate } 2277c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 2287c478bd9Sstevel@tonic-gate switch (argcount) { 2297c478bd9Sstevel@tonic-gate case 0: 2307c478bd9Sstevel@tonic-gate /* Empty line - or comment only line */ 2317c478bd9Sstevel@tonic-gate break; 2327c478bd9Sstevel@tonic-gate case 3: 2337c478bd9Sstevel@tonic-gate numerror += parse_params(argvec[0], argvec[1], 234d2b5b2d3SAnders Persson argvec[2], NULL, filename, linecount); 2357c478bd9Sstevel@tonic-gate break; 2367c478bd9Sstevel@tonic-gate case 4: 2377c478bd9Sstevel@tonic-gate numerror += parse_params(argvec[0], argvec[1], 238d2b5b2d3SAnders Persson argvec[2], argvec[3], filename, linecount); 2397c478bd9Sstevel@tonic-gate break; 2407c478bd9Sstevel@tonic-gate default: 2417c478bd9Sstevel@tonic-gate numerror++; 2427c478bd9Sstevel@tonic-gate fprintf(stderr, 2437c478bd9Sstevel@tonic-gate gettext("Malformed line: <%s>\n"), line); 2447c478bd9Sstevel@tonic-gate fprintf(stderr, 245d2b5b2d3SAnders Persson gettext("\ton line %d in %s\n"), linecount, 246d2b5b2d3SAnders Persson filename); 2477c478bd9Sstevel@tonic-gate break; 2487c478bd9Sstevel@tonic-gate } 2497c478bd9Sstevel@tonic-gate } 2507c478bd9Sstevel@tonic-gate (void) fclose(fp); 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate if (numerror > 0) 2537c478bd9Sstevel@tonic-gate return (1); 2547c478bd9Sstevel@tonic-gate else 2557c478bd9Sstevel@tonic-gate return (0); 2567c478bd9Sstevel@tonic-gate } 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate /* 2597c478bd9Sstevel@tonic-gate * Parse a line splitting it off at whitspace characters. 2607c478bd9Sstevel@tonic-gate * Modifies the content of the string by inserting NULLs. 2617c478bd9Sstevel@tonic-gate */ 2627c478bd9Sstevel@tonic-gate static int 2637c478bd9Sstevel@tonic-gate split_line(char *line, char *argvec[], int maxargvec) 2647c478bd9Sstevel@tonic-gate { 2657c478bd9Sstevel@tonic-gate int i = 0; 2667c478bd9Sstevel@tonic-gate char *cp; 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate /* Truncate at the beginning of a comment */ 2697c478bd9Sstevel@tonic-gate cp = strchr(line, '#'); 2707c478bd9Sstevel@tonic-gate if (cp != NULL) 2717c478bd9Sstevel@tonic-gate *cp = NULL; 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate /* CONSTCOND */ 2747c478bd9Sstevel@tonic-gate while (1) { 2757c478bd9Sstevel@tonic-gate /* Skip any whitespace */ 2767c478bd9Sstevel@tonic-gate while (isspace(*line) && *line != NULL) 2777c478bd9Sstevel@tonic-gate line++; 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate if (i >= maxargvec) 2807c478bd9Sstevel@tonic-gate return (i); 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate argvec[i] = line; 2837c478bd9Sstevel@tonic-gate if (*line == NULL) 2847c478bd9Sstevel@tonic-gate return (i); 2857c478bd9Sstevel@tonic-gate i++; 2867c478bd9Sstevel@tonic-gate /* Skip until next whitespace */ 2877c478bd9Sstevel@tonic-gate while (!isspace(*line) && *line != NULL) 2887c478bd9Sstevel@tonic-gate line++; 2897c478bd9Sstevel@tonic-gate if (*line != NULL) { 2907c478bd9Sstevel@tonic-gate /* Break off argument */ 2917c478bd9Sstevel@tonic-gate *line++ = NULL; 2927c478bd9Sstevel@tonic-gate } 2937c478bd9Sstevel@tonic-gate } 2947c478bd9Sstevel@tonic-gate /* NOTREACHED */ 2957c478bd9Sstevel@tonic-gate } 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate /* 2987c478bd9Sstevel@tonic-gate * Parse the set of parameters and issues the sockconfig syscall. 2997c478bd9Sstevel@tonic-gate * If line is not -1 it is assumed to be the line number in the file. 3007c478bd9Sstevel@tonic-gate */ 3017c478bd9Sstevel@tonic-gate static int 302d2b5b2d3SAnders Persson parse_params(char *famstr, char *typestr, char *protostr, char *path, 303d2b5b2d3SAnders Persson const char *file, int line) 3047c478bd9Sstevel@tonic-gate { 3053e95bd4aSAnders Persson int cmd, fam, type, protocol; 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate fam = parse_int(famstr); 3087c478bd9Sstevel@tonic-gate if (fam == -1) { 3097c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Bad family number: %s\n"), famstr); 3107c478bd9Sstevel@tonic-gate if (line != -1) 3117c478bd9Sstevel@tonic-gate fprintf(stderr, 312d2b5b2d3SAnders Persson gettext("\ton line %d in %s\n"), line, file); 3137c478bd9Sstevel@tonic-gate else { 3147c478bd9Sstevel@tonic-gate fprintf(stderr, "\n"); 3157c478bd9Sstevel@tonic-gate usage(); 3167c478bd9Sstevel@tonic-gate } 3177c478bd9Sstevel@tonic-gate return (1); 3187c478bd9Sstevel@tonic-gate } 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate type = parse_int(typestr); 3217c478bd9Sstevel@tonic-gate if (type == -1) { 3227c478bd9Sstevel@tonic-gate fprintf(stderr, 3237c478bd9Sstevel@tonic-gate gettext("Bad socket type number: %s\n"), typestr); 3247c478bd9Sstevel@tonic-gate if (line != -1) 3257c478bd9Sstevel@tonic-gate fprintf(stderr, 326d2b5b2d3SAnders Persson gettext("\ton line %d in %s\n"), line, file); 3277c478bd9Sstevel@tonic-gate else { 3287c478bd9Sstevel@tonic-gate fprintf(stderr, "\n"); 3297c478bd9Sstevel@tonic-gate usage(); 3307c478bd9Sstevel@tonic-gate } 3317c478bd9Sstevel@tonic-gate return (1); 3327c478bd9Sstevel@tonic-gate } 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate protocol = parse_int(protostr); 3357c478bd9Sstevel@tonic-gate if (protocol == -1) { 3367c478bd9Sstevel@tonic-gate fprintf(stderr, 3377c478bd9Sstevel@tonic-gate gettext("Bad protocol number: %s\n"), protostr); 3387c478bd9Sstevel@tonic-gate if (line != -1) 3397c478bd9Sstevel@tonic-gate fprintf(stderr, 340d2b5b2d3SAnders Persson gettext("\ton line %d in %s\n"), line, file); 3417c478bd9Sstevel@tonic-gate else { 3427c478bd9Sstevel@tonic-gate fprintf(stderr, "\n"); 3437c478bd9Sstevel@tonic-gate usage(); 3447c478bd9Sstevel@tonic-gate } 3457c478bd9Sstevel@tonic-gate return (1); 3467c478bd9Sstevel@tonic-gate } 3477c478bd9Sstevel@tonic-gate 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate if (path != NULL) { 3507c478bd9Sstevel@tonic-gate struct stat stats; 3517c478bd9Sstevel@tonic-gate 3520f1702c5SYu Xiangning if (strncmp(path, "/dev", strlen("/dev")) == 0 && 3530f1702c5SYu Xiangning stat(path, &stats) == -1) { 3547c478bd9Sstevel@tonic-gate perror(path); 3557c478bd9Sstevel@tonic-gate if (line != -1) 3567c478bd9Sstevel@tonic-gate fprintf(stderr, 357d2b5b2d3SAnders Persson gettext("\ton line %d in %s\n"), line, 358d2b5b2d3SAnders Persson file); 3597c478bd9Sstevel@tonic-gate else { 3607c478bd9Sstevel@tonic-gate fprintf(stderr, "\n"); 3617c478bd9Sstevel@tonic-gate usage(); 3627c478bd9Sstevel@tonic-gate } 3637c478bd9Sstevel@tonic-gate return (1); 3647c478bd9Sstevel@tonic-gate } 3653e95bd4aSAnders Persson 3663e95bd4aSAnders Persson cmd = SOCKCONFIG_ADD_SOCK; 3673e95bd4aSAnders Persson } else { 3683e95bd4aSAnders Persson cmd = SOCKCONFIG_REMOVE_SOCK; 3697c478bd9Sstevel@tonic-gate } 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate #ifdef DEBUG 3723e95bd4aSAnders Persson printf("not calling sockconfig(%d, %d, %d, %d, %s)\n", 3733e95bd4aSAnders Persson cmd, fam, type, protocol, path == NULL ? "(null)" : path); 3747c478bd9Sstevel@tonic-gate #else 3753e95bd4aSAnders Persson if (_sockconfig(cmd, fam, type, protocol, path) == -1) { 376d2b5b2d3SAnders Persson char *s; 377d2b5b2d3SAnders Persson 378d2b5b2d3SAnders Persson switch (errno) { 379d2b5b2d3SAnders Persson case EEXIST: 380d2b5b2d3SAnders Persson s = gettext("Mapping exists"); 381d2b5b2d3SAnders Persson break; 382d2b5b2d3SAnders Persson default: 383d2b5b2d3SAnders Persson s = strerror(errno); 384d2b5b2d3SAnders Persson break; 385d2b5b2d3SAnders Persson } 386d2b5b2d3SAnders Persson 387d2b5b2d3SAnders Persson fprintf(stderr, 388d2b5b2d3SAnders Persson gettext("warning: socket configuration failed " 389d2b5b2d3SAnders Persson "for family %d type %d protocol %d: %s\n"), 390d2b5b2d3SAnders Persson fam, type, protocol, s); 391d2b5b2d3SAnders Persson if (line != -1) { 392d2b5b2d3SAnders Persson fprintf(stderr, 393d2b5b2d3SAnders Persson gettext("\ton line %d in %s\n"), line, file); 394d2b5b2d3SAnders Persson } 3957c478bd9Sstevel@tonic-gate return (1); 3967c478bd9Sstevel@tonic-gate } 3977c478bd9Sstevel@tonic-gate #endif 3987c478bd9Sstevel@tonic-gate return (0); 3997c478bd9Sstevel@tonic-gate } 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate static int 4027c478bd9Sstevel@tonic-gate parse_int(char *str) 4037c478bd9Sstevel@tonic-gate { 4047c478bd9Sstevel@tonic-gate char *end; 4057c478bd9Sstevel@tonic-gate int res; 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate res = strtol(str, &end, 0); 4087c478bd9Sstevel@tonic-gate if (end == str) 4097c478bd9Sstevel@tonic-gate return (-1); 4107c478bd9Sstevel@tonic-gate return (res); 4117c478bd9Sstevel@tonic-gate } 4123e95bd4aSAnders Persson 4133e95bd4aSAnders Persson /* 4143e95bd4aSAnders Persson * Add and remove socket filters. 4153e95bd4aSAnders Persson */ 4163e95bd4aSAnders Persson static int 4173e95bd4aSAnders Persson parse_filter_params(int argc, char **argv) 4183e95bd4aSAnders Persson { 4193e95bd4aSAnders Persson struct sockconfig_filter_props filprop; 4203e95bd4aSAnders Persson sof_socktuple_t *socktuples; 4213e95bd4aSAnders Persson size_t tupcnt, nalloc; 4223e95bd4aSAnders Persson char *hintarg, *socktup, *tupstr; 4233e95bd4aSAnders Persson int i; 4243e95bd4aSAnders Persson 4253e95bd4aSAnders Persson if (argc == 1) { 4263e95bd4aSAnders Persson if (_sockconfig(SOCKCONFIG_REMOVE_FILTER, argv[0], 0, 4273e95bd4aSAnders Persson 0, 0) < 0) { 4283e95bd4aSAnders Persson switch (errno) { 4293e95bd4aSAnders Persson case ENXIO: 4303e95bd4aSAnders Persson fprintf(stderr, 4313e95bd4aSAnders Persson gettext("socket filter is not configured " 4323e95bd4aSAnders Persson "'%s'\n"), argv[0]); 4333e95bd4aSAnders Persson break; 4343e95bd4aSAnders Persson default: 4353e95bd4aSAnders Persson perror("sockconfig"); 4363e95bd4aSAnders Persson break; 4373e95bd4aSAnders Persson } 4383e95bd4aSAnders Persson return (1); 4393e95bd4aSAnders Persson } 4403e95bd4aSAnders Persson return (0); 4413e95bd4aSAnders Persson } 4423e95bd4aSAnders Persson 4433e95bd4aSAnders Persson if (argc < 4 || argc > 5) 4443e95bd4aSAnders Persson return (1); 4453e95bd4aSAnders Persson 4463e95bd4aSAnders Persson 4473e95bd4aSAnders Persson if (strlen(argv[1]) >= MODMAXNAMELEN) { 4483e95bd4aSAnders Persson fprintf(stderr, 4493e95bd4aSAnders Persson gettext("invalid module name '%s': name too long\n"), 4503e95bd4aSAnders Persson argv[1]); 4513e95bd4aSAnders Persson return (1); 4523e95bd4aSAnders Persson } 4533e95bd4aSAnders Persson filprop.sfp_modname = argv[1]; 4543e95bd4aSAnders Persson 4553e95bd4aSAnders Persson /* Check the attach semantics */ 4563e95bd4aSAnders Persson if (strcmp(argv[2], "auto") == 0) { 4573e95bd4aSAnders Persson filprop.sfp_autoattach = B_TRUE; 4583e95bd4aSAnders Persson if (argc == 5) { 4593e95bd4aSAnders Persson /* placement hint */ 4603e95bd4aSAnders Persson if (strcmp(argv[3], "top") == 0) { 4613e95bd4aSAnders Persson filprop.sfp_hint = SOF_HINT_TOP; 4623e95bd4aSAnders Persson } else if (strcmp(argv[3], "bottom") == 0) { 4633e95bd4aSAnders Persson filprop.sfp_hint = SOF_HINT_BOTTOM; 4643e95bd4aSAnders Persson } else { 4653e95bd4aSAnders Persson if (strncmp(argv[3], "before", 6) == 0) { 4663e95bd4aSAnders Persson filprop.sfp_hint = SOF_HINT_BEFORE; 4673e95bd4aSAnders Persson } else if (strncmp(argv[3], "after", 5) == 0) { 4683e95bd4aSAnders Persson filprop.sfp_hint = SOF_HINT_AFTER; 4693e95bd4aSAnders Persson } else { 4703e95bd4aSAnders Persson fprintf(stderr, 4713e95bd4aSAnders Persson gettext("invalid placement hint " 4723e95bd4aSAnders Persson "'%s'\n"), argv[3]); 4733e95bd4aSAnders Persson return (1); 4743e95bd4aSAnders Persson } 4753e95bd4aSAnders Persson 4763e95bd4aSAnders Persson hintarg = strchr(argv[3], ':'); 4773e95bd4aSAnders Persson if (hintarg == NULL || 4783e95bd4aSAnders Persson (strlen(++hintarg) == 0) || 4793e95bd4aSAnders Persson (strlen(hintarg) >= FILNAME_MAX)) { 4803e95bd4aSAnders Persson fprintf(stderr, 4813e95bd4aSAnders Persson gettext("invalid placement hint " 4823e95bd4aSAnders Persson "argument '%s': name too long\n"), 4833e95bd4aSAnders Persson argv[3]); 4843e95bd4aSAnders Persson return (1); 4853e95bd4aSAnders Persson } 4863e95bd4aSAnders Persson 4873e95bd4aSAnders Persson filprop.sfp_hintarg = hintarg; 4883e95bd4aSAnders Persson } 4893e95bd4aSAnders Persson } else { 4903e95bd4aSAnders Persson filprop.sfp_hint = SOF_HINT_NONE; 4913e95bd4aSAnders Persson } 4923e95bd4aSAnders Persson } else if (strcmp(argv[2], "prog") == 0) { 4933e95bd4aSAnders Persson filprop.sfp_autoattach = B_FALSE; 4943e95bd4aSAnders Persson filprop.sfp_hint = SOF_HINT_NONE; 4953e95bd4aSAnders Persson /* cannot specify placement hint for programmatic filter */ 4963e95bd4aSAnders Persson if (argc == 5) { 4973e95bd4aSAnders Persson fprintf(stderr, 4983e95bd4aSAnders Persson gettext("placement hint specified for programmatic " 4993e95bd4aSAnders Persson "filter\n")); 5003e95bd4aSAnders Persson return (1); 5013e95bd4aSAnders Persson } 5023e95bd4aSAnders Persson } else { 5033e95bd4aSAnders Persson fprintf(stderr, gettext("invalid attach semantic '%s'\n"), 5043e95bd4aSAnders Persson argv[2]); 5053e95bd4aSAnders Persson return (1); 5063e95bd4aSAnders Persson } 5073e95bd4aSAnders Persson 5083e95bd4aSAnders Persson /* parse the socket tuples */ 5093e95bd4aSAnders Persson nalloc = 4; 5103e95bd4aSAnders Persson socktuples = calloc(nalloc, sizeof (sof_socktuple_t)); 5113e95bd4aSAnders Persson if (socktuples == NULL) { 5123e95bd4aSAnders Persson perror("calloc"); 5133e95bd4aSAnders Persson return (1); 5143e95bd4aSAnders Persson } 5153e95bd4aSAnders Persson 5163e95bd4aSAnders Persson tupcnt = 0; 5173e95bd4aSAnders Persson tupstr = argv[(argc == 4) ? 3 : 4]; 5183e95bd4aSAnders Persson while ((socktup = strsep(&tupstr, ",")) != NULL) { 5193e95bd4aSAnders Persson int val; 5203e95bd4aSAnders Persson char *valstr; 5213e95bd4aSAnders Persson 5223e95bd4aSAnders Persson if (tupcnt == nalloc) { 5233e95bd4aSAnders Persson sof_socktuple_t *new; 5243e95bd4aSAnders Persson 5253e95bd4aSAnders Persson nalloc *= 2; 5263e95bd4aSAnders Persson new = realloc(socktuples, 5273e95bd4aSAnders Persson nalloc * sizeof (sof_socktuple_t)); 5283e95bd4aSAnders Persson if (new == NULL) { 5293e95bd4aSAnders Persson perror("realloc"); 5303e95bd4aSAnders Persson free(socktuples); 5313e95bd4aSAnders Persson return (1); 5323e95bd4aSAnders Persson } 5333e95bd4aSAnders Persson socktuples = new; 5343e95bd4aSAnders Persson } 5353e95bd4aSAnders Persson i = 0; 5363e95bd4aSAnders Persson while ((valstr = strsep(&socktup, ":")) != NULL && i < 3) { 5373e95bd4aSAnders Persson val = parse_int(valstr); 5383e95bd4aSAnders Persson if (val == -1) { 5393e95bd4aSAnders Persson fprintf(stderr, gettext("bad socket tuple\n")); 5403e95bd4aSAnders Persson free(socktuples); 5413e95bd4aSAnders Persson return (1); 5423e95bd4aSAnders Persson } 5433e95bd4aSAnders Persson switch (i) { 5443e95bd4aSAnders Persson case 0: socktuples[tupcnt].sofst_family = val; break; 5453e95bd4aSAnders Persson case 1: socktuples[tupcnt].sofst_type = val; break; 5463e95bd4aSAnders Persson case 2: socktuples[tupcnt].sofst_protocol = val; break; 5473e95bd4aSAnders Persson } 5483e95bd4aSAnders Persson i++; 5493e95bd4aSAnders Persson } 5503e95bd4aSAnders Persson if (i != 3) { 5513e95bd4aSAnders Persson fprintf(stderr, gettext("bad socket tuple\n")); 5523e95bd4aSAnders Persson free(socktuples); 5533e95bd4aSAnders Persson return (1); 5543e95bd4aSAnders Persson } 5553e95bd4aSAnders Persson tupcnt++; 5563e95bd4aSAnders Persson } 5573e95bd4aSAnders Persson if (tupcnt == 0) { 5583e95bd4aSAnders Persson fprintf(stderr, gettext("no socket tuples specified\n")); 5593e95bd4aSAnders Persson free(socktuples); 5603e95bd4aSAnders Persson return (1); 5613e95bd4aSAnders Persson } 5623e95bd4aSAnders Persson filprop.sfp_socktuple_cnt = tupcnt; 5633e95bd4aSAnders Persson filprop.sfp_socktuple = socktuples; 5643e95bd4aSAnders Persson 5653e95bd4aSAnders Persson if (_sockconfig(SOCKCONFIG_ADD_FILTER, argv[0], &filprop, 0, 0) < 0) { 5663e95bd4aSAnders Persson switch (errno) { 5673e95bd4aSAnders Persson case EINVAL: 5683e95bd4aSAnders Persson fprintf(stderr, 5693e95bd4aSAnders Persson gettext("invalid socket filter configuration\n")); 5703e95bd4aSAnders Persson break; 5713e95bd4aSAnders Persson case EEXIST: 5723e95bd4aSAnders Persson fprintf(stderr, 5733e95bd4aSAnders Persson gettext("socket filter is already configured " 5743e95bd4aSAnders Persson "'%s'\n"), argv[0]); 5753e95bd4aSAnders Persson break; 5763e95bd4aSAnders Persson case ENOSPC: 5773e95bd4aSAnders Persson fprintf(stderr, gettext("unable to satisfy placement " 5783e95bd4aSAnders Persson "constraint\n")); 5793e95bd4aSAnders Persson break; 5803e95bd4aSAnders Persson default: 5813e95bd4aSAnders Persson perror("sockconfig"); 5823e95bd4aSAnders Persson break; 5833e95bd4aSAnders Persson } 5843e95bd4aSAnders Persson free(socktuples); 5853e95bd4aSAnders Persson return (1); 5863e95bd4aSAnders Persson } 5873e95bd4aSAnders Persson free(socktuples); 5883e95bd4aSAnders Persson return (0); 5893e95bd4aSAnders Persson } 590*19581f84SAlexander Eremin 591*19581f84SAlexander Eremin /* 592*19581f84SAlexander Eremin * Print the in-kernel socket configuration table 593*19581f84SAlexander Eremin */ 594*19581f84SAlexander Eremin 595*19581f84SAlexander Eremin static int 596*19581f84SAlexander Eremin print_socktable() 597*19581f84SAlexander Eremin { 598*19581f84SAlexander Eremin sockconfig_socktable_t sc_table; 599*19581f84SAlexander Eremin int i; 600*19581f84SAlexander Eremin 601*19581f84SAlexander Eremin (void) memset(&sc_table, 0, sizeof (sockconfig_socktable_t)); 602*19581f84SAlexander Eremin 603*19581f84SAlexander Eremin /* get number of entries */ 604*19581f84SAlexander Eremin if (_sockconfig(SOCKCONFIG_GET_SOCKTABLE, &sc_table) == -1) { 605*19581f84SAlexander Eremin fprintf(stderr, 606*19581f84SAlexander Eremin gettext("cannot get in-kernel socket table: %s\n"), 607*19581f84SAlexander Eremin strerror(errno)); 608*19581f84SAlexander Eremin return (-1); 609*19581f84SAlexander Eremin } 610*19581f84SAlexander Eremin if (sc_table.num_of_entries == 0) 611*19581f84SAlexander Eremin return (0); 612*19581f84SAlexander Eremin 613*19581f84SAlexander Eremin sc_table.st_entries = calloc(sc_table.num_of_entries, 614*19581f84SAlexander Eremin sizeof (sockconfig_socktable_entry_t)); 615*19581f84SAlexander Eremin if (sc_table.st_entries == NULL) { 616*19581f84SAlexander Eremin fprintf(stderr, gettext("out of memory\n")); 617*19581f84SAlexander Eremin return (-1); 618*19581f84SAlexander Eremin } 619*19581f84SAlexander Eremin 620*19581f84SAlexander Eremin /* get socket table entries */ 621*19581f84SAlexander Eremin if (_sockconfig(SOCKCONFIG_GET_SOCKTABLE, &sc_table) == -1) { 622*19581f84SAlexander Eremin fprintf(stderr, 623*19581f84SAlexander Eremin gettext("cannot get in-kernel socket table: %s\n"), 624*19581f84SAlexander Eremin strerror(errno)); 625*19581f84SAlexander Eremin return (-1); 626*19581f84SAlexander Eremin } 627*19581f84SAlexander Eremin 628*19581f84SAlexander Eremin printf("%6s %4s %5s %15s %15s %6s %6s\n", 629*19581f84SAlexander Eremin "FAMILY", "TYPE", "PROTO", "STRDEV", "SOCKMOD", 630*19581f84SAlexander Eremin "REFS", "FLAGS"); 631*19581f84SAlexander Eremin for (i = 0; i < sc_table.num_of_entries; i++) { 632*19581f84SAlexander Eremin printf("%6u %4u %5u %15s %15s %6u %#6x\n", 633*19581f84SAlexander Eremin sc_table.st_entries[i].se_family, 634*19581f84SAlexander Eremin sc_table.st_entries[i].se_type, 635*19581f84SAlexander Eremin sc_table.st_entries[i].se_protocol, 636*19581f84SAlexander Eremin (strcmp(sc_table.st_entries[i].se_modname, 637*19581f84SAlexander Eremin "socktpi") == 0) ? 638*19581f84SAlexander Eremin sc_table.st_entries[i].se_strdev : "-", 639*19581f84SAlexander Eremin sc_table.st_entries[i].se_modname, 640*19581f84SAlexander Eremin sc_table.st_entries[i].se_refcnt, 641*19581f84SAlexander Eremin sc_table.st_entries[i].se_flags); 642*19581f84SAlexander Eremin } 643*19581f84SAlexander Eremin free(sc_table.st_entries); 644*19581f84SAlexander Eremin return (0); 645*19581f84SAlexander Eremin } 646