17c478bd9Sstevel@tonic-gate /* 2*dc632b73SJames Carlson * CDDL HEADER START 3*dc632b73SJames Carlson * 4*dc632b73SJames Carlson * The contents of this file are subject to the terms of the 5*dc632b73SJames Carlson * Common Development and Distribution License (the "License"). 6*dc632b73SJames Carlson * You may not use this file except in compliance with the License. 7*dc632b73SJames Carlson * 8*dc632b73SJames Carlson * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*dc632b73SJames Carlson * or http://www.opensolaris.org/os/licensing. 10*dc632b73SJames Carlson * See the License for the specific language governing permissions 11*dc632b73SJames Carlson * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 13*dc632b73SJames Carlson * When distributing Covered Code, include this CDDL HEADER in each 14*dc632b73SJames Carlson * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*dc632b73SJames Carlson * If applicable, add the following below this CDDL HEADER, with the 16*dc632b73SJames Carlson * fields enclosed by brackets "[]" replaced with your own identifying 17*dc632b73SJames Carlson * information: Portions Copyright [yyyy] [name of copyright owner] 18*dc632b73SJames Carlson * 19*dc632b73SJames Carlson * CDDL HEADER END 20*dc632b73SJames Carlson */ 21*dc632b73SJames Carlson 22*dc632b73SJames Carlson /* 237c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 27*dc632b73SJames Carlson /* 28*dc632b73SJames Carlson * pppoe.c - pppd plugin to handle PPPoE operation. 29*dc632b73SJames Carlson */ 30*dc632b73SJames Carlson 317c478bd9Sstevel@tonic-gate #include <unistd.h> 327c478bd9Sstevel@tonic-gate #include <stddef.h> 337c478bd9Sstevel@tonic-gate #include <stdlib.h> 347c478bd9Sstevel@tonic-gate #include <errno.h> 357c478bd9Sstevel@tonic-gate #include <sys/types.h> 367c478bd9Sstevel@tonic-gate #include <fcntl.h> 377c478bd9Sstevel@tonic-gate #include <strings.h> 387c478bd9Sstevel@tonic-gate #include <sys/stropts.h> 397c478bd9Sstevel@tonic-gate #include <netinet/in.h> 407c478bd9Sstevel@tonic-gate #include <net/pppio.h> 417c478bd9Sstevel@tonic-gate #include <net/sppptun.h> 427c478bd9Sstevel@tonic-gate #include <net/pppoe.h> 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate #include "pppd.h" 457c478bd9Sstevel@tonic-gate #include "pathnames.h" 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate /* Saved hook pointers */ 487c478bd9Sstevel@tonic-gate static int (*old_check_options)(uid_t uid); 497c478bd9Sstevel@tonic-gate static int (*old_updown_script)(const char ***argsp); 507c478bd9Sstevel@tonic-gate static int (*old_sys_read_packet)(int retv, struct strbuf *ctrl, 517c478bd9Sstevel@tonic-gate struct strbuf *data, int flags); 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate /* Room for 3 IPv4 addresses and metric */ 547c478bd9Sstevel@tonic-gate #define RTE_MSG_LEN (3*16 + 10 + 1) 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate /* Environment string for routes */ 577c478bd9Sstevel@tonic-gate #define RTE_STR "ROUTE_%d" 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate /* 607c478bd9Sstevel@tonic-gate * strioctl() 617c478bd9Sstevel@tonic-gate * 627c478bd9Sstevel@tonic-gate * wrapper for STREAMS I_STR ioctl. 637c478bd9Sstevel@tonic-gate */ 647c478bd9Sstevel@tonic-gate static int 657c478bd9Sstevel@tonic-gate strioctl(int fd, int cmd, void *ptr, int ilen, int olen) 667c478bd9Sstevel@tonic-gate { 677c478bd9Sstevel@tonic-gate struct strioctl str; 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate str.ic_cmd = cmd; 707c478bd9Sstevel@tonic-gate str.ic_timout = 0; /* Use default timer; 15 seconds */ 717c478bd9Sstevel@tonic-gate str.ic_len = ilen; 727c478bd9Sstevel@tonic-gate str.ic_dp = ptr; 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate if (ioctl(fd, I_STR, &str) == -1) { 757c478bd9Sstevel@tonic-gate return (-1); 767c478bd9Sstevel@tonic-gate } 777c478bd9Sstevel@tonic-gate if (str.ic_len != olen) { 787c478bd9Sstevel@tonic-gate return (-1); 797c478bd9Sstevel@tonic-gate } 807c478bd9Sstevel@tonic-gate return (0); 817c478bd9Sstevel@tonic-gate } 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate /* 847c478bd9Sstevel@tonic-gate * If the user named the tunneling device, check that it is 857c478bd9Sstevel@tonic-gate * reasonable; otherwise check that standard input is the tunnel. 867c478bd9Sstevel@tonic-gate */ 877c478bd9Sstevel@tonic-gate static int 887c478bd9Sstevel@tonic-gate pppoe_check_options(uid_t uid) 897c478bd9Sstevel@tonic-gate { 907c478bd9Sstevel@tonic-gate int tstfd; /* fd for device being checked */ 917c478bd9Sstevel@tonic-gate int err; /* saved errno value */ 927c478bd9Sstevel@tonic-gate int retv; /* return value */ 937c478bd9Sstevel@tonic-gate int intv; /* integer return value (from ioctl) */ 947c478bd9Sstevel@tonic-gate union ppptun_name ptn; 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate if (devnam[0] != '\0') { 977c478bd9Sstevel@tonic-gate /* 987c478bd9Sstevel@tonic-gate * Open as real user so that modes on device can be 997c478bd9Sstevel@tonic-gate * used to limit access. 1007c478bd9Sstevel@tonic-gate */ 1017c478bd9Sstevel@tonic-gate if (!devnam_info.priv) 1027c478bd9Sstevel@tonic-gate (void) seteuid(uid); 1037c478bd9Sstevel@tonic-gate tstfd = open(devnam, O_NONBLOCK | O_RDWR, 0); 1047c478bd9Sstevel@tonic-gate err = errno; 1057c478bd9Sstevel@tonic-gate if (!devnam_info.priv) 1067c478bd9Sstevel@tonic-gate (void) seteuid(0); 1077c478bd9Sstevel@tonic-gate if (tstfd == -1) { 1087c478bd9Sstevel@tonic-gate errno = err; 1097c478bd9Sstevel@tonic-gate option_error("unable to open %s: %m", devnam); 1107c478bd9Sstevel@tonic-gate return (-1); 1117c478bd9Sstevel@tonic-gate } 1127c478bd9Sstevel@tonic-gate retv = strioctl(tstfd, PPPTUN_GDATA, &ptn, 0, sizeof (ptn)); 1137c478bd9Sstevel@tonic-gate (void) close(tstfd); 1147c478bd9Sstevel@tonic-gate if (retv == -1) { 1157c478bd9Sstevel@tonic-gate option_error("device %s is not a PPP tunneling device", 1167c478bd9Sstevel@tonic-gate devnam); 1177c478bd9Sstevel@tonic-gate return (-1); 1187c478bd9Sstevel@tonic-gate } 1197c478bd9Sstevel@tonic-gate } else { 1207c478bd9Sstevel@tonic-gate retv = strioctl(0, PPPIO_GTYPE, &intv, 0, sizeof (intv)); 1217c478bd9Sstevel@tonic-gate if (retv == -1) { 1227c478bd9Sstevel@tonic-gate option_error("standard input is not a PPP device"); 1237c478bd9Sstevel@tonic-gate return (-1); 1247c478bd9Sstevel@tonic-gate } 1257c478bd9Sstevel@tonic-gate retv = strioctl(0, PPPTUN_GDATA, &ptn, 0, sizeof (ptn)); 1267c478bd9Sstevel@tonic-gate if (retv == -1) { 1277c478bd9Sstevel@tonic-gate option_error("standard input is not a PPP tunnel"); 1287c478bd9Sstevel@tonic-gate return (-1); 1297c478bd9Sstevel@tonic-gate } 1307c478bd9Sstevel@tonic-gate if (strcmp(ptn.ptn_name + strlen(ptn.ptn_name) - 6, 1317c478bd9Sstevel@tonic-gate ":pppoe") != 0) { 1327c478bd9Sstevel@tonic-gate option_error("standard input not connected to PPPoE"); 1337c478bd9Sstevel@tonic-gate return (-1); 1347c478bd9Sstevel@tonic-gate } 1357c478bd9Sstevel@tonic-gate } 1367c478bd9Sstevel@tonic-gate if (old_check_options != NULL && 1377c478bd9Sstevel@tonic-gate old_check_options != pppoe_check_options) 1387c478bd9Sstevel@tonic-gate return ((*old_check_options)(uid)); 1397c478bd9Sstevel@tonic-gate return (0); 1407c478bd9Sstevel@tonic-gate } 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate /* 1437c478bd9Sstevel@tonic-gate * When we're about to call one of the up or down scripts, change the 1447c478bd9Sstevel@tonic-gate * second argument to contain the interface name and selected PPPoE 1457c478bd9Sstevel@tonic-gate * service. 1467c478bd9Sstevel@tonic-gate */ 1477c478bd9Sstevel@tonic-gate static int 1487c478bd9Sstevel@tonic-gate pppoe_updown_script(const char ***argsp) 1497c478bd9Sstevel@tonic-gate { 1507c478bd9Sstevel@tonic-gate const char *cp; 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate if ((*argsp)[2] == devnam && 1537c478bd9Sstevel@tonic-gate (cp = script_getenv("IF_AND_SERVICE")) != NULL) 1547c478bd9Sstevel@tonic-gate (*argsp)[2] = cp; 1557c478bd9Sstevel@tonic-gate if (old_updown_script != NULL && 1567c478bd9Sstevel@tonic-gate old_updown_script != pppoe_updown_script) 1577c478bd9Sstevel@tonic-gate return ((*old_updown_script)(argsp)); 1587c478bd9Sstevel@tonic-gate return (0); 1597c478bd9Sstevel@tonic-gate } 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate /* 1627c478bd9Sstevel@tonic-gate * Concatenate and save strings from command line into environment 1637c478bd9Sstevel@tonic-gate * variable. 1647c478bd9Sstevel@tonic-gate */ 1657c478bd9Sstevel@tonic-gate static void 1667c478bd9Sstevel@tonic-gate cat_save_env(char **argv, char idchar, const char *envname) 1677c478bd9Sstevel@tonic-gate { 1687c478bd9Sstevel@tonic-gate char **argp; 1697c478bd9Sstevel@tonic-gate int totlen; 1707c478bd9Sstevel@tonic-gate char *str; 1717c478bd9Sstevel@tonic-gate char *cp; 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate totlen = 0; 1747c478bd9Sstevel@tonic-gate for (argp = argv; argp[0] != NULL; argp += 2) 1757c478bd9Sstevel@tonic-gate if (*argp[0] == idchar) 1767c478bd9Sstevel@tonic-gate totlen += strlen(argp[1]) + 1; 1777c478bd9Sstevel@tonic-gate if ((str = malloc(totlen + 1)) == NULL) { 1787c478bd9Sstevel@tonic-gate error("cannot malloc PPPoE environment for %s", envname); 1797c478bd9Sstevel@tonic-gate return; 1807c478bd9Sstevel@tonic-gate } 1817c478bd9Sstevel@tonic-gate cp = str; 1827c478bd9Sstevel@tonic-gate for (argp = argv; argp[0] != NULL; argp += 2) 1837c478bd9Sstevel@tonic-gate if (*argp[0] == idchar) { 1847c478bd9Sstevel@tonic-gate (void) strcpy(cp, argp[1]); 1857c478bd9Sstevel@tonic-gate cp += strlen(cp); 1867c478bd9Sstevel@tonic-gate *cp++ = '\n'; 1877c478bd9Sstevel@tonic-gate } 1887c478bd9Sstevel@tonic-gate *cp = '\0'; 1897c478bd9Sstevel@tonic-gate script_setenv(envname, str, 0); 1907c478bd9Sstevel@tonic-gate } 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate /* 1937c478bd9Sstevel@tonic-gate * Convert Message Of The Moment (MOTM) and Host Uniform Resource 1947c478bd9Sstevel@tonic-gate * Locator (HURL) strings into environment variables and command-line 1957c478bd9Sstevel@tonic-gate * arguments for script. 1967c478bd9Sstevel@tonic-gate */ 1977c478bd9Sstevel@tonic-gate static void 1987c478bd9Sstevel@tonic-gate handle_motm_hurl(char **argv, int argc, const uint8_t *tagp, int pktlen) 1997c478bd9Sstevel@tonic-gate { 2007c478bd9Sstevel@tonic-gate int ttype; 2017c478bd9Sstevel@tonic-gate int tlen; 2027c478bd9Sstevel@tonic-gate char *str; 2037c478bd9Sstevel@tonic-gate char **oargv = argv; 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate /* Must have room for two strings and NULL terminator. */ 2067c478bd9Sstevel@tonic-gate while (argc >= 3) { 2077c478bd9Sstevel@tonic-gate str = NULL; 2087c478bd9Sstevel@tonic-gate while (pktlen >= POET_HDRLEN) { 2097c478bd9Sstevel@tonic-gate ttype = POET_GET_TYPE(tagp); 2107c478bd9Sstevel@tonic-gate if (ttype == POETT_END) 2117c478bd9Sstevel@tonic-gate break; 2127c478bd9Sstevel@tonic-gate tlen = POET_GET_LENG(tagp); 2137c478bd9Sstevel@tonic-gate if (tlen > pktlen - POET_HDRLEN) 2147c478bd9Sstevel@tonic-gate break; 2157c478bd9Sstevel@tonic-gate if (ttype == POETT_HURL || ttype == POETT_MOTM) { 2167c478bd9Sstevel@tonic-gate if ((str = malloc(tlen + 1)) == NULL) { 2177c478bd9Sstevel@tonic-gate error("cannot malloc PPPoE message"); 2187c478bd9Sstevel@tonic-gate break; 2197c478bd9Sstevel@tonic-gate } 2207c478bd9Sstevel@tonic-gate (void) memcpy(str, POET_DATA(tagp), tlen); 2217c478bd9Sstevel@tonic-gate str[tlen] = '\0'; 2227c478bd9Sstevel@tonic-gate } 2237c478bd9Sstevel@tonic-gate pktlen -= POET_HDRLEN + tlen; 2247c478bd9Sstevel@tonic-gate tagp += POET_HDRLEN + tlen; 2257c478bd9Sstevel@tonic-gate if (str != NULL) 2267c478bd9Sstevel@tonic-gate break; 2277c478bd9Sstevel@tonic-gate } 2287c478bd9Sstevel@tonic-gate if (str == NULL) 2297c478bd9Sstevel@tonic-gate break; 2307c478bd9Sstevel@tonic-gate *argv++ = ttype == POETT_HURL ? "hurl" : "motm"; 2317c478bd9Sstevel@tonic-gate *argv++ = str; 2327c478bd9Sstevel@tonic-gate argc -= 2; 2337c478bd9Sstevel@tonic-gate } 2347c478bd9Sstevel@tonic-gate *argv = NULL; 2357c478bd9Sstevel@tonic-gate cat_save_env(oargv, 'h', "HURL"); 2367c478bd9Sstevel@tonic-gate cat_save_env(oargv, 'm', "MOTM"); 2377c478bd9Sstevel@tonic-gate } 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate /* 2407c478bd9Sstevel@tonic-gate * Convert IP Route Add structures into environment variables and 2417c478bd9Sstevel@tonic-gate * command-line arguments for script. 2427c478bd9Sstevel@tonic-gate */ 2437c478bd9Sstevel@tonic-gate static void 2447c478bd9Sstevel@tonic-gate handle_ip_route_add(char **argv, int argc, const uint8_t *tagp, int pktlen) 2457c478bd9Sstevel@tonic-gate { 2467c478bd9Sstevel@tonic-gate int ttype; 2477c478bd9Sstevel@tonic-gate int tlen; 2487c478bd9Sstevel@tonic-gate char *str; 2497c478bd9Sstevel@tonic-gate poer_t poer; 2507c478bd9Sstevel@tonic-gate int idx; 2517c478bd9Sstevel@tonic-gate char envname[sizeof (RTE_STR) + 10]; 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate idx = 0; 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate /* Must have room for four strings and NULL terminator. */ 2567c478bd9Sstevel@tonic-gate while (argc >= 5) { 2577c478bd9Sstevel@tonic-gate str = NULL; 2587c478bd9Sstevel@tonic-gate while (pktlen >= POET_HDRLEN) { 2597c478bd9Sstevel@tonic-gate ttype = POET_GET_TYPE(tagp); 2607c478bd9Sstevel@tonic-gate if (ttype == POETT_END) 2617c478bd9Sstevel@tonic-gate break; 2627c478bd9Sstevel@tonic-gate tlen = POET_GET_LENG(tagp); 2637c478bd9Sstevel@tonic-gate if (tlen > pktlen - POET_HDRLEN) 2647c478bd9Sstevel@tonic-gate break; 2657c478bd9Sstevel@tonic-gate if (ttype == POETT_RTEADD && tlen >= sizeof (poer) && 2667c478bd9Sstevel@tonic-gate (str = malloc(RTE_MSG_LEN)) == NULL) { 2677c478bd9Sstevel@tonic-gate error("cannot malloc PPPoE route"); 2687c478bd9Sstevel@tonic-gate break; 2697c478bd9Sstevel@tonic-gate } 2707c478bd9Sstevel@tonic-gate pktlen -= POET_HDRLEN + tlen; 2717c478bd9Sstevel@tonic-gate tagp += POET_HDRLEN + tlen; 2727c478bd9Sstevel@tonic-gate if (str != NULL) 2737c478bd9Sstevel@tonic-gate break; 2747c478bd9Sstevel@tonic-gate } 2757c478bd9Sstevel@tonic-gate if (str == NULL) 2767c478bd9Sstevel@tonic-gate break; 2777c478bd9Sstevel@tonic-gate /* No alignment restrictions on source; copy to local. */ 2787c478bd9Sstevel@tonic-gate (void) memcpy(&poer, POET_DATA(tagp), sizeof (poer)); 2797c478bd9Sstevel@tonic-gate (void) slprintf(str, RTE_MSG_LEN, "%I %I %I %d", 2807c478bd9Sstevel@tonic-gate poer.poer_dest_network, poer.poer_subnet_mask, 2817c478bd9Sstevel@tonic-gate poer.poer_gateway, (int)poer.poer_metric); 2827c478bd9Sstevel@tonic-gate /* Save off the environment variable version of this. */ 2837c478bd9Sstevel@tonic-gate (void) slprintf(envname, sizeof (envname), RTE_STR, ++idx); 2847c478bd9Sstevel@tonic-gate script_setenv(envname, str, 0); 2857c478bd9Sstevel@tonic-gate *argv++ = str; /* Destination */ 2867c478bd9Sstevel@tonic-gate str = strchr(str, ' '); 2877c478bd9Sstevel@tonic-gate *str++ = '\0'; 2887c478bd9Sstevel@tonic-gate *argv++ = str; /* Subnet mask */ 2897c478bd9Sstevel@tonic-gate str = strchr(str, ' '); 2907c478bd9Sstevel@tonic-gate *str++ = '\0'; 2917c478bd9Sstevel@tonic-gate *argv++ = str; /* Gateway */ 2927c478bd9Sstevel@tonic-gate str = strchr(str, ' '); 2937c478bd9Sstevel@tonic-gate *str++ = '\0'; 2947c478bd9Sstevel@tonic-gate *argv++ = str; /* Metric */ 2957c478bd9Sstevel@tonic-gate argc -= 4; 2967c478bd9Sstevel@tonic-gate } 2977c478bd9Sstevel@tonic-gate *argv = NULL; 2987c478bd9Sstevel@tonic-gate } 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate /* 3017c478bd9Sstevel@tonic-gate * If we get here, then the driver has already validated the sender, 3027c478bd9Sstevel@tonic-gate * the PPPoE version, the message length, and session ID. The code 3037c478bd9Sstevel@tonic-gate * number is known not to be zero. 3047c478bd9Sstevel@tonic-gate */ 3057c478bd9Sstevel@tonic-gate static int 3067c478bd9Sstevel@tonic-gate handle_pppoe_input(const ppptun_atype *pma, struct strbuf *ctrl, 3077c478bd9Sstevel@tonic-gate struct strbuf *data) 3087c478bd9Sstevel@tonic-gate { 3097c478bd9Sstevel@tonic-gate const poep_t *poep; 3107c478bd9Sstevel@tonic-gate struct ppp_ls *plp; 3117c478bd9Sstevel@tonic-gate const char *mname; 3127c478bd9Sstevel@tonic-gate const char *cstr; 3137c478bd9Sstevel@tonic-gate char *str; 3147c478bd9Sstevel@tonic-gate char *cp; 3157c478bd9Sstevel@tonic-gate char *argv[64]; 3167c478bd9Sstevel@tonic-gate pid_t rpid; 3177c478bd9Sstevel@tonic-gate char **argp; 3187c478bd9Sstevel@tonic-gate int idx; 3197c478bd9Sstevel@tonic-gate char envname[sizeof (RTE_STR) + 10]; 3207c478bd9Sstevel@tonic-gate const uint8_t *tagp; 3217c478bd9Sstevel@tonic-gate int pktlen; 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate /* 3247c478bd9Sstevel@tonic-gate * Warning: the data->buf pointer here is not necessarily properly 3257c478bd9Sstevel@tonic-gate * aligned for access to the poep_session_id or poep_length members. 3267c478bd9Sstevel@tonic-gate */ 3277c478bd9Sstevel@tonic-gate /* LINTED: alignment */ 3287c478bd9Sstevel@tonic-gate poep = (const poep_t *)data->buf; 3297c478bd9Sstevel@tonic-gate tagp = (const uint8_t *)poep + offsetof(poep_t, poep_length); 3307c478bd9Sstevel@tonic-gate pktlen = (tagp[0] << 8) + tagp[1]; 3317c478bd9Sstevel@tonic-gate tagp = (const uint8_t *)(poep + 1); 3327c478bd9Sstevel@tonic-gate switch (poep->poep_code) { 3337c478bd9Sstevel@tonic-gate case POECODE_PADT: 3347c478bd9Sstevel@tonic-gate dbglog("received PPPoE PADT; connection has been closed"); 3357c478bd9Sstevel@tonic-gate /* LINTED: alignment */ 3367c478bd9Sstevel@tonic-gate plp = (struct ppp_ls *)ctrl->buf; 3377c478bd9Sstevel@tonic-gate plp->magic = PPPLSMAGIC; 3387c478bd9Sstevel@tonic-gate plp->ppp_message = PPP_LINKSTAT_HANGUP; 3397c478bd9Sstevel@tonic-gate ctrl->len = sizeof (*plp); 3407c478bd9Sstevel@tonic-gate return (0); 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate /* Active Discovery Message and Network extensions */ 3437c478bd9Sstevel@tonic-gate case POECODE_PADM: 3447c478bd9Sstevel@tonic-gate case POECODE_PADN: 3457c478bd9Sstevel@tonic-gate if (poep->poep_code == POECODE_PADM) { 3467c478bd9Sstevel@tonic-gate argv[0] = _ROOT_PATH "/etc/ppp/pppoe-msg"; 3477c478bd9Sstevel@tonic-gate mname = "PADM"; 3487c478bd9Sstevel@tonic-gate handle_motm_hurl(argv + 4, Dim(argv) - 4, tagp, pktlen); 3497c478bd9Sstevel@tonic-gate } else { 3507c478bd9Sstevel@tonic-gate argv[0] = _ROOT_PATH "/etc/ppp/pppoe-network"; 3517c478bd9Sstevel@tonic-gate mname = "PADN"; 3527c478bd9Sstevel@tonic-gate handle_ip_route_add(argv + 4, Dim(argv) - 4, tagp, 3537c478bd9Sstevel@tonic-gate pktlen); 3547c478bd9Sstevel@tonic-gate } 3557c478bd9Sstevel@tonic-gate argv[1] = ifname; 3567c478bd9Sstevel@tonic-gate /* Note: strdup doesn't handle NULL input. */ 3577c478bd9Sstevel@tonic-gate str = NULL; 3587c478bd9Sstevel@tonic-gate if ((cstr = script_getenv("IF_AND_SERVICE")) == NULL || 3597c478bd9Sstevel@tonic-gate (str = strdup(cstr)) == NULL) { 3607c478bd9Sstevel@tonic-gate argv[2] = argv[3] = ""; 3617c478bd9Sstevel@tonic-gate } else { 3627c478bd9Sstevel@tonic-gate if ((cp = strrchr(str, ':')) == NULL) 3637c478bd9Sstevel@tonic-gate cp = str + strlen(str); 3647c478bd9Sstevel@tonic-gate else 3657c478bd9Sstevel@tonic-gate *cp++ = '\0'; 3667c478bd9Sstevel@tonic-gate argv[2] = str; 3677c478bd9Sstevel@tonic-gate argv[3] = cp; 3687c478bd9Sstevel@tonic-gate } 3697c478bd9Sstevel@tonic-gate rpid = run_program(argv[0], argv, 0, NULL, NULL); 3707c478bd9Sstevel@tonic-gate if (rpid == (pid_t)0) 3717c478bd9Sstevel@tonic-gate dbglog("ignored PPPoE %s; no %s script", mname, 3727c478bd9Sstevel@tonic-gate argv[0]); 3737c478bd9Sstevel@tonic-gate else if (rpid != (pid_t)-1) 3747c478bd9Sstevel@tonic-gate dbglog("PPPoE %s: started PID %d", mname, rpid); 3757c478bd9Sstevel@tonic-gate if (str != NULL) 3767c478bd9Sstevel@tonic-gate free(str); 3777c478bd9Sstevel@tonic-gate /* Free storage allocated by handle_{motm_hurl,ip_route_add} */ 3787c478bd9Sstevel@tonic-gate idx = 0; 3797c478bd9Sstevel@tonic-gate for (argp = argv + 4; *argp != NULL; ) { 3807c478bd9Sstevel@tonic-gate if (poep->poep_code == POECODE_PADM) { 3817c478bd9Sstevel@tonic-gate free(argp[1]); 3827c478bd9Sstevel@tonic-gate argp += 2; 3837c478bd9Sstevel@tonic-gate } else { 3847c478bd9Sstevel@tonic-gate free(argp[0]); 3857c478bd9Sstevel@tonic-gate argp += 4; 3867c478bd9Sstevel@tonic-gate (void) slprintf(envname, sizeof (envname), 3877c478bd9Sstevel@tonic-gate RTE_STR, ++idx); 3887c478bd9Sstevel@tonic-gate script_unsetenv(envname); 3897c478bd9Sstevel@tonic-gate } 3907c478bd9Sstevel@tonic-gate } 3917c478bd9Sstevel@tonic-gate if (poep->poep_code == POECODE_PADM) { 3927c478bd9Sstevel@tonic-gate script_unsetenv("HURL"); 3937c478bd9Sstevel@tonic-gate script_unsetenv("MOTM"); 3947c478bd9Sstevel@tonic-gate } 3957c478bd9Sstevel@tonic-gate break; 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate default: 3987c478bd9Sstevel@tonic-gate warn("unexpected PPPoE code %d from %s", poep->poep_code, 3997c478bd9Sstevel@tonic-gate ether_ntoa(&pma->pta_pppoe.ptma_mac_ether_addr)); 4007c478bd9Sstevel@tonic-gate break; 4017c478bd9Sstevel@tonic-gate } 4027c478bd9Sstevel@tonic-gate return (-1); 4037c478bd9Sstevel@tonic-gate } 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate /* 4067c478bd9Sstevel@tonic-gate * sys-solaris has just read in a packet; grovel through it and see if 4077c478bd9Sstevel@tonic-gate * it's something we need to handle ourselves. 4087c478bd9Sstevel@tonic-gate */ 4097c478bd9Sstevel@tonic-gate static int 4107c478bd9Sstevel@tonic-gate pppoe_sys_read_packet(int retv, struct strbuf *ctrl, struct strbuf *data, 4117c478bd9Sstevel@tonic-gate int flags) 4127c478bd9Sstevel@tonic-gate { 4137c478bd9Sstevel@tonic-gate struct ppptun_control *ptc; 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate if (retv >= 0 && !(retv & MORECTL) && ctrl->len >= sizeof (uint32_t)) { 4167c478bd9Sstevel@tonic-gate /* LINTED: alignment */ 4177c478bd9Sstevel@tonic-gate ptc = (struct ppptun_control *)ctrl->buf; 4187c478bd9Sstevel@tonic-gate /* ptc_discrim is the first uint32_t of the structure. */ 4197c478bd9Sstevel@tonic-gate if (ptc->ptc_discrim == PPPOE_DISCRIM) { 4207c478bd9Sstevel@tonic-gate retv = -1; 4217c478bd9Sstevel@tonic-gate if (ctrl->len == sizeof (*ptc) && 4227c478bd9Sstevel@tonic-gate ptc->ptc_action == PTCA_CONTROL) 4237c478bd9Sstevel@tonic-gate retv = handle_pppoe_input(&ptc->ptc_address, 4247c478bd9Sstevel@tonic-gate ctrl, data); 4257c478bd9Sstevel@tonic-gate if (retv < 0) 4267c478bd9Sstevel@tonic-gate errno = EAGAIN; 4277c478bd9Sstevel@tonic-gate return (retv); 4287c478bd9Sstevel@tonic-gate } 4297c478bd9Sstevel@tonic-gate } 4307c478bd9Sstevel@tonic-gate /* Forward along to other plug-ins */ 4317c478bd9Sstevel@tonic-gate if (old_sys_read_packet != NULL && 4327c478bd9Sstevel@tonic-gate old_sys_read_packet != pppoe_sys_read_packet) 4337c478bd9Sstevel@tonic-gate return ((*old_sys_read_packet)(retv, ctrl, data, flags)); 4347c478bd9Sstevel@tonic-gate return (retv); 4357c478bd9Sstevel@tonic-gate } 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate /* 4387c478bd9Sstevel@tonic-gate * Get an environment variable from the chat script. 4397c478bd9Sstevel@tonic-gate */ 4407c478bd9Sstevel@tonic-gate static int 4417c478bd9Sstevel@tonic-gate saveenv(FILE *fd, const char *envname) 4427c478bd9Sstevel@tonic-gate { 4437c478bd9Sstevel@tonic-gate char envstr[1024]; 4447c478bd9Sstevel@tonic-gate int len; 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate if (fgets(envstr, sizeof (envstr), fd) == NULL) 4477c478bd9Sstevel@tonic-gate return (-1); 4487c478bd9Sstevel@tonic-gate len = strlen(envstr); 4497c478bd9Sstevel@tonic-gate if (len <= 1) 4507c478bd9Sstevel@tonic-gate return (0); 4517c478bd9Sstevel@tonic-gate envstr[len-1] = '\0'; 4527c478bd9Sstevel@tonic-gate script_setenv(envname, envstr, 0); 4537c478bd9Sstevel@tonic-gate return (1); 4547c478bd9Sstevel@tonic-gate } 4557c478bd9Sstevel@tonic-gate 4567c478bd9Sstevel@tonic-gate /* 4577c478bd9Sstevel@tonic-gate * Read environment variables exported by chat script. 4587c478bd9Sstevel@tonic-gate */ 4597c478bd9Sstevel@tonic-gate static void 4607c478bd9Sstevel@tonic-gate pppoe_device_pipe(int pipefd) 4617c478bd9Sstevel@tonic-gate { 4627c478bd9Sstevel@tonic-gate FILE *fd; 4637c478bd9Sstevel@tonic-gate int i; 4647c478bd9Sstevel@tonic-gate char envname[32]; 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate fd = fdopen(pipefd, "r"); 4677c478bd9Sstevel@tonic-gate if (fd == NULL) 4687c478bd9Sstevel@tonic-gate fatal("unable to open environment file: %m"); 4697c478bd9Sstevel@tonic-gate (void) saveenv(fd, "IF_AND_SERVICE"); 4707c478bd9Sstevel@tonic-gate (void) saveenv(fd, "SERVICE_NAME"); 4717c478bd9Sstevel@tonic-gate (void) saveenv(fd, "AC_NAME"); 4727c478bd9Sstevel@tonic-gate (void) saveenv(fd, "AC_MAC"); 4737c478bd9Sstevel@tonic-gate (void) saveenv(fd, "SESSION_ID"); 4747c478bd9Sstevel@tonic-gate for (i = 1; ; i++) { 4757c478bd9Sstevel@tonic-gate slprintf(envname, sizeof (envname), "VENDOR_SPECIFIC_%d", i); 4767c478bd9Sstevel@tonic-gate if (saveenv(fd, envname) <= 0) 4777c478bd9Sstevel@tonic-gate break; 4787c478bd9Sstevel@tonic-gate } 4797c478bd9Sstevel@tonic-gate (void) fclose(fd); 4807c478bd9Sstevel@tonic-gate } 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate void 4837c478bd9Sstevel@tonic-gate plugin_init(void) 4847c478bd9Sstevel@tonic-gate { 4857c478bd9Sstevel@tonic-gate if (absmax_mtu > 1492) 4867c478bd9Sstevel@tonic-gate absmax_mtu = 1492; 4877c478bd9Sstevel@tonic-gate if (absmax_mru > 1492) 4887c478bd9Sstevel@tonic-gate absmax_mru = 1492; 4897c478bd9Sstevel@tonic-gate old_check_options = check_options_hook; 4907c478bd9Sstevel@tonic-gate check_options_hook = pppoe_check_options; 4917c478bd9Sstevel@tonic-gate old_updown_script = updown_script_hook; 4927c478bd9Sstevel@tonic-gate updown_script_hook = pppoe_updown_script; 4937c478bd9Sstevel@tonic-gate old_sys_read_packet = sys_read_packet_hook; 4947c478bd9Sstevel@tonic-gate sys_read_packet_hook = pppoe_sys_read_packet; 4957c478bd9Sstevel@tonic-gate device_pipe_hook = pppoe_device_pipe; 4967c478bd9Sstevel@tonic-gate already_ppp = 1; 4977c478bd9Sstevel@tonic-gate } 498