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. 237c478bd9Sstevel@tonic-gate */ 247c478bd9Sstevel@tonic-gate 257c478bd9Sstevel@tonic-gate #include <ctype.h> 26*d2b5b2d3SAnders Persson #include <dirent.h> 27*d2b5b2d3SAnders Persson #include <errno.h> 287c478bd9Sstevel@tonic-gate #include <locale.h> 29*d2b5b2d3SAnders Persson #include <stdio.h> 30*d2b5b2d3SAnders Persson #include <stdlib.h> 31*d2b5b2d3SAnders Persson #include <string.h> 323e95bd4aSAnders Persson #include <sys/socket.h> 333e95bd4aSAnders Persson #include <sys/socketvar.h> 34*d2b5b2d3SAnders Persson #include <sys/stat.h> 35*d2b5b2d3SAnders Persson #include <unistd.h> 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate #define MAXLINELEN 4096 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate /* 407c478bd9Sstevel@tonic-gate * Usage: 41*d2b5b2d3SAnders Persson * soconfig -d <dir> 42*d2b5b2d3SAnders Persson * Reads input from files in dir. 43*d2b5b2d3SAnders Persson * 44*d2b5b2d3SAnders Persson * soconfig -f <file> 457c478bd9Sstevel@tonic-gate * Reads input from file. The file is structured as 460f1702c5SYu Xiangning * <fam> <type> <protocol> <path|module> 477c478bd9Sstevel@tonic-gate * <fam> <type> <protocol> 487c478bd9Sstevel@tonic-gate * with the first line registering and the second line 497c478bd9Sstevel@tonic-gate * deregistering. 507c478bd9Sstevel@tonic-gate * 510f1702c5SYu Xiangning * soconfig <fam> <type> <protocol> <path|module> 527c478bd9Sstevel@tonic-gate * registers 537c478bd9Sstevel@tonic-gate * 547c478bd9Sstevel@tonic-gate * soconfig <fam> <type> <protocol> 557c478bd9Sstevel@tonic-gate * deregisters 563e95bd4aSAnders Persson * 573e95bd4aSAnders Persson * Filter Operations (Consolidation Private): 583e95bd4aSAnders Persson * 593e95bd4aSAnders Persson * soconfig -F <name> <modname> {auto [top | bottom | before:filter | 603e95bd4aSAnders Persson * after:filter] | prog} <fam>:<type>:<proto>,... 613e95bd4aSAnders Persson * configure filter 623e95bd4aSAnders Persson * 633e95bd4aSAnders Persson * soconfig -F <name> 643e95bd4aSAnders Persson * unconfigures filter 657c478bd9Sstevel@tonic-gate */ 667c478bd9Sstevel@tonic-gate 67*d2b5b2d3SAnders Persson static int parse_files_in_dir(const char *dir); 68*d2b5b2d3SAnders Persson 697c478bd9Sstevel@tonic-gate static int parse_file(char *filename); 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate static int split_line(char *line, char *argvec[], int maxargvec); 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate static int parse_params(char *famstr, char *typestr, char *protostr, 74*d2b5b2d3SAnders Persson char *path, const char *file, int line); 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate static int parse_int(char *str); 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate static void usage(void); 797c478bd9Sstevel@tonic-gate 803e95bd4aSAnders Persson static int parse_filter_params(int argc, char **argv); 813e95bd4aSAnders Persson 827c478bd9Sstevel@tonic-gate int 837c478bd9Sstevel@tonic-gate main(argc, argv) 847c478bd9Sstevel@tonic-gate int argc; 857c478bd9Sstevel@tonic-gate char *argv[]; 867c478bd9Sstevel@tonic-gate { 877c478bd9Sstevel@tonic-gate int ret; 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate argc--; argv++; 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 927c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 937c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 947c478bd9Sstevel@tonic-gate #endif 957c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 967c478bd9Sstevel@tonic-gate 973e95bd4aSAnders Persson if (argc >= 2 && strcmp(argv[0], "-F") == 0) { 983e95bd4aSAnders Persson argc--; argv++; 993e95bd4aSAnders Persson ret = parse_filter_params(argc, argv); 1003e95bd4aSAnders Persson exit(ret); 1013e95bd4aSAnders Persson } 102*d2b5b2d3SAnders Persson if (argc == 2 && strcmp(argv[0], "-d") == 0) { 103*d2b5b2d3SAnders Persson ret = parse_files_in_dir(argv[1]); 104*d2b5b2d3SAnders Persson exit(ret); 105*d2b5b2d3SAnders Persson } 1067c478bd9Sstevel@tonic-gate if (argc == 2 && strcmp(argv[0], "-f") == 0) { 1077c478bd9Sstevel@tonic-gate ret = parse_file(argv[1]); 1087c478bd9Sstevel@tonic-gate exit(ret); 1097c478bd9Sstevel@tonic-gate } 1107c478bd9Sstevel@tonic-gate if (argc == 3) { 111*d2b5b2d3SAnders Persson ret = parse_params(argv[0], argv[1], argv[2], NULL, NULL, -1); 1127c478bd9Sstevel@tonic-gate exit(ret); 1137c478bd9Sstevel@tonic-gate } 1147c478bd9Sstevel@tonic-gate if (argc == 4) { 115*d2b5b2d3SAnders Persson ret = parse_params(argv[0], argv[1], argv[2], argv[3], 116*d2b5b2d3SAnders Persson NULL, -1); 1177c478bd9Sstevel@tonic-gate exit(ret); 1187c478bd9Sstevel@tonic-gate } 1197c478bd9Sstevel@tonic-gate usage(); 1207c478bd9Sstevel@tonic-gate exit(1); 1217c478bd9Sstevel@tonic-gate /* NOTREACHED */ 1227c478bd9Sstevel@tonic-gate } 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate static void 1257c478bd9Sstevel@tonic-gate usage(void) 1267c478bd9Sstevel@tonic-gate { 1277c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 128*d2b5b2d3SAnders Persson "Usage: soconfig -d <dir>\n" 129*d2b5b2d3SAnders Persson "\tsoconfig -f <file>\n" 1300f1702c5SYu Xiangning "\tsoconfig <fam> <type> <protocol> <path|module>\n" 1317c478bd9Sstevel@tonic-gate "\tsoconfig <fam> <type> <protocol>\n")); 1327c478bd9Sstevel@tonic-gate } 1337c478bd9Sstevel@tonic-gate 1347c478bd9Sstevel@tonic-gate /* 135*d2b5b2d3SAnders Persson * Parse all files in the given directory. 136*d2b5b2d3SAnders Persson */ 137*d2b5b2d3SAnders Persson static int 138*d2b5b2d3SAnders Persson parse_files_in_dir(const char *dirname) 139*d2b5b2d3SAnders Persson { 140*d2b5b2d3SAnders Persson DIR *dp; 141*d2b5b2d3SAnders Persson struct dirent *dirp; 142*d2b5b2d3SAnders Persson struct stat stats; 143*d2b5b2d3SAnders Persson char buf[MAXPATHLEN]; 144*d2b5b2d3SAnders Persson 145*d2b5b2d3SAnders Persson if ((dp = opendir(dirname)) == NULL) { 146*d2b5b2d3SAnders Persson fprintf(stderr, gettext("failed to open directory '%s': %s\n"), 147*d2b5b2d3SAnders Persson dirname, strerror(errno)); 148*d2b5b2d3SAnders Persson return (1); 149*d2b5b2d3SAnders Persson } 150*d2b5b2d3SAnders Persson 151*d2b5b2d3SAnders Persson while ((dirp = readdir(dp)) != NULL) { 152*d2b5b2d3SAnders Persson if (dirp->d_name[0] == '.') 153*d2b5b2d3SAnders Persson continue; 154*d2b5b2d3SAnders Persson 155*d2b5b2d3SAnders Persson if (snprintf(buf, sizeof (buf), "%s/%s", dirname, 156*d2b5b2d3SAnders Persson dirp->d_name) >= sizeof (buf)) { 157*d2b5b2d3SAnders Persson fprintf(stderr, 158*d2b5b2d3SAnders Persson gettext("path name is too long: %s/%s\n"), 159*d2b5b2d3SAnders Persson dirname, dirp->d_name); 160*d2b5b2d3SAnders Persson continue; 161*d2b5b2d3SAnders Persson } 162*d2b5b2d3SAnders Persson if (stat(buf, &stats) == -1) { 163*d2b5b2d3SAnders Persson fprintf(stderr, 164*d2b5b2d3SAnders Persson gettext("failed to stat '%s': %s\n"), buf, 165*d2b5b2d3SAnders Persson strerror(errno)); 166*d2b5b2d3SAnders Persson continue; 167*d2b5b2d3SAnders Persson } 168*d2b5b2d3SAnders Persson if (!S_ISREG(stats.st_mode)) 169*d2b5b2d3SAnders Persson continue; 170*d2b5b2d3SAnders Persson 171*d2b5b2d3SAnders Persson (void) parse_file(buf); 172*d2b5b2d3SAnders Persson } 173*d2b5b2d3SAnders Persson 174*d2b5b2d3SAnders Persson closedir(dp); 175*d2b5b2d3SAnders Persson 176*d2b5b2d3SAnders Persson return (0); 177*d2b5b2d3SAnders Persson } 178*d2b5b2d3SAnders Persson 179*d2b5b2d3SAnders Persson /* 1807c478bd9Sstevel@tonic-gate * Open the specified file and parse each line. Skip comments (everything 1817c478bd9Sstevel@tonic-gate * after a '#'). Return 1 if at least one error was encountered; otherwise 0. 1827c478bd9Sstevel@tonic-gate */ 1837c478bd9Sstevel@tonic-gate static int 1847c478bd9Sstevel@tonic-gate parse_file(char *filename) 1857c478bd9Sstevel@tonic-gate { 1867c478bd9Sstevel@tonic-gate char line[MAXLINELEN]; 1877c478bd9Sstevel@tonic-gate char pline[MAXLINELEN]; 1887c478bd9Sstevel@tonic-gate int argcount; 1897c478bd9Sstevel@tonic-gate char *argvec[20]; 1907c478bd9Sstevel@tonic-gate FILE *fp; 1917c478bd9Sstevel@tonic-gate int linecount = 0; 1927c478bd9Sstevel@tonic-gate int numerror = 0; 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate fp = fopen(filename, "r"); 1957c478bd9Sstevel@tonic-gate if (fp == NULL) { 1967c478bd9Sstevel@tonic-gate perror("soconfig: open"); 1977c478bd9Sstevel@tonic-gate fprintf(stderr, "\n"); 1987c478bd9Sstevel@tonic-gate usage(); 1997c478bd9Sstevel@tonic-gate return (1); 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate while (fgets(line, sizeof (line) - 1, fp) != NULL) { 2037c478bd9Sstevel@tonic-gate linecount++; 2047c478bd9Sstevel@tonic-gate strcpy(pline, line); 2057c478bd9Sstevel@tonic-gate argcount = split_line(pline, argvec, 2067c478bd9Sstevel@tonic-gate sizeof (argvec) / sizeof (argvec[0])); 2077c478bd9Sstevel@tonic-gate #ifdef DEBUG 2087c478bd9Sstevel@tonic-gate { 2097c478bd9Sstevel@tonic-gate int i; 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate printf("scanned %d args\n", argcount); 2127c478bd9Sstevel@tonic-gate for (i = 0; i < argcount; i++) 2137c478bd9Sstevel@tonic-gate printf("arg[%d]: %s\n", i, argvec[i]); 2147c478bd9Sstevel@tonic-gate } 2157c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 2167c478bd9Sstevel@tonic-gate switch (argcount) { 2177c478bd9Sstevel@tonic-gate case 0: 2187c478bd9Sstevel@tonic-gate /* Empty line - or comment only line */ 2197c478bd9Sstevel@tonic-gate break; 2207c478bd9Sstevel@tonic-gate case 3: 2217c478bd9Sstevel@tonic-gate numerror += parse_params(argvec[0], argvec[1], 222*d2b5b2d3SAnders Persson argvec[2], NULL, filename, linecount); 2237c478bd9Sstevel@tonic-gate break; 2247c478bd9Sstevel@tonic-gate case 4: 2257c478bd9Sstevel@tonic-gate numerror += parse_params(argvec[0], argvec[1], 226*d2b5b2d3SAnders Persson argvec[2], argvec[3], filename, linecount); 2277c478bd9Sstevel@tonic-gate break; 2287c478bd9Sstevel@tonic-gate default: 2297c478bd9Sstevel@tonic-gate numerror++; 2307c478bd9Sstevel@tonic-gate fprintf(stderr, 2317c478bd9Sstevel@tonic-gate gettext("Malformed line: <%s>\n"), line); 2327c478bd9Sstevel@tonic-gate fprintf(stderr, 233*d2b5b2d3SAnders Persson gettext("\ton line %d in %s\n"), linecount, 234*d2b5b2d3SAnders Persson filename); 2357c478bd9Sstevel@tonic-gate break; 2367c478bd9Sstevel@tonic-gate } 2377c478bd9Sstevel@tonic-gate } 2387c478bd9Sstevel@tonic-gate (void) fclose(fp); 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate if (numerror > 0) 2417c478bd9Sstevel@tonic-gate return (1); 2427c478bd9Sstevel@tonic-gate else 2437c478bd9Sstevel@tonic-gate return (0); 2447c478bd9Sstevel@tonic-gate } 2457c478bd9Sstevel@tonic-gate 2467c478bd9Sstevel@tonic-gate /* 2477c478bd9Sstevel@tonic-gate * Parse a line splitting it off at whitspace characters. 2487c478bd9Sstevel@tonic-gate * Modifies the content of the string by inserting NULLs. 2497c478bd9Sstevel@tonic-gate */ 2507c478bd9Sstevel@tonic-gate static int 2517c478bd9Sstevel@tonic-gate split_line(char *line, char *argvec[], int maxargvec) 2527c478bd9Sstevel@tonic-gate { 2537c478bd9Sstevel@tonic-gate int i = 0; 2547c478bd9Sstevel@tonic-gate char *cp; 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate /* Truncate at the beginning of a comment */ 2577c478bd9Sstevel@tonic-gate cp = strchr(line, '#'); 2587c478bd9Sstevel@tonic-gate if (cp != NULL) 2597c478bd9Sstevel@tonic-gate *cp = NULL; 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate /* CONSTCOND */ 2627c478bd9Sstevel@tonic-gate while (1) { 2637c478bd9Sstevel@tonic-gate /* Skip any whitespace */ 2647c478bd9Sstevel@tonic-gate while (isspace(*line) && *line != NULL) 2657c478bd9Sstevel@tonic-gate line++; 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate if (i >= maxargvec) 2687c478bd9Sstevel@tonic-gate return (i); 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate argvec[i] = line; 2717c478bd9Sstevel@tonic-gate if (*line == NULL) 2727c478bd9Sstevel@tonic-gate return (i); 2737c478bd9Sstevel@tonic-gate i++; 2747c478bd9Sstevel@tonic-gate /* Skip until next whitespace */ 2757c478bd9Sstevel@tonic-gate while (!isspace(*line) && *line != NULL) 2767c478bd9Sstevel@tonic-gate line++; 2777c478bd9Sstevel@tonic-gate if (*line != NULL) { 2787c478bd9Sstevel@tonic-gate /* Break off argument */ 2797c478bd9Sstevel@tonic-gate *line++ = NULL; 2807c478bd9Sstevel@tonic-gate } 2817c478bd9Sstevel@tonic-gate } 2827c478bd9Sstevel@tonic-gate /* NOTREACHED */ 2837c478bd9Sstevel@tonic-gate } 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate /* 2867c478bd9Sstevel@tonic-gate * Parse the set of parameters and issues the sockconfig syscall. 2877c478bd9Sstevel@tonic-gate * If line is not -1 it is assumed to be the line number in the file. 2887c478bd9Sstevel@tonic-gate */ 2897c478bd9Sstevel@tonic-gate static int 290*d2b5b2d3SAnders Persson parse_params(char *famstr, char *typestr, char *protostr, char *path, 291*d2b5b2d3SAnders Persson const char *file, int line) 2927c478bd9Sstevel@tonic-gate { 2933e95bd4aSAnders Persson int cmd, fam, type, protocol; 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate fam = parse_int(famstr); 2967c478bd9Sstevel@tonic-gate if (fam == -1) { 2977c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Bad family number: %s\n"), famstr); 2987c478bd9Sstevel@tonic-gate if (line != -1) 2997c478bd9Sstevel@tonic-gate fprintf(stderr, 300*d2b5b2d3SAnders Persson gettext("\ton line %d in %s\n"), line, file); 3017c478bd9Sstevel@tonic-gate else { 3027c478bd9Sstevel@tonic-gate fprintf(stderr, "\n"); 3037c478bd9Sstevel@tonic-gate usage(); 3047c478bd9Sstevel@tonic-gate } 3057c478bd9Sstevel@tonic-gate return (1); 3067c478bd9Sstevel@tonic-gate } 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate type = parse_int(typestr); 3097c478bd9Sstevel@tonic-gate if (type == -1) { 3107c478bd9Sstevel@tonic-gate fprintf(stderr, 3117c478bd9Sstevel@tonic-gate gettext("Bad socket type number: %s\n"), typestr); 3127c478bd9Sstevel@tonic-gate if (line != -1) 3137c478bd9Sstevel@tonic-gate fprintf(stderr, 314*d2b5b2d3SAnders Persson gettext("\ton line %d in %s\n"), line, file); 3157c478bd9Sstevel@tonic-gate else { 3167c478bd9Sstevel@tonic-gate fprintf(stderr, "\n"); 3177c478bd9Sstevel@tonic-gate usage(); 3187c478bd9Sstevel@tonic-gate } 3197c478bd9Sstevel@tonic-gate return (1); 3207c478bd9Sstevel@tonic-gate } 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate protocol = parse_int(protostr); 3237c478bd9Sstevel@tonic-gate if (protocol == -1) { 3247c478bd9Sstevel@tonic-gate fprintf(stderr, 3257c478bd9Sstevel@tonic-gate gettext("Bad protocol number: %s\n"), protostr); 3267c478bd9Sstevel@tonic-gate if (line != -1) 3277c478bd9Sstevel@tonic-gate fprintf(stderr, 328*d2b5b2d3SAnders Persson gettext("\ton line %d in %s\n"), line, file); 3297c478bd9Sstevel@tonic-gate else { 3307c478bd9Sstevel@tonic-gate fprintf(stderr, "\n"); 3317c478bd9Sstevel@tonic-gate usage(); 3327c478bd9Sstevel@tonic-gate } 3337c478bd9Sstevel@tonic-gate return (1); 3347c478bd9Sstevel@tonic-gate } 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate 3377c478bd9Sstevel@tonic-gate if (path != NULL) { 3387c478bd9Sstevel@tonic-gate struct stat stats; 3397c478bd9Sstevel@tonic-gate 3400f1702c5SYu Xiangning if (strncmp(path, "/dev", strlen("/dev")) == 0 && 3410f1702c5SYu Xiangning stat(path, &stats) == -1) { 3427c478bd9Sstevel@tonic-gate perror(path); 3437c478bd9Sstevel@tonic-gate if (line != -1) 3447c478bd9Sstevel@tonic-gate fprintf(stderr, 345*d2b5b2d3SAnders Persson gettext("\ton line %d in %s\n"), line, 346*d2b5b2d3SAnders Persson file); 3477c478bd9Sstevel@tonic-gate else { 3487c478bd9Sstevel@tonic-gate fprintf(stderr, "\n"); 3497c478bd9Sstevel@tonic-gate usage(); 3507c478bd9Sstevel@tonic-gate } 3517c478bd9Sstevel@tonic-gate return (1); 3527c478bd9Sstevel@tonic-gate } 3533e95bd4aSAnders Persson 3543e95bd4aSAnders Persson cmd = SOCKCONFIG_ADD_SOCK; 3553e95bd4aSAnders Persson } else { 3563e95bd4aSAnders Persson cmd = SOCKCONFIG_REMOVE_SOCK; 3577c478bd9Sstevel@tonic-gate } 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate #ifdef DEBUG 3603e95bd4aSAnders Persson printf("not calling sockconfig(%d, %d, %d, %d, %s)\n", 3613e95bd4aSAnders Persson cmd, fam, type, protocol, path == NULL ? "(null)" : path); 3627c478bd9Sstevel@tonic-gate #else 3633e95bd4aSAnders Persson if (_sockconfig(cmd, fam, type, protocol, path) == -1) { 364*d2b5b2d3SAnders Persson char *s; 365*d2b5b2d3SAnders Persson 366*d2b5b2d3SAnders Persson switch (errno) { 367*d2b5b2d3SAnders Persson case EEXIST: 368*d2b5b2d3SAnders Persson s = gettext("Mapping exists"); 369*d2b5b2d3SAnders Persson break; 370*d2b5b2d3SAnders Persson default: 371*d2b5b2d3SAnders Persson s = strerror(errno); 372*d2b5b2d3SAnders Persson break; 373*d2b5b2d3SAnders Persson } 374*d2b5b2d3SAnders Persson 375*d2b5b2d3SAnders Persson fprintf(stderr, 376*d2b5b2d3SAnders Persson gettext("warning: socket configuration failed " 377*d2b5b2d3SAnders Persson "for family %d type %d protocol %d: %s\n"), 378*d2b5b2d3SAnders Persson fam, type, protocol, s); 379*d2b5b2d3SAnders Persson if (line != -1) { 380*d2b5b2d3SAnders Persson fprintf(stderr, 381*d2b5b2d3SAnders Persson gettext("\ton line %d in %s\n"), line, file); 382*d2b5b2d3SAnders Persson } 3837c478bd9Sstevel@tonic-gate return (1); 3847c478bd9Sstevel@tonic-gate } 3857c478bd9Sstevel@tonic-gate #endif 3867c478bd9Sstevel@tonic-gate return (0); 3877c478bd9Sstevel@tonic-gate } 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate static int 3907c478bd9Sstevel@tonic-gate parse_int(char *str) 3917c478bd9Sstevel@tonic-gate { 3927c478bd9Sstevel@tonic-gate char *end; 3937c478bd9Sstevel@tonic-gate int res; 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate res = strtol(str, &end, 0); 3967c478bd9Sstevel@tonic-gate if (end == str) 3977c478bd9Sstevel@tonic-gate return (-1); 3987c478bd9Sstevel@tonic-gate return (res); 3997c478bd9Sstevel@tonic-gate } 4003e95bd4aSAnders Persson 4013e95bd4aSAnders Persson /* 4023e95bd4aSAnders Persson * Add and remove socket filters. 4033e95bd4aSAnders Persson */ 4043e95bd4aSAnders Persson static int 4053e95bd4aSAnders Persson parse_filter_params(int argc, char **argv) 4063e95bd4aSAnders Persson { 4073e95bd4aSAnders Persson struct sockconfig_filter_props filprop; 4083e95bd4aSAnders Persson sof_socktuple_t *socktuples; 4093e95bd4aSAnders Persson size_t tupcnt, nalloc; 4103e95bd4aSAnders Persson char *hintarg, *socktup, *tupstr; 4113e95bd4aSAnders Persson int i; 4123e95bd4aSAnders Persson 4133e95bd4aSAnders Persson if (argc == 1) { 4143e95bd4aSAnders Persson if (_sockconfig(SOCKCONFIG_REMOVE_FILTER, argv[0], 0, 4153e95bd4aSAnders Persson 0, 0) < 0) { 4163e95bd4aSAnders Persson switch (errno) { 4173e95bd4aSAnders Persson case ENXIO: 4183e95bd4aSAnders Persson fprintf(stderr, 4193e95bd4aSAnders Persson gettext("socket filter is not configured " 4203e95bd4aSAnders Persson "'%s'\n"), argv[0]); 4213e95bd4aSAnders Persson break; 4223e95bd4aSAnders Persson default: 4233e95bd4aSAnders Persson perror("sockconfig"); 4243e95bd4aSAnders Persson break; 4253e95bd4aSAnders Persson } 4263e95bd4aSAnders Persson return (1); 4273e95bd4aSAnders Persson } 4283e95bd4aSAnders Persson return (0); 4293e95bd4aSAnders Persson } 4303e95bd4aSAnders Persson 4313e95bd4aSAnders Persson if (argc < 4 || argc > 5) 4323e95bd4aSAnders Persson return (1); 4333e95bd4aSAnders Persson 4343e95bd4aSAnders Persson 4353e95bd4aSAnders Persson if (strlen(argv[1]) >= MODMAXNAMELEN) { 4363e95bd4aSAnders Persson fprintf(stderr, 4373e95bd4aSAnders Persson gettext("invalid module name '%s': name too long\n"), 4383e95bd4aSAnders Persson argv[1]); 4393e95bd4aSAnders Persson return (1); 4403e95bd4aSAnders Persson } 4413e95bd4aSAnders Persson filprop.sfp_modname = argv[1]; 4423e95bd4aSAnders Persson 4433e95bd4aSAnders Persson /* Check the attach semantics */ 4443e95bd4aSAnders Persson if (strcmp(argv[2], "auto") == 0) { 4453e95bd4aSAnders Persson filprop.sfp_autoattach = B_TRUE; 4463e95bd4aSAnders Persson if (argc == 5) { 4473e95bd4aSAnders Persson /* placement hint */ 4483e95bd4aSAnders Persson if (strcmp(argv[3], "top") == 0) { 4493e95bd4aSAnders Persson filprop.sfp_hint = SOF_HINT_TOP; 4503e95bd4aSAnders Persson } else if (strcmp(argv[3], "bottom") == 0) { 4513e95bd4aSAnders Persson filprop.sfp_hint = SOF_HINT_BOTTOM; 4523e95bd4aSAnders Persson } else { 4533e95bd4aSAnders Persson if (strncmp(argv[3], "before", 6) == 0) { 4543e95bd4aSAnders Persson filprop.sfp_hint = SOF_HINT_BEFORE; 4553e95bd4aSAnders Persson } else if (strncmp(argv[3], "after", 5) == 0) { 4563e95bd4aSAnders Persson filprop.sfp_hint = SOF_HINT_AFTER; 4573e95bd4aSAnders Persson } else { 4583e95bd4aSAnders Persson fprintf(stderr, 4593e95bd4aSAnders Persson gettext("invalid placement hint " 4603e95bd4aSAnders Persson "'%s'\n"), argv[3]); 4613e95bd4aSAnders Persson return (1); 4623e95bd4aSAnders Persson } 4633e95bd4aSAnders Persson 4643e95bd4aSAnders Persson hintarg = strchr(argv[3], ':'); 4653e95bd4aSAnders Persson if (hintarg == NULL || 4663e95bd4aSAnders Persson (strlen(++hintarg) == 0) || 4673e95bd4aSAnders Persson (strlen(hintarg) >= FILNAME_MAX)) { 4683e95bd4aSAnders Persson fprintf(stderr, 4693e95bd4aSAnders Persson gettext("invalid placement hint " 4703e95bd4aSAnders Persson "argument '%s': name too long\n"), 4713e95bd4aSAnders Persson argv[3]); 4723e95bd4aSAnders Persson return (1); 4733e95bd4aSAnders Persson } 4743e95bd4aSAnders Persson 4753e95bd4aSAnders Persson filprop.sfp_hintarg = hintarg; 4763e95bd4aSAnders Persson } 4773e95bd4aSAnders Persson } else { 4783e95bd4aSAnders Persson filprop.sfp_hint = SOF_HINT_NONE; 4793e95bd4aSAnders Persson } 4803e95bd4aSAnders Persson } else if (strcmp(argv[2], "prog") == 0) { 4813e95bd4aSAnders Persson filprop.sfp_autoattach = B_FALSE; 4823e95bd4aSAnders Persson filprop.sfp_hint = SOF_HINT_NONE; 4833e95bd4aSAnders Persson /* cannot specify placement hint for programmatic filter */ 4843e95bd4aSAnders Persson if (argc == 5) { 4853e95bd4aSAnders Persson fprintf(stderr, 4863e95bd4aSAnders Persson gettext("placement hint specified for programmatic " 4873e95bd4aSAnders Persson "filter\n")); 4883e95bd4aSAnders Persson return (1); 4893e95bd4aSAnders Persson } 4903e95bd4aSAnders Persson } else { 4913e95bd4aSAnders Persson fprintf(stderr, gettext("invalid attach semantic '%s'\n"), 4923e95bd4aSAnders Persson argv[2]); 4933e95bd4aSAnders Persson return (1); 4943e95bd4aSAnders Persson } 4953e95bd4aSAnders Persson 4963e95bd4aSAnders Persson /* parse the socket tuples */ 4973e95bd4aSAnders Persson nalloc = 4; 4983e95bd4aSAnders Persson socktuples = calloc(nalloc, sizeof (sof_socktuple_t)); 4993e95bd4aSAnders Persson if (socktuples == NULL) { 5003e95bd4aSAnders Persson perror("calloc"); 5013e95bd4aSAnders Persson return (1); 5023e95bd4aSAnders Persson } 5033e95bd4aSAnders Persson 5043e95bd4aSAnders Persson tupcnt = 0; 5053e95bd4aSAnders Persson tupstr = argv[(argc == 4) ? 3 : 4]; 5063e95bd4aSAnders Persson while ((socktup = strsep(&tupstr, ",")) != NULL) { 5073e95bd4aSAnders Persson int val; 5083e95bd4aSAnders Persson char *valstr; 5093e95bd4aSAnders Persson 5103e95bd4aSAnders Persson if (tupcnt == nalloc) { 5113e95bd4aSAnders Persson sof_socktuple_t *new; 5123e95bd4aSAnders Persson 5133e95bd4aSAnders Persson nalloc *= 2; 5143e95bd4aSAnders Persson new = realloc(socktuples, 5153e95bd4aSAnders Persson nalloc * sizeof (sof_socktuple_t)); 5163e95bd4aSAnders Persson if (new == NULL) { 5173e95bd4aSAnders Persson perror("realloc"); 5183e95bd4aSAnders Persson free(socktuples); 5193e95bd4aSAnders Persson return (1); 5203e95bd4aSAnders Persson } 5213e95bd4aSAnders Persson socktuples = new; 5223e95bd4aSAnders Persson } 5233e95bd4aSAnders Persson i = 0; 5243e95bd4aSAnders Persson while ((valstr = strsep(&socktup, ":")) != NULL && i < 3) { 5253e95bd4aSAnders Persson val = parse_int(valstr); 5263e95bd4aSAnders Persson if (val == -1) { 5273e95bd4aSAnders Persson fprintf(stderr, gettext("bad socket tuple\n")); 5283e95bd4aSAnders Persson free(socktuples); 5293e95bd4aSAnders Persson return (1); 5303e95bd4aSAnders Persson } 5313e95bd4aSAnders Persson switch (i) { 5323e95bd4aSAnders Persson case 0: socktuples[tupcnt].sofst_family = val; break; 5333e95bd4aSAnders Persson case 1: socktuples[tupcnt].sofst_type = val; break; 5343e95bd4aSAnders Persson case 2: socktuples[tupcnt].sofst_protocol = val; break; 5353e95bd4aSAnders Persson } 5363e95bd4aSAnders Persson i++; 5373e95bd4aSAnders Persson } 5383e95bd4aSAnders Persson if (i != 3) { 5393e95bd4aSAnders Persson fprintf(stderr, gettext("bad socket tuple\n")); 5403e95bd4aSAnders Persson free(socktuples); 5413e95bd4aSAnders Persson return (1); 5423e95bd4aSAnders Persson } 5433e95bd4aSAnders Persson tupcnt++; 5443e95bd4aSAnders Persson } 5453e95bd4aSAnders Persson if (tupcnt == 0) { 5463e95bd4aSAnders Persson fprintf(stderr, gettext("no socket tuples specified\n")); 5473e95bd4aSAnders Persson free(socktuples); 5483e95bd4aSAnders Persson return (1); 5493e95bd4aSAnders Persson } 5503e95bd4aSAnders Persson filprop.sfp_socktuple_cnt = tupcnt; 5513e95bd4aSAnders Persson filprop.sfp_socktuple = socktuples; 5523e95bd4aSAnders Persson 5533e95bd4aSAnders Persson if (_sockconfig(SOCKCONFIG_ADD_FILTER, argv[0], &filprop, 0, 0) < 0) { 5543e95bd4aSAnders Persson switch (errno) { 5553e95bd4aSAnders Persson case EINVAL: 5563e95bd4aSAnders Persson fprintf(stderr, 5573e95bd4aSAnders Persson gettext("invalid socket filter configuration\n")); 5583e95bd4aSAnders Persson break; 5593e95bd4aSAnders Persson case EEXIST: 5603e95bd4aSAnders Persson fprintf(stderr, 5613e95bd4aSAnders Persson gettext("socket filter is already configured " 5623e95bd4aSAnders Persson "'%s'\n"), argv[0]); 5633e95bd4aSAnders Persson break; 5643e95bd4aSAnders Persson case ENOSPC: 5653e95bd4aSAnders Persson fprintf(stderr, gettext("unable to satisfy placement " 5663e95bd4aSAnders Persson "constraint\n")); 5673e95bd4aSAnders Persson break; 5683e95bd4aSAnders Persson default: 5693e95bd4aSAnders Persson perror("sockconfig"); 5703e95bd4aSAnders Persson break; 5713e95bd4aSAnders Persson } 5723e95bd4aSAnders Persson free(socktuples); 5733e95bd4aSAnders Persson return (1); 5743e95bd4aSAnders Persson } 5753e95bd4aSAnders Persson free(socktuples); 5763e95bd4aSAnders Persson return (0); 5773e95bd4aSAnders Persson } 578