/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
*/
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socketvar.h>
#include <unistd.h>
/*
* Usage:
* soconfig -d <dir>
* Reads input from files in dir.
*
* soconfig -f <file>
* Reads input from file. The file is structured as
* <fam> <type> <protocol> <path|module>
* <fam> <type> <protocol>
* with the first line registering and the second line
* deregistering.
*
* soconfig <fam> <type> <protocol> <path|module>
* registers
*
* soconfig <fam> <type> <protocol>
* deregisters
*
* soconfig -l
* print the in-kernel socket configuration table
*
* Filter Operations (Consolidation Private):
*
* soconfig -F <name> <modname> {auto [top | bottom | before:filter |
* after:filter] | prog} <fam>:<type>:<proto>,...
* configure filter
*
* soconfig -F <name>
* unconfigures filter
*/
static int parse_files_in_dir(const char *dir);
static int parse_file(char *filename);
static void usage(void);
static int print_socktable();
int
int argc;
char *argv[];
{
int ret;
#if !defined(TEXT_DOMAIN)
#endif
(void) textdomain(TEXT_DOMAIN);
ret = print_socktable();
}
}
}
}
if (argc == 3) {
}
if (argc == 4) {
NULL, -1);
}
usage();
exit(1);
/* NOTREACHED */
}
static void
usage(void)
{
"Usage: soconfig -d <dir>\n"
"\tsoconfig -f <file>\n"
"\tsoconfig <fam> <type> <protocol> <path|module>\n"
"\tsoconfig <fam> <type> <protocol>\n"
"\tsoconfig -l\n"));
}
/*
* Parse all files in the given directory.
*/
static int
{
return (1);
}
continue;
gettext("path name is too long: %s/%s\n"),
continue;
}
continue;
}
continue;
(void) parse_file(buf);
}
return (0);
}
/*
* Open the specified file and parse each line. Skip comments (everything
* after a '#'). Return 1 if at least one error was encountered; otherwise 0.
*/
static int
{
int argcount;
int linecount = 0;
int numerror = 0;
perror("soconfig: open");
usage();
return (1);
}
linecount++;
#ifdef DEBUG
{
int i;
for (i = 0; i < argcount; i++)
}
#endif /* DEBUG */
switch (argcount) {
case 0:
/* Empty line - or comment only line */
break;
case 3:
break;
case 4:
break;
default:
numerror++;
filename);
break;
}
}
if (numerror > 0)
return (1);
else
return (0);
}
/*
* Parse a line splitting it off at whitspace characters.
* Modifies the content of the string by inserting NULLs.
*/
static int
{
int i = 0;
char *cp;
/* Truncate at the beginning of a comment */
/* CONSTCOND */
while (1) {
/* Skip any whitespace */
line++;
if (i >= maxargvec)
return (i);
return (i);
i++;
/* Skip until next whitespace */
line++;
/* Break off argument */
}
}
/* NOTREACHED */
}
/*
* Parse the set of parameters and issues the sockconfig syscall.
* If line is not -1 it is assumed to be the line number in the file.
*/
static int
{
if (fam == -1) {
if (line != -1)
else {
usage();
}
return (1);
}
if (type == -1) {
if (line != -1)
else {
usage();
}
return (1);
}
if (protocol == -1) {
if (line != -1)
else {
usage();
}
return (1);
}
if (line != -1)
file);
else {
usage();
}
return (1);
}
} else {
}
#ifdef DEBUG
printf("not calling sockconfig(%d, %d, %d, %d, %s)\n",
#else
char *s;
switch (errno) {
case EEXIST:
s = gettext("Mapping exists");
break;
default:
break;
}
gettext("warning: socket configuration failed "
"for family %d type %d protocol %d: %s\n"),
if (line != -1) {
}
return (1);
}
#endif
return (0);
}
static int
{
char *end;
int res;
return (-1);
return (res);
}
/*
* Add and remove socket filters.
*/
static int
{
int i;
if (argc == 1) {
0, 0) < 0) {
switch (errno) {
case ENXIO:
gettext("socket filter is not configured "
"'%s'\n"), argv[0]);
break;
default:
perror("sockconfig");
break;
}
return (1);
}
return (0);
}
return (1);
gettext("invalid module name '%s': name too long\n"),
argv[1]);
return (1);
}
/* Check the attach semantics */
if (argc == 5) {
/* placement hint */
} else {
} else {
gettext("invalid placement hint "
return (1);
}
gettext("invalid placement hint "
"argument '%s': name too long\n"),
argv[3]);
return (1);
}
}
} else {
}
/* cannot specify placement hint for programmatic filter */
if (argc == 5) {
gettext("placement hint specified for programmatic "
"filter\n"));
return (1);
}
} else {
argv[2]);
return (1);
}
/* parse the socket tuples */
nalloc = 4;
if (socktuples == NULL) {
perror("calloc");
return (1);
}
tupcnt = 0;
int val;
char *valstr;
nalloc *= 2;
nalloc * sizeof (sof_socktuple_t));
perror("realloc");
return (1);
}
socktuples = new;
}
i = 0;
if (val == -1) {
return (1);
}
switch (i) {
}
i++;
}
if (i != 3) {
return (1);
}
tupcnt++;
}
if (tupcnt == 0) {
return (1);
}
switch (errno) {
case EINVAL:
gettext("invalid socket filter configuration\n"));
break;
case EEXIST:
gettext("socket filter is already configured "
"'%s'\n"), argv[0]);
break;
case ENOSPC:
"constraint\n"));
break;
default:
perror("sockconfig");
break;
}
return (1);
}
return (0);
}
/*
* Print the in-kernel socket configuration table
*/
static int
{
int i;
/* get number of entries */
gettext("cannot get in-kernel socket table: %s\n"),
return (-1);
}
if (sc_table.num_of_entries == 0)
return (0);
sizeof (sockconfig_socktable_entry_t));
return (-1);
}
/* get socket table entries */
gettext("cannot get in-kernel socket table: %s\n"),
return (-1);
}
printf("%6s %4s %5s %15s %15s %6s %6s\n",
"FAMILY", "TYPE", "PROTO", "STRDEV", "SOCKMOD",
"REFS", "FLAGS");
for (i = 0; i < sc_table.num_of_entries; i++) {
printf("%6u %4u %5u %15s %15s %6u %#6x\n",
"socktpi") == 0) ?
}
return (0);
}