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 /* 22*3e95bd4aSAnders Persson * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. 237c478bd9Sstevel@tonic-gate */ 247c478bd9Sstevel@tonic-gate 257c478bd9Sstevel@tonic-gate #include <stdio.h> 267c478bd9Sstevel@tonic-gate #include <sys/stat.h> 277c478bd9Sstevel@tonic-gate #include <stdlib.h> 287c478bd9Sstevel@tonic-gate #include <unistd.h> 297c478bd9Sstevel@tonic-gate #include <string.h> 307c478bd9Sstevel@tonic-gate #include <ctype.h> 317c478bd9Sstevel@tonic-gate #include <locale.h> 32*3e95bd4aSAnders Persson #include <sys/socket.h> 33*3e95bd4aSAnders Persson #include <sys/socketvar.h> 34*3e95bd4aSAnders Persson #include <errno.h> 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate #define MAXLINELEN 4096 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate /* 397c478bd9Sstevel@tonic-gate * Usage: 407c478bd9Sstevel@tonic-gate * sonconfig -f <file> 417c478bd9Sstevel@tonic-gate * Reads input from file. The file is structured as 420f1702c5SYu Xiangning * <fam> <type> <protocol> <path|module> 437c478bd9Sstevel@tonic-gate * <fam> <type> <protocol> 447c478bd9Sstevel@tonic-gate * with the first line registering and the second line 457c478bd9Sstevel@tonic-gate * deregistering. 467c478bd9Sstevel@tonic-gate * 470f1702c5SYu Xiangning * soconfig <fam> <type> <protocol> <path|module> 487c478bd9Sstevel@tonic-gate * registers 497c478bd9Sstevel@tonic-gate * 507c478bd9Sstevel@tonic-gate * soconfig <fam> <type> <protocol> 517c478bd9Sstevel@tonic-gate * deregisters 52*3e95bd4aSAnders Persson * 53*3e95bd4aSAnders Persson * Filter Operations (Consolidation Private): 54*3e95bd4aSAnders Persson * 55*3e95bd4aSAnders Persson * soconfig -F <name> <modname> {auto [top | bottom | before:filter | 56*3e95bd4aSAnders Persson * after:filter] | prog} <fam>:<type>:<proto>,... 57*3e95bd4aSAnders Persson * configure filter 58*3e95bd4aSAnders Persson * 59*3e95bd4aSAnders Persson * soconfig -F <name> 60*3e95bd4aSAnders Persson * unconfigures filter 617c478bd9Sstevel@tonic-gate */ 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate static int parse_file(char *filename); 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate static int split_line(char *line, char *argvec[], int maxargvec); 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate static int parse_params(char *famstr, char *typestr, char *protostr, 687c478bd9Sstevel@tonic-gate char *path, int line); 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate static int parse_int(char *str); 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate static void usage(void); 737c478bd9Sstevel@tonic-gate 74*3e95bd4aSAnders Persson static int parse_filter_params(int argc, char **argv); 75*3e95bd4aSAnders Persson 767c478bd9Sstevel@tonic-gate int 777c478bd9Sstevel@tonic-gate main(argc, argv) 787c478bd9Sstevel@tonic-gate int argc; 797c478bd9Sstevel@tonic-gate char *argv[]; 807c478bd9Sstevel@tonic-gate { 817c478bd9Sstevel@tonic-gate int ret; 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate argc--; argv++; 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 867c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 877c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 887c478bd9Sstevel@tonic-gate #endif 897c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 907c478bd9Sstevel@tonic-gate 91*3e95bd4aSAnders Persson if (argc >= 2 && strcmp(argv[0], "-F") == 0) { 92*3e95bd4aSAnders Persson argc--; argv++; 93*3e95bd4aSAnders Persson ret = parse_filter_params(argc, argv); 94*3e95bd4aSAnders Persson exit(ret); 95*3e95bd4aSAnders Persson } 967c478bd9Sstevel@tonic-gate if (argc == 2 && strcmp(argv[0], "-f") == 0) { 977c478bd9Sstevel@tonic-gate ret = parse_file(argv[1]); 987c478bd9Sstevel@tonic-gate exit(ret); 997c478bd9Sstevel@tonic-gate } 1007c478bd9Sstevel@tonic-gate if (argc == 3) { 1017c478bd9Sstevel@tonic-gate ret = parse_params(argv[0], argv[1], argv[2], NULL, -1); 1027c478bd9Sstevel@tonic-gate exit(ret); 1037c478bd9Sstevel@tonic-gate } 1047c478bd9Sstevel@tonic-gate if (argc == 4) { 1057c478bd9Sstevel@tonic-gate ret = parse_params(argv[0], argv[1], argv[2], argv[3], -1); 1067c478bd9Sstevel@tonic-gate exit(ret); 1077c478bd9Sstevel@tonic-gate } 1087c478bd9Sstevel@tonic-gate usage(); 1097c478bd9Sstevel@tonic-gate exit(1); 1107c478bd9Sstevel@tonic-gate /* NOTREACHED */ 1117c478bd9Sstevel@tonic-gate } 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate static void 1147c478bd9Sstevel@tonic-gate usage(void) 1157c478bd9Sstevel@tonic-gate { 1167c478bd9Sstevel@tonic-gate fprintf(stderr, gettext( 1177c478bd9Sstevel@tonic-gate "Usage: soconfig -f <file>\n" 1180f1702c5SYu Xiangning "\tsoconfig <fam> <type> <protocol> <path|module>\n" 1197c478bd9Sstevel@tonic-gate "\tsoconfig <fam> <type> <protocol>\n")); 1207c478bd9Sstevel@tonic-gate } 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gate /* 1237c478bd9Sstevel@tonic-gate * Open the specified file and parse each line. Skip comments (everything 1247c478bd9Sstevel@tonic-gate * after a '#'). Return 1 if at least one error was encountered; otherwise 0. 1257c478bd9Sstevel@tonic-gate */ 1267c478bd9Sstevel@tonic-gate static int 1277c478bd9Sstevel@tonic-gate parse_file(char *filename) 1287c478bd9Sstevel@tonic-gate { 1297c478bd9Sstevel@tonic-gate char line[MAXLINELEN]; 1307c478bd9Sstevel@tonic-gate char pline[MAXLINELEN]; 1317c478bd9Sstevel@tonic-gate int argcount; 1327c478bd9Sstevel@tonic-gate char *argvec[20]; 1337c478bd9Sstevel@tonic-gate FILE *fp; 1347c478bd9Sstevel@tonic-gate int linecount = 0; 1357c478bd9Sstevel@tonic-gate int numerror = 0; 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate fp = fopen(filename, "r"); 1387c478bd9Sstevel@tonic-gate if (fp == NULL) { 1397c478bd9Sstevel@tonic-gate perror("soconfig: open"); 1407c478bd9Sstevel@tonic-gate fprintf(stderr, "\n"); 1417c478bd9Sstevel@tonic-gate usage(); 1427c478bd9Sstevel@tonic-gate return (1); 1437c478bd9Sstevel@tonic-gate } 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate while (fgets(line, sizeof (line) - 1, fp) != NULL) { 1467c478bd9Sstevel@tonic-gate linecount++; 1477c478bd9Sstevel@tonic-gate strcpy(pline, line); 1487c478bd9Sstevel@tonic-gate argcount = split_line(pline, argvec, 1497c478bd9Sstevel@tonic-gate sizeof (argvec) / sizeof (argvec[0])); 1507c478bd9Sstevel@tonic-gate #ifdef DEBUG 1517c478bd9Sstevel@tonic-gate { 1527c478bd9Sstevel@tonic-gate int i; 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate printf("scanned %d args\n", argcount); 1557c478bd9Sstevel@tonic-gate for (i = 0; i < argcount; i++) 1567c478bd9Sstevel@tonic-gate printf("arg[%d]: %s\n", i, argvec[i]); 1577c478bd9Sstevel@tonic-gate } 1587c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 1597c478bd9Sstevel@tonic-gate switch (argcount) { 1607c478bd9Sstevel@tonic-gate case 0: 1617c478bd9Sstevel@tonic-gate /* Empty line - or comment only line */ 1627c478bd9Sstevel@tonic-gate break; 1637c478bd9Sstevel@tonic-gate case 3: 1647c478bd9Sstevel@tonic-gate numerror += parse_params(argvec[0], argvec[1], 1657c478bd9Sstevel@tonic-gate argvec[2], NULL, linecount); 1667c478bd9Sstevel@tonic-gate break; 1677c478bd9Sstevel@tonic-gate case 4: 1687c478bd9Sstevel@tonic-gate numerror += parse_params(argvec[0], argvec[1], 1697c478bd9Sstevel@tonic-gate argvec[2], argvec[3], linecount); 1707c478bd9Sstevel@tonic-gate break; 1717c478bd9Sstevel@tonic-gate default: 1727c478bd9Sstevel@tonic-gate numerror++; 1737c478bd9Sstevel@tonic-gate fprintf(stderr, 1747c478bd9Sstevel@tonic-gate gettext("Malformed line: <%s>\n"), line); 1757c478bd9Sstevel@tonic-gate fprintf(stderr, 1767c478bd9Sstevel@tonic-gate gettext("\ton line %d\n"), linecount); 1777c478bd9Sstevel@tonic-gate break; 1787c478bd9Sstevel@tonic-gate } 1797c478bd9Sstevel@tonic-gate } 1807c478bd9Sstevel@tonic-gate (void) fclose(fp); 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate if (numerror > 0) 1837c478bd9Sstevel@tonic-gate return (1); 1847c478bd9Sstevel@tonic-gate else 1857c478bd9Sstevel@tonic-gate return (0); 1867c478bd9Sstevel@tonic-gate } 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate /* 1897c478bd9Sstevel@tonic-gate * Parse a line splitting it off at whitspace characters. 1907c478bd9Sstevel@tonic-gate * Modifies the content of the string by inserting NULLs. 1917c478bd9Sstevel@tonic-gate */ 1927c478bd9Sstevel@tonic-gate static int 1937c478bd9Sstevel@tonic-gate split_line(char *line, char *argvec[], int maxargvec) 1947c478bd9Sstevel@tonic-gate { 1957c478bd9Sstevel@tonic-gate int i = 0; 1967c478bd9Sstevel@tonic-gate char *cp; 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate /* Truncate at the beginning of a comment */ 1997c478bd9Sstevel@tonic-gate cp = strchr(line, '#'); 2007c478bd9Sstevel@tonic-gate if (cp != NULL) 2017c478bd9Sstevel@tonic-gate *cp = NULL; 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate /* CONSTCOND */ 2047c478bd9Sstevel@tonic-gate while (1) { 2057c478bd9Sstevel@tonic-gate /* Skip any whitespace */ 2067c478bd9Sstevel@tonic-gate while (isspace(*line) && *line != NULL) 2077c478bd9Sstevel@tonic-gate line++; 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate if (i >= maxargvec) 2107c478bd9Sstevel@tonic-gate return (i); 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate argvec[i] = line; 2137c478bd9Sstevel@tonic-gate if (*line == NULL) 2147c478bd9Sstevel@tonic-gate return (i); 2157c478bd9Sstevel@tonic-gate i++; 2167c478bd9Sstevel@tonic-gate /* Skip until next whitespace */ 2177c478bd9Sstevel@tonic-gate while (!isspace(*line) && *line != NULL) 2187c478bd9Sstevel@tonic-gate line++; 2197c478bd9Sstevel@tonic-gate if (*line != NULL) { 2207c478bd9Sstevel@tonic-gate /* Break off argument */ 2217c478bd9Sstevel@tonic-gate *line++ = NULL; 2227c478bd9Sstevel@tonic-gate } 2237c478bd9Sstevel@tonic-gate } 2247c478bd9Sstevel@tonic-gate /* NOTREACHED */ 2257c478bd9Sstevel@tonic-gate } 2267c478bd9Sstevel@tonic-gate 2277c478bd9Sstevel@tonic-gate /* 2287c478bd9Sstevel@tonic-gate * Parse the set of parameters and issues the sockconfig syscall. 2297c478bd9Sstevel@tonic-gate * If line is not -1 it is assumed to be the line number in the file. 2307c478bd9Sstevel@tonic-gate */ 2317c478bd9Sstevel@tonic-gate static int 2327c478bd9Sstevel@tonic-gate parse_params(char *famstr, char *typestr, char *protostr, char *path, int line) 2337c478bd9Sstevel@tonic-gate { 234*3e95bd4aSAnders Persson int cmd, fam, type, protocol; 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate fam = parse_int(famstr); 2377c478bd9Sstevel@tonic-gate if (fam == -1) { 2387c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Bad family number: %s\n"), famstr); 2397c478bd9Sstevel@tonic-gate if (line != -1) 2407c478bd9Sstevel@tonic-gate fprintf(stderr, 2417c478bd9Sstevel@tonic-gate gettext("\ton line %d\n"), line); 2427c478bd9Sstevel@tonic-gate else { 2437c478bd9Sstevel@tonic-gate fprintf(stderr, "\n"); 2447c478bd9Sstevel@tonic-gate usage(); 2457c478bd9Sstevel@tonic-gate } 2467c478bd9Sstevel@tonic-gate return (1); 2477c478bd9Sstevel@tonic-gate } 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate type = parse_int(typestr); 2507c478bd9Sstevel@tonic-gate if (type == -1) { 2517c478bd9Sstevel@tonic-gate fprintf(stderr, 2527c478bd9Sstevel@tonic-gate gettext("Bad socket type number: %s\n"), typestr); 2537c478bd9Sstevel@tonic-gate if (line != -1) 2547c478bd9Sstevel@tonic-gate fprintf(stderr, 2557c478bd9Sstevel@tonic-gate gettext("\ton line %d\n"), line); 2567c478bd9Sstevel@tonic-gate else { 2577c478bd9Sstevel@tonic-gate fprintf(stderr, "\n"); 2587c478bd9Sstevel@tonic-gate usage(); 2597c478bd9Sstevel@tonic-gate } 2607c478bd9Sstevel@tonic-gate return (1); 2617c478bd9Sstevel@tonic-gate } 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate protocol = parse_int(protostr); 2647c478bd9Sstevel@tonic-gate if (protocol == -1) { 2657c478bd9Sstevel@tonic-gate fprintf(stderr, 2667c478bd9Sstevel@tonic-gate gettext("Bad protocol number: %s\n"), protostr); 2677c478bd9Sstevel@tonic-gate if (line != -1) 2687c478bd9Sstevel@tonic-gate fprintf(stderr, 2697c478bd9Sstevel@tonic-gate gettext("\ton line %d\n"), line); 2707c478bd9Sstevel@tonic-gate else { 2717c478bd9Sstevel@tonic-gate fprintf(stderr, "\n"); 2727c478bd9Sstevel@tonic-gate usage(); 2737c478bd9Sstevel@tonic-gate } 2747c478bd9Sstevel@tonic-gate return (1); 2757c478bd9Sstevel@tonic-gate } 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate 2787c478bd9Sstevel@tonic-gate if (path != NULL) { 2797c478bd9Sstevel@tonic-gate struct stat stats; 2807c478bd9Sstevel@tonic-gate 2810f1702c5SYu Xiangning if (strncmp(path, "/dev", strlen("/dev")) == 0 && 2820f1702c5SYu Xiangning stat(path, &stats) == -1) { 2837c478bd9Sstevel@tonic-gate perror(path); 2847c478bd9Sstevel@tonic-gate if (line != -1) 2857c478bd9Sstevel@tonic-gate fprintf(stderr, 2867c478bd9Sstevel@tonic-gate gettext("\ton line %d\n"), line); 2877c478bd9Sstevel@tonic-gate else { 2887c478bd9Sstevel@tonic-gate fprintf(stderr, "\n"); 2897c478bd9Sstevel@tonic-gate usage(); 2907c478bd9Sstevel@tonic-gate } 2917c478bd9Sstevel@tonic-gate return (1); 2927c478bd9Sstevel@tonic-gate } 293*3e95bd4aSAnders Persson 294*3e95bd4aSAnders Persson cmd = SOCKCONFIG_ADD_SOCK; 295*3e95bd4aSAnders Persson } else { 296*3e95bd4aSAnders Persson cmd = SOCKCONFIG_REMOVE_SOCK; 2977c478bd9Sstevel@tonic-gate } 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate #ifdef DEBUG 300*3e95bd4aSAnders Persson printf("not calling sockconfig(%d, %d, %d, %d, %s)\n", 301*3e95bd4aSAnders Persson cmd, fam, type, protocol, path == NULL ? "(null)" : path); 3027c478bd9Sstevel@tonic-gate #else 303*3e95bd4aSAnders Persson if (_sockconfig(cmd, fam, type, protocol, path) == -1) { 3047c478bd9Sstevel@tonic-gate perror("sockconfig"); 3057c478bd9Sstevel@tonic-gate return (1); 3067c478bd9Sstevel@tonic-gate } 3077c478bd9Sstevel@tonic-gate #endif 3087c478bd9Sstevel@tonic-gate return (0); 3097c478bd9Sstevel@tonic-gate } 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate static int 3127c478bd9Sstevel@tonic-gate parse_int(char *str) 3137c478bd9Sstevel@tonic-gate { 3147c478bd9Sstevel@tonic-gate char *end; 3157c478bd9Sstevel@tonic-gate int res; 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate res = strtol(str, &end, 0); 3187c478bd9Sstevel@tonic-gate if (end == str) 3197c478bd9Sstevel@tonic-gate return (-1); 3207c478bd9Sstevel@tonic-gate return (res); 3217c478bd9Sstevel@tonic-gate } 322*3e95bd4aSAnders Persson 323*3e95bd4aSAnders Persson /* 324*3e95bd4aSAnders Persson * Add and remove socket filters. 325*3e95bd4aSAnders Persson */ 326*3e95bd4aSAnders Persson static int 327*3e95bd4aSAnders Persson parse_filter_params(int argc, char **argv) 328*3e95bd4aSAnders Persson { 329*3e95bd4aSAnders Persson struct sockconfig_filter_props filprop; 330*3e95bd4aSAnders Persson sof_socktuple_t *socktuples; 331*3e95bd4aSAnders Persson size_t tupcnt, nalloc; 332*3e95bd4aSAnders Persson char *hintarg, *socktup, *tupstr; 333*3e95bd4aSAnders Persson int i; 334*3e95bd4aSAnders Persson 335*3e95bd4aSAnders Persson if (argc == 1) { 336*3e95bd4aSAnders Persson if (_sockconfig(SOCKCONFIG_REMOVE_FILTER, argv[0], 0, 337*3e95bd4aSAnders Persson 0, 0) < 0) { 338*3e95bd4aSAnders Persson switch (errno) { 339*3e95bd4aSAnders Persson case ENXIO: 340*3e95bd4aSAnders Persson fprintf(stderr, 341*3e95bd4aSAnders Persson gettext("socket filter is not configured " 342*3e95bd4aSAnders Persson "'%s'\n"), argv[0]); 343*3e95bd4aSAnders Persson break; 344*3e95bd4aSAnders Persson default: 345*3e95bd4aSAnders Persson perror("sockconfig"); 346*3e95bd4aSAnders Persson break; 347*3e95bd4aSAnders Persson } 348*3e95bd4aSAnders Persson return (1); 349*3e95bd4aSAnders Persson } 350*3e95bd4aSAnders Persson return (0); 351*3e95bd4aSAnders Persson } 352*3e95bd4aSAnders Persson 353*3e95bd4aSAnders Persson if (argc < 4 || argc > 5) 354*3e95bd4aSAnders Persson return (1); 355*3e95bd4aSAnders Persson 356*3e95bd4aSAnders Persson 357*3e95bd4aSAnders Persson if (strlen(argv[1]) >= MODMAXNAMELEN) { 358*3e95bd4aSAnders Persson fprintf(stderr, 359*3e95bd4aSAnders Persson gettext("invalid module name '%s': name too long\n"), 360*3e95bd4aSAnders Persson argv[1]); 361*3e95bd4aSAnders Persson return (1); 362*3e95bd4aSAnders Persson } 363*3e95bd4aSAnders Persson filprop.sfp_modname = argv[1]; 364*3e95bd4aSAnders Persson 365*3e95bd4aSAnders Persson /* Check the attach semantics */ 366*3e95bd4aSAnders Persson if (strcmp(argv[2], "auto") == 0) { 367*3e95bd4aSAnders Persson filprop.sfp_autoattach = B_TRUE; 368*3e95bd4aSAnders Persson if (argc == 5) { 369*3e95bd4aSAnders Persson /* placement hint */ 370*3e95bd4aSAnders Persson if (strcmp(argv[3], "top") == 0) { 371*3e95bd4aSAnders Persson filprop.sfp_hint = SOF_HINT_TOP; 372*3e95bd4aSAnders Persson } else if (strcmp(argv[3], "bottom") == 0) { 373*3e95bd4aSAnders Persson filprop.sfp_hint = SOF_HINT_BOTTOM; 374*3e95bd4aSAnders Persson } else { 375*3e95bd4aSAnders Persson if (strncmp(argv[3], "before", 6) == 0) { 376*3e95bd4aSAnders Persson filprop.sfp_hint = SOF_HINT_BEFORE; 377*3e95bd4aSAnders Persson } else if (strncmp(argv[3], "after", 5) == 0) { 378*3e95bd4aSAnders Persson filprop.sfp_hint = SOF_HINT_AFTER; 379*3e95bd4aSAnders Persson } else { 380*3e95bd4aSAnders Persson fprintf(stderr, 381*3e95bd4aSAnders Persson gettext("invalid placement hint " 382*3e95bd4aSAnders Persson "'%s'\n"), argv[3]); 383*3e95bd4aSAnders Persson return (1); 384*3e95bd4aSAnders Persson } 385*3e95bd4aSAnders Persson 386*3e95bd4aSAnders Persson hintarg = strchr(argv[3], ':'); 387*3e95bd4aSAnders Persson if (hintarg == NULL || 388*3e95bd4aSAnders Persson (strlen(++hintarg) == 0) || 389*3e95bd4aSAnders Persson (strlen(hintarg) >= FILNAME_MAX)) { 390*3e95bd4aSAnders Persson fprintf(stderr, 391*3e95bd4aSAnders Persson gettext("invalid placement hint " 392*3e95bd4aSAnders Persson "argument '%s': name too long\n"), 393*3e95bd4aSAnders Persson argv[3]); 394*3e95bd4aSAnders Persson return (1); 395*3e95bd4aSAnders Persson } 396*3e95bd4aSAnders Persson 397*3e95bd4aSAnders Persson filprop.sfp_hintarg = hintarg; 398*3e95bd4aSAnders Persson } 399*3e95bd4aSAnders Persson } else { 400*3e95bd4aSAnders Persson filprop.sfp_hint = SOF_HINT_NONE; 401*3e95bd4aSAnders Persson } 402*3e95bd4aSAnders Persson } else if (strcmp(argv[2], "prog") == 0) { 403*3e95bd4aSAnders Persson filprop.sfp_autoattach = B_FALSE; 404*3e95bd4aSAnders Persson filprop.sfp_hint = SOF_HINT_NONE; 405*3e95bd4aSAnders Persson /* cannot specify placement hint for programmatic filter */ 406*3e95bd4aSAnders Persson if (argc == 5) { 407*3e95bd4aSAnders Persson fprintf(stderr, 408*3e95bd4aSAnders Persson gettext("placement hint specified for programmatic " 409*3e95bd4aSAnders Persson "filter\n")); 410*3e95bd4aSAnders Persson return (1); 411*3e95bd4aSAnders Persson } 412*3e95bd4aSAnders Persson } else { 413*3e95bd4aSAnders Persson fprintf(stderr, gettext("invalid attach semantic '%s'\n"), 414*3e95bd4aSAnders Persson argv[2]); 415*3e95bd4aSAnders Persson return (1); 416*3e95bd4aSAnders Persson } 417*3e95bd4aSAnders Persson 418*3e95bd4aSAnders Persson /* parse the socket tuples */ 419*3e95bd4aSAnders Persson nalloc = 4; 420*3e95bd4aSAnders Persson socktuples = calloc(nalloc, sizeof (sof_socktuple_t)); 421*3e95bd4aSAnders Persson if (socktuples == NULL) { 422*3e95bd4aSAnders Persson perror("calloc"); 423*3e95bd4aSAnders Persson return (1); 424*3e95bd4aSAnders Persson } 425*3e95bd4aSAnders Persson 426*3e95bd4aSAnders Persson tupcnt = 0; 427*3e95bd4aSAnders Persson tupstr = argv[(argc == 4) ? 3 : 4]; 428*3e95bd4aSAnders Persson while ((socktup = strsep(&tupstr, ",")) != NULL) { 429*3e95bd4aSAnders Persson int val; 430*3e95bd4aSAnders Persson char *valstr; 431*3e95bd4aSAnders Persson 432*3e95bd4aSAnders Persson if (tupcnt == nalloc) { 433*3e95bd4aSAnders Persson sof_socktuple_t *new; 434*3e95bd4aSAnders Persson 435*3e95bd4aSAnders Persson nalloc *= 2; 436*3e95bd4aSAnders Persson new = realloc(socktuples, 437*3e95bd4aSAnders Persson nalloc * sizeof (sof_socktuple_t)); 438*3e95bd4aSAnders Persson if (new == NULL) { 439*3e95bd4aSAnders Persson perror("realloc"); 440*3e95bd4aSAnders Persson free(socktuples); 441*3e95bd4aSAnders Persson return (1); 442*3e95bd4aSAnders Persson } 443*3e95bd4aSAnders Persson socktuples = new; 444*3e95bd4aSAnders Persson } 445*3e95bd4aSAnders Persson i = 0; 446*3e95bd4aSAnders Persson while ((valstr = strsep(&socktup, ":")) != NULL && i < 3) { 447*3e95bd4aSAnders Persson val = parse_int(valstr); 448*3e95bd4aSAnders Persson if (val == -1) { 449*3e95bd4aSAnders Persson fprintf(stderr, gettext("bad socket tuple\n")); 450*3e95bd4aSAnders Persson free(socktuples); 451*3e95bd4aSAnders Persson return (1); 452*3e95bd4aSAnders Persson } 453*3e95bd4aSAnders Persson switch (i) { 454*3e95bd4aSAnders Persson case 0: socktuples[tupcnt].sofst_family = val; break; 455*3e95bd4aSAnders Persson case 1: socktuples[tupcnt].sofst_type = val; break; 456*3e95bd4aSAnders Persson case 2: socktuples[tupcnt].sofst_protocol = val; break; 457*3e95bd4aSAnders Persson } 458*3e95bd4aSAnders Persson i++; 459*3e95bd4aSAnders Persson } 460*3e95bd4aSAnders Persson if (i != 3) { 461*3e95bd4aSAnders Persson fprintf(stderr, gettext("bad socket tuple\n")); 462*3e95bd4aSAnders Persson free(socktuples); 463*3e95bd4aSAnders Persson return (1); 464*3e95bd4aSAnders Persson } 465*3e95bd4aSAnders Persson tupcnt++; 466*3e95bd4aSAnders Persson } 467*3e95bd4aSAnders Persson if (tupcnt == 0) { 468*3e95bd4aSAnders Persson fprintf(stderr, gettext("no socket tuples specified\n")); 469*3e95bd4aSAnders Persson free(socktuples); 470*3e95bd4aSAnders Persson return (1); 471*3e95bd4aSAnders Persson } 472*3e95bd4aSAnders Persson filprop.sfp_socktuple_cnt = tupcnt; 473*3e95bd4aSAnders Persson filprop.sfp_socktuple = socktuples; 474*3e95bd4aSAnders Persson 475*3e95bd4aSAnders Persson if (_sockconfig(SOCKCONFIG_ADD_FILTER, argv[0], &filprop, 0, 0) < 0) { 476*3e95bd4aSAnders Persson switch (errno) { 477*3e95bd4aSAnders Persson case EINVAL: 478*3e95bd4aSAnders Persson fprintf(stderr, 479*3e95bd4aSAnders Persson gettext("invalid socket filter configuration\n")); 480*3e95bd4aSAnders Persson break; 481*3e95bd4aSAnders Persson case EEXIST: 482*3e95bd4aSAnders Persson fprintf(stderr, 483*3e95bd4aSAnders Persson gettext("socket filter is already configured " 484*3e95bd4aSAnders Persson "'%s'\n"), argv[0]); 485*3e95bd4aSAnders Persson break; 486*3e95bd4aSAnders Persson case ENOSPC: 487*3e95bd4aSAnders Persson fprintf(stderr, gettext("unable to satisfy placement " 488*3e95bd4aSAnders Persson "constraint\n")); 489*3e95bd4aSAnders Persson break; 490*3e95bd4aSAnders Persson default: 491*3e95bd4aSAnders Persson perror("sockconfig"); 492*3e95bd4aSAnders Persson break; 493*3e95bd4aSAnders Persson } 494*3e95bd4aSAnders Persson free(socktuples); 495*3e95bd4aSAnders Persson return (1); 496*3e95bd4aSAnders Persson } 497*3e95bd4aSAnders Persson free(socktuples); 498*3e95bd4aSAnders Persson return (0); 499*3e95bd4aSAnders Persson } 500