10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
56631Sss150715 * Common Development and Distribution License (the "License").
66631Sss150715 * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
220Sstevel@tonic-gate * sppptun.c - Solaris STREAMS PPP multiplexing tunnel driver
230Sstevel@tonic-gate * installer.
240Sstevel@tonic-gate *
25*9751Sjames.d.carlson@sun.com * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
266631Sss150715 * Use is subject to license terms.
270Sstevel@tonic-gate */
280Sstevel@tonic-gate
290Sstevel@tonic-gate #include <stdio.h>
300Sstevel@tonic-gate #include <stdlib.h>
310Sstevel@tonic-gate #include <unistd.h>
320Sstevel@tonic-gate #include <string.h>
330Sstevel@tonic-gate #include <ctype.h>
340Sstevel@tonic-gate #include <errno.h>
350Sstevel@tonic-gate #include <signal.h>
360Sstevel@tonic-gate #include <stropts.h>
370Sstevel@tonic-gate #include <fcntl.h>
380Sstevel@tonic-gate #include <locale.h>
390Sstevel@tonic-gate #include <sys/fcntl.h>
400Sstevel@tonic-gate #include <sys/stropts.h>
410Sstevel@tonic-gate #include <sys/socket.h>
420Sstevel@tonic-gate #include <net/if.h>
430Sstevel@tonic-gate #include <netinet/in.h>
440Sstevel@tonic-gate #include <netinet/if_ether.h>
450Sstevel@tonic-gate #include <net/sppptun.h>
466631Sss150715 #include <libdlpi.h>
470Sstevel@tonic-gate
480Sstevel@tonic-gate static char *myname; /* Copied from argv[0] */
490Sstevel@tonic-gate static int verbose; /* -v on command line */
500Sstevel@tonic-gate
510Sstevel@tonic-gate /* Data gathered during per-style attach routine. */
520Sstevel@tonic-gate struct attach_data {
536631Sss150715 ppptun_lname appstr; /* String to append to interface name (PPA) */
546631Sss150715 ppptun_atype localaddr; /* Local interface address */
556631Sss150715 uint_t locallen; /* Length of local address */
56*9751Sjames.d.carlson@sun.com uint_t sap; /* SAP for PPPoE */
570Sstevel@tonic-gate };
580Sstevel@tonic-gate
590Sstevel@tonic-gate /* Per-protocol plumbing data */
600Sstevel@tonic-gate struct protos {
610Sstevel@tonic-gate const char *name;
620Sstevel@tonic-gate const char *desc;
636631Sss150715 int (*attach)(struct protos *prot, char *linkname,
640Sstevel@tonic-gate struct attach_data *adata);
656631Sss150715 uint_t protval;
660Sstevel@tonic-gate int style;
670Sstevel@tonic-gate };
680Sstevel@tonic-gate
690Sstevel@tonic-gate /*
700Sstevel@tonic-gate * Print a usage string and terminate. Used for command line argument
710Sstevel@tonic-gate * errors. Does not return.
720Sstevel@tonic-gate */
730Sstevel@tonic-gate static void
usage(void)740Sstevel@tonic-gate usage(void)
750Sstevel@tonic-gate {
760Sstevel@tonic-gate (void) fprintf(stderr, gettext(
77*9751Sjames.d.carlson@sun.com "Usage:\n\t%s plumb [-s <sap>] [<protocol> <device>]\n"
786631Sss150715 "\t%s unplumb <interface-name>\n"
796631Sss150715 "\t%s query\n"), myname, myname, myname);
800Sstevel@tonic-gate exit(1);
810Sstevel@tonic-gate }
820Sstevel@tonic-gate
830Sstevel@tonic-gate /*
846631Sss150715 * General DLPI function. This is called indirectly through
856631Sss150715 * the protos structure for the selected lower stream protocol.
860Sstevel@tonic-gate */
87*9751Sjames.d.carlson@sun.com /* ARGSUSED */
880Sstevel@tonic-gate static int
sppp_dlpi(struct protos * prot,char * linkname,struct attach_data * adata)896631Sss150715 sppp_dlpi(struct protos *prot, char *linkname, struct attach_data *adata)
900Sstevel@tonic-gate {
916631Sss150715 int retv;
926631Sss150715 dlpi_handle_t dh;
930Sstevel@tonic-gate
946631Sss150715 if (verbose)
956631Sss150715 (void) printf(gettext("opening DLPI link %s\n"), linkname);
966631Sss150715 if ((retv = dlpi_open(linkname, &dh, 0)) != DLPI_SUCCESS) {
976631Sss150715 (void) fprintf(stderr, gettext("%s: failed opening %s: %s\n"),
986631Sss150715 myname, linkname, dlpi_strerror(retv));
990Sstevel@tonic-gate return (-1);
1000Sstevel@tonic-gate }
1010Sstevel@tonic-gate
1026631Sss150715 if (verbose) {
1036631Sss150715 (void) printf(gettext("binding to Ethertype %04X\n"),
104*9751Sjames.d.carlson@sun.com adata->sap);
1050Sstevel@tonic-gate }
106*9751Sjames.d.carlson@sun.com if ((retv = dlpi_bind(dh, adata->sap, NULL)) != DLPI_SUCCESS) {
107*9751Sjames.d.carlson@sun.com (void) fprintf(stderr,
108*9751Sjames.d.carlson@sun.com gettext("%s: failed binding on %s: %s\n"),
1096631Sss150715 myname, linkname, dlpi_strerror(retv));
1106631Sss150715 dlpi_close(dh);
1110Sstevel@tonic-gate return (-1);
1120Sstevel@tonic-gate }
1130Sstevel@tonic-gate
1146631Sss150715 adata->locallen = DLPI_PHYSADDR_MAX;
1156631Sss150715 if ((retv = dlpi_get_physaddr(dh, DL_CURR_PHYS_ADDR, &adata->localaddr,
1166631Sss150715 &adata->locallen)) != DLPI_SUCCESS) {
1176631Sss150715 (void) fprintf(stderr, gettext("%s: failed getting physical"
118*9751Sjames.d.carlson@sun.com " address on %s: %s\n"), myname, linkname,
1196631Sss150715 dlpi_strerror(retv));
1206631Sss150715 dlpi_close(dh);
1210Sstevel@tonic-gate return (-1);
1220Sstevel@tonic-gate }
1230Sstevel@tonic-gate
124*9751Sjames.d.carlson@sun.com if (strlcpy(adata->appstr, linkname, sizeof (adata->appstr)) >=
125*9751Sjames.d.carlson@sun.com sizeof (adata->appstr)) {
126*9751Sjames.d.carlson@sun.com (void) fprintf(stderr,
127*9751Sjames.d.carlson@sun.com gettext("%s: interface name too long: %s\n"),
128*9751Sjames.d.carlson@sun.com myname, linkname);
1296631Sss150715 dlpi_close(dh);
1306631Sss150715 return (-1);
1310Sstevel@tonic-gate }
1320Sstevel@tonic-gate
1336631Sss150715 return (dlpi_fd(dh));
1340Sstevel@tonic-gate }
1350Sstevel@tonic-gate
1360Sstevel@tonic-gate
1370Sstevel@tonic-gate static struct protos proto_list[] = {
1386631Sss150715 { "pppoe", "RFC 2516 PPP over Ethernet", sppp_dlpi, ETHERTYPE_PPPOES,
1390Sstevel@tonic-gate PTS_PPPOE },
1406631Sss150715 { "pppoed", "RFC 2516 PPP over Ethernet Discovery", sppp_dlpi,
1410Sstevel@tonic-gate ETHERTYPE_PPPOED, PTS_PPPOE },
1420Sstevel@tonic-gate { NULL }
1430Sstevel@tonic-gate };
1440Sstevel@tonic-gate
1450Sstevel@tonic-gate /*
1460Sstevel@tonic-gate * Issue a STREAMS I_STR ioctl and fetch the result. Returns -1 on
1470Sstevel@tonic-gate * error, or length of returned data on success.
1480Sstevel@tonic-gate */
1490Sstevel@tonic-gate static int
strioctl(int fd,int cmd,void * ptr,int ilen,int olen,const char * iocname)1500Sstevel@tonic-gate strioctl(int fd, int cmd, void *ptr, int ilen, int olen, const char *iocname)
1510Sstevel@tonic-gate {
1520Sstevel@tonic-gate struct strioctl str;
1530Sstevel@tonic-gate
1540Sstevel@tonic-gate str.ic_cmd = cmd;
1550Sstevel@tonic-gate str.ic_timout = 0;
1560Sstevel@tonic-gate str.ic_len = ilen;
1570Sstevel@tonic-gate str.ic_dp = ptr;
1580Sstevel@tonic-gate
1590Sstevel@tonic-gate if (ioctl(fd, I_STR, &str) == -1) {
1600Sstevel@tonic-gate perror(iocname);
1610Sstevel@tonic-gate return (-1);
1620Sstevel@tonic-gate }
1630Sstevel@tonic-gate
1640Sstevel@tonic-gate if (olen >= 0) {
1650Sstevel@tonic-gate if (str.ic_len > olen && verbose > 1) {
1660Sstevel@tonic-gate (void) printf(gettext("%s:%s: extra data received; "
1670Sstevel@tonic-gate "%d > %d\n"), myname, iocname, str.ic_len, olen);
1680Sstevel@tonic-gate } else if (str.ic_len < olen) {
1690Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s:%s: expected %d "
1700Sstevel@tonic-gate "bytes, got %d\n"), myname, iocname, olen,
1710Sstevel@tonic-gate str.ic_len);
1720Sstevel@tonic-gate return (-1);
1730Sstevel@tonic-gate }
1740Sstevel@tonic-gate }
1750Sstevel@tonic-gate
1760Sstevel@tonic-gate return (str.ic_len);
1770Sstevel@tonic-gate }
1780Sstevel@tonic-gate
1790Sstevel@tonic-gate /*
1800Sstevel@tonic-gate * Handle user request to plumb a new lower stream under the sppptun
1810Sstevel@tonic-gate * driver.
1820Sstevel@tonic-gate */
1830Sstevel@tonic-gate static int
plumb_it(int argc,char ** argv)1840Sstevel@tonic-gate plumb_it(int argc, char **argv)
1850Sstevel@tonic-gate {
186*9751Sjames.d.carlson@sun.com int opt, devfd, muxfd, muxid;
1870Sstevel@tonic-gate struct ppptun_info pti;
1886631Sss150715 char *cp, *linkname;
1890Sstevel@tonic-gate struct protos *prot;
1900Sstevel@tonic-gate struct attach_data adata;
191*9751Sjames.d.carlson@sun.com uint_t sap = 0;
1920Sstevel@tonic-gate
1930Sstevel@tonic-gate /* If no protocol requested, then list known protocols. */
1940Sstevel@tonic-gate if (optind == argc) {
1950Sstevel@tonic-gate (void) puts("Known tunneling protocols:");
1960Sstevel@tonic-gate for (prot = proto_list; prot->name != NULL; prot++)
1970Sstevel@tonic-gate (void) printf("\t%s\t%s\n", prot->name, prot->desc);
1980Sstevel@tonic-gate return (0);
1990Sstevel@tonic-gate }
2000Sstevel@tonic-gate
201*9751Sjames.d.carlson@sun.com /* Parse plumbing flags */
202*9751Sjames.d.carlson@sun.com while ((opt = getopt(argc, argv, "s:")) != EOF) {
203*9751Sjames.d.carlson@sun.com switch (opt) {
204*9751Sjames.d.carlson@sun.com case 's':
205*9751Sjames.d.carlson@sun.com sap = strtoul(optarg, NULL, 16);
206*9751Sjames.d.carlson@sun.com break;
207*9751Sjames.d.carlson@sun.com default:
208*9751Sjames.d.carlson@sun.com usage();
209*9751Sjames.d.carlson@sun.com }
210*9751Sjames.d.carlson@sun.com }
211*9751Sjames.d.carlson@sun.com
2120Sstevel@tonic-gate /* If missing protocol or device, then abort. */
2130Sstevel@tonic-gate if (optind != argc-2)
2140Sstevel@tonic-gate usage();
2150Sstevel@tonic-gate
2160Sstevel@tonic-gate /* Look up requested protocol. */
2170Sstevel@tonic-gate cp = argv[optind++];
2180Sstevel@tonic-gate for (prot = proto_list; prot->name != NULL; prot++)
2190Sstevel@tonic-gate if (strcasecmp(cp, prot->name) == 0)
2200Sstevel@tonic-gate break;
2210Sstevel@tonic-gate if (prot->name == NULL) {
2220Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: unknown protocol %s\n"),
2230Sstevel@tonic-gate myname, cp);
2240Sstevel@tonic-gate return (1);
2250Sstevel@tonic-gate }
2260Sstevel@tonic-gate
227*9751Sjames.d.carlson@sun.com adata.sap = sap == 0 ? prot->protval : sap;
228*9751Sjames.d.carlson@sun.com
2296631Sss150715 /* Get interface. */
2306631Sss150715 linkname = argv[optind];
2310Sstevel@tonic-gate /* Call per-protocol attach routine to open device */
2320Sstevel@tonic-gate if (verbose)
2336631Sss150715 (void) printf(gettext("opening %s\n"), linkname);
2346631Sss150715 if ((devfd = (*prot->attach)(prot, linkname, &adata)) < 0)
2350Sstevel@tonic-gate return (1);
2360Sstevel@tonic-gate
2370Sstevel@tonic-gate /* Open sppptun driver */
2380Sstevel@tonic-gate if (verbose)
2390Sstevel@tonic-gate (void) printf(gettext("opening /dev/%s\n"), PPP_TUN_NAME);
2400Sstevel@tonic-gate if ((muxfd = open("/dev/" PPP_TUN_NAME, O_RDWR)) < 0) {
2410Sstevel@tonic-gate perror("/dev/" PPP_TUN_NAME);
2420Sstevel@tonic-gate return (1);
2430Sstevel@tonic-gate }
2440Sstevel@tonic-gate
2450Sstevel@tonic-gate /* Push sppptun module on top of lower driver. */
2460Sstevel@tonic-gate if (verbose)
2470Sstevel@tonic-gate (void) printf(gettext("pushing %s on %s\n"), PPP_TUN_NAME,
2486631Sss150715 linkname);
2490Sstevel@tonic-gate if (ioctl(devfd, I_PUSH, PPP_TUN_NAME) == -1) {
2500Sstevel@tonic-gate perror("I_PUSH " PPP_TUN_NAME);
2510Sstevel@tonic-gate return (1);
2520Sstevel@tonic-gate }
2530Sstevel@tonic-gate
254*9751Sjames.d.carlson@sun.com /* Convert stream name to protocol-specific name. */
255*9751Sjames.d.carlson@sun.com if (snprintf(pti.pti_name, sizeof (pti.pti_name), "%s:%s",
256*9751Sjames.d.carlson@sun.com adata.appstr, prot->name) >= sizeof (pti.pti_name)) {
257*9751Sjames.d.carlson@sun.com (void) fprintf(stderr,
258*9751Sjames.d.carlson@sun.com gettext("%s: stream name too long: %s:%s\n"),
259*9751Sjames.d.carlson@sun.com myname, adata.appstr, prot->name);
2600Sstevel@tonic-gate return (1);
261*9751Sjames.d.carlson@sun.com }
2620Sstevel@tonic-gate
2630Sstevel@tonic-gate /* Change the lower stream name. */
2640Sstevel@tonic-gate if (verbose)
2650Sstevel@tonic-gate (void) printf(gettext("resetting interface name to %s\n"),
2660Sstevel@tonic-gate pti.pti_name);
2670Sstevel@tonic-gate if (strioctl(devfd, PPPTUN_SNAME, pti.pti_name,
2680Sstevel@tonic-gate sizeof (pti.pti_name), 0, "PPPTUN_SNAME") < 0) {
2690Sstevel@tonic-gate if (errno == EEXIST)
2700Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: %s already "
2710Sstevel@tonic-gate "installed\n"), myname, pti.pti_name);
2720Sstevel@tonic-gate return (1);
2730Sstevel@tonic-gate }
2740Sstevel@tonic-gate
2750Sstevel@tonic-gate /*
2760Sstevel@tonic-gate * Send down the local interface address to the lower stream
2770Sstevel@tonic-gate * so that it can originate packets.
2780Sstevel@tonic-gate */
2790Sstevel@tonic-gate if (verbose)
2800Sstevel@tonic-gate (void) printf(gettext("send down local address\n"));
2810Sstevel@tonic-gate if (strioctl(devfd, PPPTUN_LCLADDR, &adata.localaddr, adata.locallen,
2820Sstevel@tonic-gate 0, "PPPTUN_LCLADDR") < 0)
2830Sstevel@tonic-gate return (1);
2840Sstevel@tonic-gate
285*9751Sjames.d.carlson@sun.com /*
286*9751Sjames.d.carlson@sun.com * And set the SAP value.
287*9751Sjames.d.carlson@sun.com */
288*9751Sjames.d.carlson@sun.com if (verbose)
289*9751Sjames.d.carlson@sun.com (void) printf(gettext("send down SAP %x\n"), adata.sap);
290*9751Sjames.d.carlson@sun.com if (strioctl(devfd, PPPTUN_SSAP, &adata.sap, sizeof (adata.sap), 0,
291*9751Sjames.d.carlson@sun.com "PPPTUN_SSAP") < 0)
292*9751Sjames.d.carlson@sun.com return (1);
293*9751Sjames.d.carlson@sun.com
2940Sstevel@tonic-gate /* Link the lower stream under the tunnel device. */
2950Sstevel@tonic-gate if (verbose)
2960Sstevel@tonic-gate (void) printf(gettext("doing I_PLINK\n"));
2970Sstevel@tonic-gate if ((muxid = ioctl(muxfd, I_PLINK, devfd)) == -1) {
2980Sstevel@tonic-gate perror("I_PLINK");
2990Sstevel@tonic-gate return (1);
3000Sstevel@tonic-gate }
3010Sstevel@tonic-gate
3020Sstevel@tonic-gate /*
3030Sstevel@tonic-gate * Give the tunnel driver the multiplex ID of the new lower
3040Sstevel@tonic-gate * stream. This allows the unplumb function to find and
3050Sstevel@tonic-gate * disconnect the lower stream.
3060Sstevel@tonic-gate */
3070Sstevel@tonic-gate if (verbose)
3080Sstevel@tonic-gate (void) printf(gettext("sending muxid %d and style %d to "
3090Sstevel@tonic-gate "driver\n"), muxid, prot->style);
3100Sstevel@tonic-gate pti.pti_muxid = muxid;
3110Sstevel@tonic-gate pti.pti_style = prot->style;
3120Sstevel@tonic-gate if (strioctl(muxfd, PPPTUN_SINFO, &pti, sizeof (pti), 0,
3130Sstevel@tonic-gate "PPPTUN_SINFO") < 0)
3140Sstevel@tonic-gate return (1);
3150Sstevel@tonic-gate
3160Sstevel@tonic-gate if (verbose)
3170Sstevel@tonic-gate (void) printf(gettext("done; installed %s\n"), pti.pti_name);
3180Sstevel@tonic-gate else
3190Sstevel@tonic-gate (void) puts(pti.pti_name);
3200Sstevel@tonic-gate
3210Sstevel@tonic-gate return (0);
3220Sstevel@tonic-gate }
3230Sstevel@tonic-gate
3240Sstevel@tonic-gate /*
3250Sstevel@tonic-gate * Handle user request to unplumb an existing lower stream from the
3260Sstevel@tonic-gate * sppptun driver.
3270Sstevel@tonic-gate */
3280Sstevel@tonic-gate static int
unplumb_it(int argc,char ** argv)3290Sstevel@tonic-gate unplumb_it(int argc, char **argv)
3300Sstevel@tonic-gate {
3310Sstevel@tonic-gate char *ifname;
3320Sstevel@tonic-gate int muxfd;
3330Sstevel@tonic-gate struct ppptun_info pti;
3340Sstevel@tonic-gate
3350Sstevel@tonic-gate /*
3360Sstevel@tonic-gate * Need to have the name of the lower stream on the command
3370Sstevel@tonic-gate * line.
3380Sstevel@tonic-gate */
3390Sstevel@tonic-gate if (optind != argc-1)
3400Sstevel@tonic-gate usage();
3410Sstevel@tonic-gate
3420Sstevel@tonic-gate ifname = argv[optind];
3430Sstevel@tonic-gate
3440Sstevel@tonic-gate /* Open the tunnel driver. */
3450Sstevel@tonic-gate if (verbose)
3460Sstevel@tonic-gate (void) printf(gettext("opening /dev/%s\n"), PPP_TUN_NAME);
3470Sstevel@tonic-gate if ((muxfd = open("/dev/" PPP_TUN_NAME, O_RDWR)) < 0) {
3480Sstevel@tonic-gate perror("/dev/" PPP_TUN_NAME);
3490Sstevel@tonic-gate return (1);
3500Sstevel@tonic-gate }
3510Sstevel@tonic-gate
3520Sstevel@tonic-gate /* Get lower stream information; including multiplex ID. */
3530Sstevel@tonic-gate if (verbose)
3540Sstevel@tonic-gate (void) printf(gettext("getting info from driver\n"));
3550Sstevel@tonic-gate (void) strncpy(pti.pti_name, ifname, sizeof (pti.pti_name));
3560Sstevel@tonic-gate if (strioctl(muxfd, PPPTUN_GINFO, &pti, sizeof (pti),
3570Sstevel@tonic-gate sizeof (pti), "PPPTUN_GINFO") < 0)
3580Sstevel@tonic-gate return (1);
3590Sstevel@tonic-gate if (verbose)
3600Sstevel@tonic-gate (void) printf(gettext("got muxid %d from driver\n"),
3610Sstevel@tonic-gate pti.pti_muxid);
3620Sstevel@tonic-gate
3630Sstevel@tonic-gate /* Unlink lower stream from driver. */
3640Sstevel@tonic-gate if (verbose)
3650Sstevel@tonic-gate (void) printf(gettext("doing I_PUNLINK\n"));
3660Sstevel@tonic-gate if (ioctl(muxfd, I_PUNLINK, pti.pti_muxid) < 0) {
3670Sstevel@tonic-gate perror("I_PUNLINK");
3680Sstevel@tonic-gate return (1);
3690Sstevel@tonic-gate }
3700Sstevel@tonic-gate if (verbose)
3710Sstevel@tonic-gate (void) printf(gettext("done!\n"));
3720Sstevel@tonic-gate
3730Sstevel@tonic-gate return (0);
3740Sstevel@tonic-gate }
3750Sstevel@tonic-gate
3760Sstevel@tonic-gate /*
3770Sstevel@tonic-gate * Handle user request to list lower streams plumbed under the sppptun
3780Sstevel@tonic-gate * driver.
3790Sstevel@tonic-gate */
3800Sstevel@tonic-gate /*ARGSUSED*/
3810Sstevel@tonic-gate static int
query_interfaces(int argc,char ** argv)3820Sstevel@tonic-gate query_interfaces(int argc, char **argv)
3830Sstevel@tonic-gate {
3840Sstevel@tonic-gate int muxfd, i;
3850Sstevel@tonic-gate union ppptun_name ptn;
3860Sstevel@tonic-gate
3870Sstevel@tonic-gate /* No other arguments permitted. */
3880Sstevel@tonic-gate if (optind != argc)
3890Sstevel@tonic-gate usage();
3900Sstevel@tonic-gate
3910Sstevel@tonic-gate /* Open the tunnel driver. */
3920Sstevel@tonic-gate if (verbose)
3930Sstevel@tonic-gate (void) printf(gettext("opening /dev/%s\n"), PPP_TUN_NAME);
3940Sstevel@tonic-gate if ((muxfd = open("/dev/" PPP_TUN_NAME, O_RDWR)) < 0) {
3950Sstevel@tonic-gate perror("/dev/" PPP_TUN_NAME);
3960Sstevel@tonic-gate return (1);
3970Sstevel@tonic-gate }
3980Sstevel@tonic-gate
3990Sstevel@tonic-gate /* Read and print names of lower streams. */
4000Sstevel@tonic-gate for (i = 0; ; i++) {
4010Sstevel@tonic-gate ptn.ptn_index = i;
4020Sstevel@tonic-gate if (strioctl(muxfd, PPPTUN_GNNAME, &ptn, sizeof (ptn),
4030Sstevel@tonic-gate sizeof (ptn), "PPPTUN_GNNAME") < 0) {
4040Sstevel@tonic-gate perror("PPPTUN_GNNAME");
4050Sstevel@tonic-gate break;
4060Sstevel@tonic-gate }
4070Sstevel@tonic-gate /* Stop when we index off the end of the list. */
4080Sstevel@tonic-gate if (ptn.ptn_name[0] == '\0')
4090Sstevel@tonic-gate break;
4100Sstevel@tonic-gate (void) puts(ptn.ptn_name);
4110Sstevel@tonic-gate }
4120Sstevel@tonic-gate return (0);
4130Sstevel@tonic-gate }
4140Sstevel@tonic-gate
4150Sstevel@tonic-gate /*
4160Sstevel@tonic-gate * Invoked by SIGALRM -- timer prevents problems in driver from
4170Sstevel@tonic-gate * hanging the utility.
4180Sstevel@tonic-gate */
4190Sstevel@tonic-gate /*ARGSUSED*/
4200Sstevel@tonic-gate static void
toolong(int dummy)4210Sstevel@tonic-gate toolong(int dummy)
4220Sstevel@tonic-gate {
4230Sstevel@tonic-gate (void) fprintf(stderr, gettext("%s: time-out in driver\n"), myname);
4240Sstevel@tonic-gate exit(1);
4250Sstevel@tonic-gate }
4260Sstevel@tonic-gate
4270Sstevel@tonic-gate int
main(int argc,char ** argv)4280Sstevel@tonic-gate main(int argc, char **argv)
4290Sstevel@tonic-gate {
4300Sstevel@tonic-gate int opt, errflag = 0;
4310Sstevel@tonic-gate char *arg;
4320Sstevel@tonic-gate
4330Sstevel@tonic-gate myname = *argv;
4340Sstevel@tonic-gate
4350Sstevel@tonic-gate
4360Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
4370Sstevel@tonic-gate
4380Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
4390Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST"
4400Sstevel@tonic-gate #endif
4410Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN);
4420Sstevel@tonic-gate
4430Sstevel@tonic-gate /* Parse command line flags */
4440Sstevel@tonic-gate while ((opt = getopt(argc, argv, "v")) != EOF)
4450Sstevel@tonic-gate switch (opt) {
4460Sstevel@tonic-gate case 'v':
4470Sstevel@tonic-gate verbose++;
4480Sstevel@tonic-gate break;
4490Sstevel@tonic-gate default:
4500Sstevel@tonic-gate errflag++;
4510Sstevel@tonic-gate break;
4520Sstevel@tonic-gate }
4530Sstevel@tonic-gate if (errflag != 0 || optind >= argc)
4540Sstevel@tonic-gate usage();
4550Sstevel@tonic-gate
4560Sstevel@tonic-gate /* Set alarm to avoid stalling on any driver errors. */
4570Sstevel@tonic-gate (void) signal(SIGALRM, toolong);
4580Sstevel@tonic-gate (void) alarm(2);
4590Sstevel@tonic-gate
4600Sstevel@tonic-gate /* Switch out based on user-requested function. */
4610Sstevel@tonic-gate arg = argv[optind++];
4620Sstevel@tonic-gate if (strcmp(arg, "plumb") == 0)
4630Sstevel@tonic-gate return (plumb_it(argc, argv));
4640Sstevel@tonic-gate if (strcmp(arg, "unplumb") == 0)
4650Sstevel@tonic-gate return (unplumb_it(argc, argv));
4660Sstevel@tonic-gate if (strcmp(arg, "query") == 0)
4670Sstevel@tonic-gate return (query_interfaces(argc, argv));
4680Sstevel@tonic-gate
4690Sstevel@tonic-gate usage();
4700Sstevel@tonic-gate return (1);
4710Sstevel@tonic-gate }
472