sppptun.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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
*/
/*
* sppptun.c - Solaris STREAMS PPP multiplexing tunnel driver
* installer.
*
* Copyright (c) 2000-2001 by Sun Microsystems, Inc.
* All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <signal.h>
#include <alloca.h>
#include <stropts.h>
#include <fcntl.h>
#include <locale.h>
#include <netinet/if_ether.h>
static char *myname; /* Copied from argv[0] */
static int verbose; /* -v on command line */
/* Data gathered during per-style attach routine. */
struct attach_data {
int locallen; /* Length of local address */
};
/* Per-protocol plumbing data */
struct protos {
const char *name;
const char *desc;
struct attach_data *adata);
int protval;
int style;
};
/*
* Print a usage string and terminate. Used for command line argument
* errors. Does not return.
*/
static void
usage(void)
{
"Usage:\n\t%s plumb [<protocol> <device>]\n"
"\t%s unplumb <interface-name>\n"
exit(1);
}
/*
* Await a DLPI response to a previous driver command. "etype" is set
* to the expected response primitive. "rptr" and "rlen" may point to
* a buffer to hold returned data, if desired. Otherwise, "rptr" is
* NULL. Returns -1 on error, 0 on success.
*
* If "rlen" is a positive number, then it indicates the number of
* bytes expected in return, and any longer response is truncated to
* that value, and any shorter response generates a warning message.
* If it's a negative number, then it indicates the maximum number of
* bytes expected, and no warning is printed if fewer are received.
*/
static int
{
/* Align 'buf' on natural boundary for aggregates. */
int flags;
/* read reply */
flags = 0;
perror("getmsg");
return (-1);
}
/* Validate reply. */
myname);
return (-1);
}
return (-1);
}
return (-1);
}
return (0);
return (-1);
}
if (rlen < 0)
return (0);
}
/*
* Send a DLPI Info-Request message and return the response in the
* provided buffer. Returns -1 on error, 0 on success.
*/
static int
{
int flags;
flags = 0;
perror("putmsg DL_INFO_REQ");
return (-1);
}
}
/*
* Send a DLPI Attach-Request message for the indicated PPA. Returns
* -1 on error, 0 for success.
*/
static int
{
int flags;
flags = 0;
perror("putmsg DL_ATTACH_REQ");
return (-1);
}
}
/*
* Send a DLPI Bind-Request message for the requested SAP and set the
* local address. Returns -1 for error. Otherwise, the length of the
* local address is returned.
*/
static int
{
/* DLPI SAPs are in host byte order! */
flags = 0;
perror("putmsg DL_BIND_REQ");
return (-1);
}
return (-1);
"from driver; %d > %d or %lu+%d > %d\n"), myname,
return (-1);
}
return (rsize);
}
/*
* Return a printable string for a DLPI style number. (Unfortunately,
* these style numbers aren't just simple integer values, and printing
* with %d gives ugly output.)
*/
static const char *
{
static char buf[32];
switch (dlstyle) {
case DL_STYLE1:
return ("1");
case DL_STYLE2:
return ("2");
}
dlstyle);
return ((const char *)buf);
}
/*
* General DLPI attach function. This is called indirectly through
* the protos structure for the selected lower stream protocol.
*/
static int
{
cp--;
cp++;
/*
* Try once for the exact device name as a node. If it's
* there, then this should be a DLPI style 1 driver (one node
* per instance). If it's not, then it should be a style 2
* driver (attach specifies instance number).
*/
return (-1);
}
}
if (verbose)
tname);
return (-1);
if (ifname[0] != '\0' &&
"instance number?)\n"));
}
return (-1);
}
if (verbose)
return (-1);
}
}
if (verbose)
if (retv < 0) {
return (-1);
}
return (devfd);
}
static struct protos proto_list[] = {
PTS_PPPOE },
{ NULL }
};
/*
* Issue a STREAMS I_STR ioctl and fetch the result. Returns -1 on
* error, or length of returned data on success.
*/
static int
{
return (-1);
}
if (olen >= 0) {
return (-1);
}
}
}
/*
* Handle user request to plumb a new lower stream under the sppptun
* driver.
*/
static int
{
struct ppptun_info pti;
char dname[MAXPATHLEN];
struct attach_data adata;
/* If no protocol requested, then list known protocols. */
(void) puts("Known tunneling protocols:");
return (0);
}
/* If missing protocol or device, then abort. */
usage();
/* Look up requested protocol. */
break;
return (1);
}
/* Get interface and make relative to /dev/ if necessary. */
}
/* Call per-protocol attach routine to open device */
if (verbose)
if (devfd < 0)
return (1);
/* Open sppptun driver */
if (verbose)
return (1);
}
/* Push sppptun module on top of lower driver. */
if (verbose)
ifname);
return (1);
}
/* Get the name of the newly-created lower stream. */
if (verbose)
return (1);
if (verbose)
/* Convert stream name to protocol-specific name. */
*cp = '\0';
/* Change the lower stream name. */
if (verbose)
return (1);
}
/*
* Send down the local interface address to the lower stream
* so that it can originate packets.
*/
if (verbose)
0, "PPPTUN_LCLADDR") < 0)
return (1);
/* Link the lower stream under the tunnel device. */
if (verbose)
perror("I_PLINK");
return (1);
}
/*
* Give the tunnel driver the multiplex ID of the new lower
* stream. This allows the unplumb function to find and
* disconnect the lower stream.
*/
if (verbose)
"PPPTUN_SINFO") < 0)
return (1);
if (verbose)
else
return (0);
}
/*
* Handle user request to unplumb an existing lower stream from the
* sppptun driver.
*/
static int
{
char *ifname;
int muxfd;
struct ppptun_info pti;
/*
* Need to have the name of the lower stream on the command
* line.
*/
usage();
/* Open the tunnel driver. */
if (verbose)
return (1);
}
/* Get lower stream information; including multiplex ID. */
if (verbose)
sizeof (pti), "PPPTUN_GINFO") < 0)
return (1);
if (verbose)
/* Unlink lower stream from driver. */
if (verbose)
perror("I_PUNLINK");
return (1);
}
if (verbose)
return (0);
}
/*
* Handle user request to list lower streams plumbed under the sppptun
* driver.
*/
/*ARGSUSED*/
static int
{
int muxfd, i;
union ppptun_name ptn;
/* No other arguments permitted. */
usage();
/* Open the tunnel driver. */
if (verbose)
return (1);
}
/* Read and print names of lower streams. */
for (i = 0; ; i++) {
sizeof (ptn), "PPPTUN_GNNAME") < 0) {
perror("PPPTUN_GNNAME");
break;
}
/* Stop when we index off the end of the list. */
break;
}
return (0);
}
/*
* Invoked by SIGALRM -- timer prevents problems in driver from
* hanging the utility.
*/
/*ARGSUSED*/
static void
{
exit(1);
}
int
{
char *arg;
#if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
#define TEXT_DOMAIN "SYS_TEST"
#endif
(void) textdomain(TEXT_DOMAIN);
/* Parse command line flags */
switch (opt) {
case 'v':
verbose++;
break;
default:
errflag++;
break;
}
usage();
/* Set alarm to avoid stalling on any driver errors. */
(void) alarm(2);
/* Switch out based on user-requested function. */
usage();
return (1);
}