18483Sjames.d.carlson@sun.com /*
28483Sjames.d.carlson@sun.com * CDDL HEADER START
38483Sjames.d.carlson@sun.com *
48483Sjames.d.carlson@sun.com * The contents of this file are subject to the terms of the
58483Sjames.d.carlson@sun.com * Common Development and Distribution License (the "License").
68483Sjames.d.carlson@sun.com * You may not use this file except in compliance with the License.
78483Sjames.d.carlson@sun.com *
88483Sjames.d.carlson@sun.com * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
98483Sjames.d.carlson@sun.com * or http://www.opensolaris.org/os/licensing.
108483Sjames.d.carlson@sun.com * See the License for the specific language governing permissions
118483Sjames.d.carlson@sun.com * and limitations under the License.
128483Sjames.d.carlson@sun.com *
138483Sjames.d.carlson@sun.com * When distributing Covered Code, include this CDDL HEADER in each
148483Sjames.d.carlson@sun.com * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
158483Sjames.d.carlson@sun.com * If applicable, add the following below this CDDL HEADER, with the
168483Sjames.d.carlson@sun.com * fields enclosed by brackets "[]" replaced with your own identifying
178483Sjames.d.carlson@sun.com * information: Portions Copyright [yyyy] [name of copyright owner]
188483Sjames.d.carlson@sun.com *
198483Sjames.d.carlson@sun.com * CDDL HEADER END
208483Sjames.d.carlson@sun.com */
218483Sjames.d.carlson@sun.com
228483Sjames.d.carlson@sun.com /*
23*11415SSurya.Prakki@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
248483Sjames.d.carlson@sun.com * Use is subject to license terms.
258483Sjames.d.carlson@sun.com */
268483Sjames.d.carlson@sun.com
270Sstevel@tonic-gate /*
280Sstevel@tonic-gate * pppoe.c - pppd plugin to handle PPPoE operation.
290Sstevel@tonic-gate */
300Sstevel@tonic-gate
310Sstevel@tonic-gate #include <unistd.h>
320Sstevel@tonic-gate #include <stddef.h>
330Sstevel@tonic-gate #include <stdlib.h>
340Sstevel@tonic-gate #include <errno.h>
350Sstevel@tonic-gate #include <sys/types.h>
360Sstevel@tonic-gate #include <fcntl.h>
370Sstevel@tonic-gate #include <strings.h>
380Sstevel@tonic-gate #include <sys/stropts.h>
390Sstevel@tonic-gate #include <netinet/in.h>
400Sstevel@tonic-gate #include <net/pppio.h>
410Sstevel@tonic-gate #include <net/sppptun.h>
420Sstevel@tonic-gate #include <net/pppoe.h>
430Sstevel@tonic-gate
440Sstevel@tonic-gate #include "pppd.h"
450Sstevel@tonic-gate #include "pathnames.h"
460Sstevel@tonic-gate
470Sstevel@tonic-gate /* Saved hook pointers */
480Sstevel@tonic-gate static int (*old_check_options)(uid_t uid);
490Sstevel@tonic-gate static int (*old_updown_script)(const char ***argsp);
500Sstevel@tonic-gate static int (*old_sys_read_packet)(int retv, struct strbuf *ctrl,
510Sstevel@tonic-gate struct strbuf *data, int flags);
520Sstevel@tonic-gate
530Sstevel@tonic-gate /* Room for 3 IPv4 addresses and metric */
540Sstevel@tonic-gate #define RTE_MSG_LEN (3*16 + 10 + 1)
550Sstevel@tonic-gate
560Sstevel@tonic-gate /* Environment string for routes */
570Sstevel@tonic-gate #define RTE_STR "ROUTE_%d"
580Sstevel@tonic-gate
590Sstevel@tonic-gate /*
600Sstevel@tonic-gate * strioctl()
610Sstevel@tonic-gate *
620Sstevel@tonic-gate * wrapper for STREAMS I_STR ioctl.
630Sstevel@tonic-gate */
640Sstevel@tonic-gate static int
strioctl(int fd,int cmd,void * ptr,int ilen,int olen)650Sstevel@tonic-gate strioctl(int fd, int cmd, void *ptr, int ilen, int olen)
660Sstevel@tonic-gate {
670Sstevel@tonic-gate struct strioctl str;
680Sstevel@tonic-gate
690Sstevel@tonic-gate str.ic_cmd = cmd;
700Sstevel@tonic-gate str.ic_timout = 0; /* Use default timer; 15 seconds */
710Sstevel@tonic-gate str.ic_len = ilen;
720Sstevel@tonic-gate str.ic_dp = ptr;
730Sstevel@tonic-gate
740Sstevel@tonic-gate if (ioctl(fd, I_STR, &str) == -1) {
750Sstevel@tonic-gate return (-1);
760Sstevel@tonic-gate }
770Sstevel@tonic-gate if (str.ic_len != olen) {
780Sstevel@tonic-gate return (-1);
790Sstevel@tonic-gate }
800Sstevel@tonic-gate return (0);
810Sstevel@tonic-gate }
820Sstevel@tonic-gate
830Sstevel@tonic-gate /*
840Sstevel@tonic-gate * If the user named the tunneling device, check that it is
850Sstevel@tonic-gate * reasonable; otherwise check that standard input is the tunnel.
860Sstevel@tonic-gate */
870Sstevel@tonic-gate static int
pppoe_check_options(uid_t uid)880Sstevel@tonic-gate pppoe_check_options(uid_t uid)
890Sstevel@tonic-gate {
900Sstevel@tonic-gate int tstfd; /* fd for device being checked */
910Sstevel@tonic-gate int err; /* saved errno value */
920Sstevel@tonic-gate int retv; /* return value */
930Sstevel@tonic-gate int intv; /* integer return value (from ioctl) */
940Sstevel@tonic-gate union ppptun_name ptn;
950Sstevel@tonic-gate
960Sstevel@tonic-gate if (devnam[0] != '\0') {
970Sstevel@tonic-gate /*
980Sstevel@tonic-gate * Open as real user so that modes on device can be
990Sstevel@tonic-gate * used to limit access.
1000Sstevel@tonic-gate */
1010Sstevel@tonic-gate if (!devnam_info.priv)
1020Sstevel@tonic-gate (void) seteuid(uid);
1030Sstevel@tonic-gate tstfd = open(devnam, O_NONBLOCK | O_RDWR, 0);
1040Sstevel@tonic-gate err = errno;
1050Sstevel@tonic-gate if (!devnam_info.priv)
1060Sstevel@tonic-gate (void) seteuid(0);
1070Sstevel@tonic-gate if (tstfd == -1) {
1080Sstevel@tonic-gate errno = err;
1090Sstevel@tonic-gate option_error("unable to open %s: %m", devnam);
1100Sstevel@tonic-gate return (-1);
1110Sstevel@tonic-gate }
1120Sstevel@tonic-gate retv = strioctl(tstfd, PPPTUN_GDATA, &ptn, 0, sizeof (ptn));
1130Sstevel@tonic-gate (void) close(tstfd);
1140Sstevel@tonic-gate if (retv == -1) {
1150Sstevel@tonic-gate option_error("device %s is not a PPP tunneling device",
1160Sstevel@tonic-gate devnam);
1170Sstevel@tonic-gate return (-1);
1180Sstevel@tonic-gate }
1190Sstevel@tonic-gate } else {
1200Sstevel@tonic-gate retv = strioctl(0, PPPIO_GTYPE, &intv, 0, sizeof (intv));
1210Sstevel@tonic-gate if (retv == -1) {
1220Sstevel@tonic-gate option_error("standard input is not a PPP device");
1230Sstevel@tonic-gate return (-1);
1240Sstevel@tonic-gate }
1250Sstevel@tonic-gate retv = strioctl(0, PPPTUN_GDATA, &ptn, 0, sizeof (ptn));
1260Sstevel@tonic-gate if (retv == -1) {
1270Sstevel@tonic-gate option_error("standard input is not a PPP tunnel");
1280Sstevel@tonic-gate return (-1);
1290Sstevel@tonic-gate }
1300Sstevel@tonic-gate if (strcmp(ptn.ptn_name + strlen(ptn.ptn_name) - 6,
1310Sstevel@tonic-gate ":pppoe") != 0) {
1320Sstevel@tonic-gate option_error("standard input not connected to PPPoE");
1330Sstevel@tonic-gate return (-1);
1340Sstevel@tonic-gate }
1350Sstevel@tonic-gate }
1360Sstevel@tonic-gate if (old_check_options != NULL &&
1370Sstevel@tonic-gate old_check_options != pppoe_check_options)
1380Sstevel@tonic-gate return ((*old_check_options)(uid));
1390Sstevel@tonic-gate return (0);
1400Sstevel@tonic-gate }
1410Sstevel@tonic-gate
1420Sstevel@tonic-gate /*
1430Sstevel@tonic-gate * When we're about to call one of the up or down scripts, change the
1440Sstevel@tonic-gate * second argument to contain the interface name and selected PPPoE
1450Sstevel@tonic-gate * service.
1460Sstevel@tonic-gate */
1470Sstevel@tonic-gate static int
pppoe_updown_script(const char *** argsp)1480Sstevel@tonic-gate pppoe_updown_script(const char ***argsp)
1490Sstevel@tonic-gate {
1500Sstevel@tonic-gate const char *cp;
1510Sstevel@tonic-gate
1520Sstevel@tonic-gate if ((*argsp)[2] == devnam &&
1530Sstevel@tonic-gate (cp = script_getenv("IF_AND_SERVICE")) != NULL)
1540Sstevel@tonic-gate (*argsp)[2] = cp;
1550Sstevel@tonic-gate if (old_updown_script != NULL &&
1560Sstevel@tonic-gate old_updown_script != pppoe_updown_script)
1570Sstevel@tonic-gate return ((*old_updown_script)(argsp));
1580Sstevel@tonic-gate return (0);
1590Sstevel@tonic-gate }
1600Sstevel@tonic-gate
1610Sstevel@tonic-gate /*
1620Sstevel@tonic-gate * Concatenate and save strings from command line into environment
1630Sstevel@tonic-gate * variable.
1640Sstevel@tonic-gate */
1650Sstevel@tonic-gate static void
cat_save_env(char ** argv,char idchar,const char * envname)1660Sstevel@tonic-gate cat_save_env(char **argv, char idchar, const char *envname)
1670Sstevel@tonic-gate {
1680Sstevel@tonic-gate char **argp;
1690Sstevel@tonic-gate int totlen;
1700Sstevel@tonic-gate char *str;
1710Sstevel@tonic-gate char *cp;
1720Sstevel@tonic-gate
1730Sstevel@tonic-gate totlen = 0;
1740Sstevel@tonic-gate for (argp = argv; argp[0] != NULL; argp += 2)
1750Sstevel@tonic-gate if (*argp[0] == idchar)
1760Sstevel@tonic-gate totlen += strlen(argp[1]) + 1;
1770Sstevel@tonic-gate if ((str = malloc(totlen + 1)) == NULL) {
1780Sstevel@tonic-gate error("cannot malloc PPPoE environment for %s", envname);
1790Sstevel@tonic-gate return;
1800Sstevel@tonic-gate }
1810Sstevel@tonic-gate cp = str;
1820Sstevel@tonic-gate for (argp = argv; argp[0] != NULL; argp += 2)
1830Sstevel@tonic-gate if (*argp[0] == idchar) {
1840Sstevel@tonic-gate (void) strcpy(cp, argp[1]);
1850Sstevel@tonic-gate cp += strlen(cp);
1860Sstevel@tonic-gate *cp++ = '\n';
1870Sstevel@tonic-gate }
1880Sstevel@tonic-gate *cp = '\0';
1890Sstevel@tonic-gate script_setenv(envname, str, 0);
1900Sstevel@tonic-gate }
1910Sstevel@tonic-gate
1920Sstevel@tonic-gate /*
1930Sstevel@tonic-gate * Convert Message Of The Moment (MOTM) and Host Uniform Resource
1940Sstevel@tonic-gate * Locator (HURL) strings into environment variables and command-line
1950Sstevel@tonic-gate * arguments for script.
1960Sstevel@tonic-gate */
1970Sstevel@tonic-gate static void
handle_motm_hurl(char ** argv,int argc,const uint8_t * tagp,int pktlen)1980Sstevel@tonic-gate handle_motm_hurl(char **argv, int argc, const uint8_t *tagp, int pktlen)
1990Sstevel@tonic-gate {
2000Sstevel@tonic-gate int ttype;
2010Sstevel@tonic-gate int tlen;
2020Sstevel@tonic-gate char *str;
2030Sstevel@tonic-gate char **oargv = argv;
2040Sstevel@tonic-gate
2050Sstevel@tonic-gate /* Must have room for two strings and NULL terminator. */
2060Sstevel@tonic-gate while (argc >= 3) {
2070Sstevel@tonic-gate str = NULL;
2080Sstevel@tonic-gate while (pktlen >= POET_HDRLEN) {
2090Sstevel@tonic-gate ttype = POET_GET_TYPE(tagp);
2100Sstevel@tonic-gate if (ttype == POETT_END)
2110Sstevel@tonic-gate break;
2120Sstevel@tonic-gate tlen = POET_GET_LENG(tagp);
2130Sstevel@tonic-gate if (tlen > pktlen - POET_HDRLEN)
2140Sstevel@tonic-gate break;
2150Sstevel@tonic-gate if (ttype == POETT_HURL || ttype == POETT_MOTM) {
2160Sstevel@tonic-gate if ((str = malloc(tlen + 1)) == NULL) {
2170Sstevel@tonic-gate error("cannot malloc PPPoE message");
2180Sstevel@tonic-gate break;
2190Sstevel@tonic-gate }
2200Sstevel@tonic-gate (void) memcpy(str, POET_DATA(tagp), tlen);
2210Sstevel@tonic-gate str[tlen] = '\0';
2220Sstevel@tonic-gate }
2230Sstevel@tonic-gate pktlen -= POET_HDRLEN + tlen;
2240Sstevel@tonic-gate tagp += POET_HDRLEN + tlen;
2250Sstevel@tonic-gate if (str != NULL)
2260Sstevel@tonic-gate break;
2270Sstevel@tonic-gate }
2280Sstevel@tonic-gate if (str == NULL)
2290Sstevel@tonic-gate break;
2300Sstevel@tonic-gate *argv++ = ttype == POETT_HURL ? "hurl" : "motm";
2310Sstevel@tonic-gate *argv++ = str;
2320Sstevel@tonic-gate argc -= 2;
2330Sstevel@tonic-gate }
2340Sstevel@tonic-gate *argv = NULL;
2350Sstevel@tonic-gate cat_save_env(oargv, 'h', "HURL");
2360Sstevel@tonic-gate cat_save_env(oargv, 'm', "MOTM");
2370Sstevel@tonic-gate }
2380Sstevel@tonic-gate
2390Sstevel@tonic-gate /*
2400Sstevel@tonic-gate * Convert IP Route Add structures into environment variables and
2410Sstevel@tonic-gate * command-line arguments for script.
2420Sstevel@tonic-gate */
2430Sstevel@tonic-gate static void
handle_ip_route_add(char ** argv,int argc,const uint8_t * tagp,int pktlen)2440Sstevel@tonic-gate handle_ip_route_add(char **argv, int argc, const uint8_t *tagp, int pktlen)
2450Sstevel@tonic-gate {
2460Sstevel@tonic-gate int ttype;
2470Sstevel@tonic-gate int tlen;
2480Sstevel@tonic-gate char *str;
2490Sstevel@tonic-gate poer_t poer;
2500Sstevel@tonic-gate int idx;
2510Sstevel@tonic-gate char envname[sizeof (RTE_STR) + 10];
2520Sstevel@tonic-gate
2530Sstevel@tonic-gate idx = 0;
2540Sstevel@tonic-gate
2550Sstevel@tonic-gate /* Must have room for four strings and NULL terminator. */
2560Sstevel@tonic-gate while (argc >= 5) {
2570Sstevel@tonic-gate str = NULL;
2580Sstevel@tonic-gate while (pktlen >= POET_HDRLEN) {
2590Sstevel@tonic-gate ttype = POET_GET_TYPE(tagp);
2600Sstevel@tonic-gate if (ttype == POETT_END)
2610Sstevel@tonic-gate break;
2620Sstevel@tonic-gate tlen = POET_GET_LENG(tagp);
2630Sstevel@tonic-gate if (tlen > pktlen - POET_HDRLEN)
2640Sstevel@tonic-gate break;
2650Sstevel@tonic-gate if (ttype == POETT_RTEADD && tlen >= sizeof (poer) &&
2660Sstevel@tonic-gate (str = malloc(RTE_MSG_LEN)) == NULL) {
2670Sstevel@tonic-gate error("cannot malloc PPPoE route");
2680Sstevel@tonic-gate break;
2690Sstevel@tonic-gate }
2700Sstevel@tonic-gate pktlen -= POET_HDRLEN + tlen;
2710Sstevel@tonic-gate tagp += POET_HDRLEN + tlen;
2720Sstevel@tonic-gate if (str != NULL)
2730Sstevel@tonic-gate break;
2740Sstevel@tonic-gate }
2750Sstevel@tonic-gate if (str == NULL)
2760Sstevel@tonic-gate break;
2770Sstevel@tonic-gate /* No alignment restrictions on source; copy to local. */
2780Sstevel@tonic-gate (void) memcpy(&poer, POET_DATA(tagp), sizeof (poer));
2790Sstevel@tonic-gate (void) slprintf(str, RTE_MSG_LEN, "%I %I %I %d",
2800Sstevel@tonic-gate poer.poer_dest_network, poer.poer_subnet_mask,
2810Sstevel@tonic-gate poer.poer_gateway, (int)poer.poer_metric);
2820Sstevel@tonic-gate /* Save off the environment variable version of this. */
2830Sstevel@tonic-gate (void) slprintf(envname, sizeof (envname), RTE_STR, ++idx);
2840Sstevel@tonic-gate script_setenv(envname, str, 0);
2850Sstevel@tonic-gate *argv++ = str; /* Destination */
2860Sstevel@tonic-gate str = strchr(str, ' ');
2870Sstevel@tonic-gate *str++ = '\0';
2880Sstevel@tonic-gate *argv++ = str; /* Subnet mask */
2890Sstevel@tonic-gate str = strchr(str, ' ');
2900Sstevel@tonic-gate *str++ = '\0';
2910Sstevel@tonic-gate *argv++ = str; /* Gateway */
2920Sstevel@tonic-gate str = strchr(str, ' ');
2930Sstevel@tonic-gate *str++ = '\0';
2940Sstevel@tonic-gate *argv++ = str; /* Metric */
2950Sstevel@tonic-gate argc -= 4;
2960Sstevel@tonic-gate }
2970Sstevel@tonic-gate *argv = NULL;
2980Sstevel@tonic-gate }
2990Sstevel@tonic-gate
3000Sstevel@tonic-gate /*
3010Sstevel@tonic-gate * If we get here, then the driver has already validated the sender,
3020Sstevel@tonic-gate * the PPPoE version, the message length, and session ID. The code
3030Sstevel@tonic-gate * number is known not to be zero.
3040Sstevel@tonic-gate */
3050Sstevel@tonic-gate static int
handle_pppoe_input(const ppptun_atype * pma,struct strbuf * ctrl,struct strbuf * data)3060Sstevel@tonic-gate handle_pppoe_input(const ppptun_atype *pma, struct strbuf *ctrl,
3070Sstevel@tonic-gate struct strbuf *data)
3080Sstevel@tonic-gate {
3090Sstevel@tonic-gate const poep_t *poep;
3100Sstevel@tonic-gate struct ppp_ls *plp;
3110Sstevel@tonic-gate const char *mname;
3120Sstevel@tonic-gate const char *cstr;
3130Sstevel@tonic-gate char *str;
3140Sstevel@tonic-gate char *cp;
3150Sstevel@tonic-gate char *argv[64];
3160Sstevel@tonic-gate pid_t rpid;
3170Sstevel@tonic-gate char **argp;
3180Sstevel@tonic-gate int idx;
3190Sstevel@tonic-gate char envname[sizeof (RTE_STR) + 10];
3200Sstevel@tonic-gate const uint8_t *tagp;
3210Sstevel@tonic-gate int pktlen;
3220Sstevel@tonic-gate
3230Sstevel@tonic-gate /*
3240Sstevel@tonic-gate * Warning: the data->buf pointer here is not necessarily properly
3250Sstevel@tonic-gate * aligned for access to the poep_session_id or poep_length members.
3260Sstevel@tonic-gate */
3270Sstevel@tonic-gate /* LINTED: alignment */
3280Sstevel@tonic-gate poep = (const poep_t *)data->buf;
3290Sstevel@tonic-gate tagp = (const uint8_t *)poep + offsetof(poep_t, poep_length);
3300Sstevel@tonic-gate pktlen = (tagp[0] << 8) + tagp[1];
3310Sstevel@tonic-gate tagp = (const uint8_t *)(poep + 1);
3320Sstevel@tonic-gate switch (poep->poep_code) {
3330Sstevel@tonic-gate case POECODE_PADT:
3340Sstevel@tonic-gate dbglog("received PPPoE PADT; connection has been closed");
3350Sstevel@tonic-gate /* LINTED: alignment */
3360Sstevel@tonic-gate plp = (struct ppp_ls *)ctrl->buf;
3370Sstevel@tonic-gate plp->magic = PPPLSMAGIC;
3380Sstevel@tonic-gate plp->ppp_message = PPP_LINKSTAT_HANGUP;
3390Sstevel@tonic-gate ctrl->len = sizeof (*plp);
3400Sstevel@tonic-gate return (0);
3410Sstevel@tonic-gate
3420Sstevel@tonic-gate /* Active Discovery Message and Network extensions */
3430Sstevel@tonic-gate case POECODE_PADM:
3440Sstevel@tonic-gate case POECODE_PADN:
3450Sstevel@tonic-gate if (poep->poep_code == POECODE_PADM) {
3460Sstevel@tonic-gate argv[0] = _ROOT_PATH "/etc/ppp/pppoe-msg";
3470Sstevel@tonic-gate mname = "PADM";
3480Sstevel@tonic-gate handle_motm_hurl(argv + 4, Dim(argv) - 4, tagp, pktlen);
3490Sstevel@tonic-gate } else {
3500Sstevel@tonic-gate argv[0] = _ROOT_PATH "/etc/ppp/pppoe-network";
3510Sstevel@tonic-gate mname = "PADN";
3520Sstevel@tonic-gate handle_ip_route_add(argv + 4, Dim(argv) - 4, tagp,
3530Sstevel@tonic-gate pktlen);
3540Sstevel@tonic-gate }
3550Sstevel@tonic-gate argv[1] = ifname;
3560Sstevel@tonic-gate /* Note: strdup doesn't handle NULL input. */
3570Sstevel@tonic-gate str = NULL;
3580Sstevel@tonic-gate if ((cstr = script_getenv("IF_AND_SERVICE")) == NULL ||
3590Sstevel@tonic-gate (str = strdup(cstr)) == NULL) {
3600Sstevel@tonic-gate argv[2] = argv[3] = "";
3610Sstevel@tonic-gate } else {
3620Sstevel@tonic-gate if ((cp = strrchr(str, ':')) == NULL)
3630Sstevel@tonic-gate cp = str + strlen(str);
3640Sstevel@tonic-gate else
3650Sstevel@tonic-gate *cp++ = '\0';
3660Sstevel@tonic-gate argv[2] = str;
3670Sstevel@tonic-gate argv[3] = cp;
3680Sstevel@tonic-gate }
3690Sstevel@tonic-gate rpid = run_program(argv[0], argv, 0, NULL, NULL);
3700Sstevel@tonic-gate if (rpid == (pid_t)0)
3710Sstevel@tonic-gate dbglog("ignored PPPoE %s; no %s script", mname,
3720Sstevel@tonic-gate argv[0]);
3730Sstevel@tonic-gate else if (rpid != (pid_t)-1)
3740Sstevel@tonic-gate dbglog("PPPoE %s: started PID %d", mname, rpid);
3750Sstevel@tonic-gate if (str != NULL)
3760Sstevel@tonic-gate free(str);
3770Sstevel@tonic-gate /* Free storage allocated by handle_{motm_hurl,ip_route_add} */
3780Sstevel@tonic-gate idx = 0;
3790Sstevel@tonic-gate for (argp = argv + 4; *argp != NULL; ) {
3800Sstevel@tonic-gate if (poep->poep_code == POECODE_PADM) {
3810Sstevel@tonic-gate free(argp[1]);
3820Sstevel@tonic-gate argp += 2;
3830Sstevel@tonic-gate } else {
3840Sstevel@tonic-gate free(argp[0]);
3850Sstevel@tonic-gate argp += 4;
3860Sstevel@tonic-gate (void) slprintf(envname, sizeof (envname),
3870Sstevel@tonic-gate RTE_STR, ++idx);
3880Sstevel@tonic-gate script_unsetenv(envname);
3890Sstevel@tonic-gate }
3900Sstevel@tonic-gate }
3910Sstevel@tonic-gate if (poep->poep_code == POECODE_PADM) {
3920Sstevel@tonic-gate script_unsetenv("HURL");
3930Sstevel@tonic-gate script_unsetenv("MOTM");
3940Sstevel@tonic-gate }
3950Sstevel@tonic-gate break;
3960Sstevel@tonic-gate
3970Sstevel@tonic-gate default:
3980Sstevel@tonic-gate warn("unexpected PPPoE code %d from %s", poep->poep_code,
3990Sstevel@tonic-gate ether_ntoa(&pma->pta_pppoe.ptma_mac_ether_addr));
4000Sstevel@tonic-gate break;
4010Sstevel@tonic-gate }
4020Sstevel@tonic-gate return (-1);
4030Sstevel@tonic-gate }
4040Sstevel@tonic-gate
4050Sstevel@tonic-gate /*
4069751Sjames.d.carlson@sun.com * Handle an action code passed up from the driver.
4079751Sjames.d.carlson@sun.com */
4089751Sjames.d.carlson@sun.com static int
handle_action(struct ppptun_control * ptc,struct strbuf * ctrl,struct strbuf * data)4099751Sjames.d.carlson@sun.com handle_action(struct ppptun_control *ptc, struct strbuf *ctrl,
4109751Sjames.d.carlson@sun.com struct strbuf *data)
4119751Sjames.d.carlson@sun.com {
4129751Sjames.d.carlson@sun.com switch (ptc->ptc_action) {
4139751Sjames.d.carlson@sun.com case PTCA_CONTROL:
4149751Sjames.d.carlson@sun.com return (handle_pppoe_input(&ptc->ptc_address, ctrl, data));
4159751Sjames.d.carlson@sun.com
4169751Sjames.d.carlson@sun.com case PTCA_BADCTRL:
4179751Sjames.d.carlson@sun.com warn("bad control message; session %u on %s", ptc->ptc_rsessid,
4189751Sjames.d.carlson@sun.com ptc->ptc_name);
4199751Sjames.d.carlson@sun.com return (0);
4209751Sjames.d.carlson@sun.com }
4219751Sjames.d.carlson@sun.com
4229751Sjames.d.carlson@sun.com return (-1);
4239751Sjames.d.carlson@sun.com }
4249751Sjames.d.carlson@sun.com
4259751Sjames.d.carlson@sun.com /*
4260Sstevel@tonic-gate * sys-solaris has just read in a packet; grovel through it and see if
4270Sstevel@tonic-gate * it's something we need to handle ourselves.
4280Sstevel@tonic-gate */
4290Sstevel@tonic-gate static int
pppoe_sys_read_packet(int retv,struct strbuf * ctrl,struct strbuf * data,int flags)4300Sstevel@tonic-gate pppoe_sys_read_packet(int retv, struct strbuf *ctrl, struct strbuf *data,
4310Sstevel@tonic-gate int flags)
4320Sstevel@tonic-gate {
4330Sstevel@tonic-gate struct ppptun_control *ptc;
4340Sstevel@tonic-gate
4350Sstevel@tonic-gate if (retv >= 0 && !(retv & MORECTL) && ctrl->len >= sizeof (uint32_t)) {
4360Sstevel@tonic-gate /* LINTED: alignment */
4370Sstevel@tonic-gate ptc = (struct ppptun_control *)ctrl->buf;
4380Sstevel@tonic-gate /* ptc_discrim is the first uint32_t of the structure. */
4390Sstevel@tonic-gate if (ptc->ptc_discrim == PPPOE_DISCRIM) {
4400Sstevel@tonic-gate retv = -1;
4419751Sjames.d.carlson@sun.com if (ctrl->len == sizeof (*ptc))
4429751Sjames.d.carlson@sun.com retv = handle_action(ptc, ctrl, data);
4430Sstevel@tonic-gate if (retv < 0)
4440Sstevel@tonic-gate errno = EAGAIN;
4450Sstevel@tonic-gate return (retv);
4460Sstevel@tonic-gate }
4470Sstevel@tonic-gate }
4480Sstevel@tonic-gate /* Forward along to other plug-ins */
4490Sstevel@tonic-gate if (old_sys_read_packet != NULL &&
4500Sstevel@tonic-gate old_sys_read_packet != pppoe_sys_read_packet)
4510Sstevel@tonic-gate return ((*old_sys_read_packet)(retv, ctrl, data, flags));
4520Sstevel@tonic-gate return (retv);
4530Sstevel@tonic-gate }
4540Sstevel@tonic-gate
4550Sstevel@tonic-gate /*
4560Sstevel@tonic-gate * Get an environment variable from the chat script.
4570Sstevel@tonic-gate */
4580Sstevel@tonic-gate static int
saveenv(FILE * fd,const char * envname)4590Sstevel@tonic-gate saveenv(FILE *fd, const char *envname)
4600Sstevel@tonic-gate {
4610Sstevel@tonic-gate char envstr[1024];
4620Sstevel@tonic-gate int len;
4630Sstevel@tonic-gate
4640Sstevel@tonic-gate if (fgets(envstr, sizeof (envstr), fd) == NULL)
4650Sstevel@tonic-gate return (-1);
4660Sstevel@tonic-gate len = strlen(envstr);
4670Sstevel@tonic-gate if (len <= 1)
4680Sstevel@tonic-gate return (0);
4690Sstevel@tonic-gate envstr[len-1] = '\0';
4700Sstevel@tonic-gate script_setenv(envname, envstr, 0);
4710Sstevel@tonic-gate return (1);
4720Sstevel@tonic-gate }
4730Sstevel@tonic-gate
4740Sstevel@tonic-gate /*
4750Sstevel@tonic-gate * Read environment variables exported by chat script.
4760Sstevel@tonic-gate */
4770Sstevel@tonic-gate static void
pppoe_device_pipe(int pipefd)4780Sstevel@tonic-gate pppoe_device_pipe(int pipefd)
4790Sstevel@tonic-gate {
4800Sstevel@tonic-gate FILE *fd;
4810Sstevel@tonic-gate int i;
4820Sstevel@tonic-gate char envname[32];
4830Sstevel@tonic-gate
4840Sstevel@tonic-gate fd = fdopen(pipefd, "r");
4850Sstevel@tonic-gate if (fd == NULL)
4860Sstevel@tonic-gate fatal("unable to open environment file: %m");
4870Sstevel@tonic-gate (void) saveenv(fd, "IF_AND_SERVICE");
4880Sstevel@tonic-gate (void) saveenv(fd, "SERVICE_NAME");
4890Sstevel@tonic-gate (void) saveenv(fd, "AC_NAME");
4900Sstevel@tonic-gate (void) saveenv(fd, "AC_MAC");
4910Sstevel@tonic-gate (void) saveenv(fd, "SESSION_ID");
4920Sstevel@tonic-gate for (i = 1; ; i++) {
493*11415SSurya.Prakki@Sun.COM (void) slprintf(envname, sizeof (envname),
494*11415SSurya.Prakki@Sun.COM "VENDOR_SPECIFIC_%d", i);
4950Sstevel@tonic-gate if (saveenv(fd, envname) <= 0)
4960Sstevel@tonic-gate break;
4970Sstevel@tonic-gate }
4980Sstevel@tonic-gate (void) fclose(fd);
4990Sstevel@tonic-gate }
5000Sstevel@tonic-gate
5010Sstevel@tonic-gate void
plugin_init(void)5020Sstevel@tonic-gate plugin_init(void)
5030Sstevel@tonic-gate {
5040Sstevel@tonic-gate if (absmax_mtu > 1492)
5050Sstevel@tonic-gate absmax_mtu = 1492;
5060Sstevel@tonic-gate if (absmax_mru > 1492)
5070Sstevel@tonic-gate absmax_mru = 1492;
5080Sstevel@tonic-gate old_check_options = check_options_hook;
5090Sstevel@tonic-gate check_options_hook = pppoe_check_options;
5100Sstevel@tonic-gate old_updown_script = updown_script_hook;
5110Sstevel@tonic-gate updown_script_hook = pppoe_updown_script;
5120Sstevel@tonic-gate old_sys_read_packet = sys_read_packet_hook;
5130Sstevel@tonic-gate sys_read_packet_hook = pppoe_sys_read_packet;
5140Sstevel@tonic-gate device_pipe_hook = pppoe_device_pipe;
5150Sstevel@tonic-gate already_ppp = 1;
5160Sstevel@tonic-gate }
517