/*
* System-dependent procedures for pppd under Solaris 2.
*
+ * Parts re-written by Adi Masputra <adi.masputra@sun.com>, based on
+ * the original sys-svr4.c
+ *
+ * Copyright (c) 2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, provided that the above copyright
+ * notice appears in all copies.
+ *
+ * SUN MAKES NO REPRESENTATION OR WARRANTIES ABOUT THE SUITABILITY OF
+ * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+ * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES
+ *
* Copyright (c) 1994 The Australian National University.
* All rights reserved.
*
* OR MODIFICATIONS.
*/
-#define RCSID "$Id: sys-svr4.c,v 1.39 2000/01/25 03:25:36 masputra Exp $"
+#define RCSID "$Id: sys-svr4.c,v 1.44 2002/02/12 20:07:10 dfs Exp $"
#include <limits.h>
#include <stdio.h>
#endif
#include "pppd.h"
+#include "fsm.h"
+#include "lcp.h"
+#include "ipcp.h"
+#include "ccp.h"
#if !defined(PPP_DEV_NAME)
#define PPP_DEV_NAME "/dev/ppp"
#endif /* defined(INET6) && defined(SOL2) */
+#if defined(INET6) && defined(SOL2)
+static char first_ether_name[LIFNAMSIZ]; /* Solaris 8 and above */
+#else
+static char first_ether_name[IFNAMSIZ]; /* Before Solaris 8 */
+#define MAXIFS 256 /* Max # of interfaces */
+#endif /* defined(INET6) && defined(SOL2) */
+
static int restore_term;
static struct termios inittermios;
#ifndef CRTSCTS
#if defined(SOL2) && defined(INET6)
/*
- * slifname - Sets interface ppa and flags
- *
- * in addition to the comments stated in sifppa(), IFF_IPV6 bit must
- * be set in order to declare this as an IPv6 interface
- */
-static int
-slifname(fd, ppa)
- int fd;
- int ppa;
-{
- struct lifreq lifr;
- int ret;
-
- memset(&lifr, 0, sizeof(lifr));
- ret = ioctl(fd, SIOCGLIFFLAGS, &lifr);
- if (ret < 0)
- goto slifname_done;
-
- lifr.lifr_flags |= IFF_IPV6;
- lifr.lifr_flags &= ~(IFF_BROADCAST | IFF_IPV4);
- lifr.lifr_ppa = ppa;
- strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
-
- ret = ioctl(fd, SIOCSLIFNAME, &lifr);
-
-slifname_done:
- return ret;
-
-
-}
-
-/*
- * ether_to_eui64 - Convert 48-bit Ethernet address into 64-bit EUI
+ * get_first_ethernet - returns the first Ethernet interface name found in
+ * the system, or NULL if none is found
*
- * walks the list of valid ethernet interfaces, and convert the first
- * found 48-bit MAC address into EUI 64. caller also assumes that
- * the system has a properly configured Ethernet interface for this
- * function to return non-zero.
+ * NOTE: This is the lifreq version (Solaris 8 and above)
*/
-int
-ether_to_eui64(eui64_t *p_eui64)
+char *
+get_first_ethernet()
{
struct lifnum lifn;
struct lifconf lifc;
int fd, num_ifs, i, found;
uint_t fl, req_size;
char *req;
- struct sockaddr s_eth_addr;
- struct ether_addr *eth_addr = (struct ether_addr *)&s_eth_addr.sa_data;
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
*/
plifreq = lifc.lifc_req;
found = 0;
- for (i = lifc.lifc_len / sizeof(struct lifreq); i>0; i--, plifreq++) {
+ for (i = lifc.lifc_len / sizeof(struct lifreq); i > 0; i--, plifreq++) {
if (strchr(plifreq->lifr_name, ':') != NULL)
continue;
free(req);
close(fd);
- if (!found) {
+ if (found) {
+ strncpy(first_ether_name, lifr.lifr_name, sizeof(first_ether_name));
+ return (char *)first_ether_name;
+ } else
+ return NULL;
+}
+#else
+/*
+ * get_first_ethernet - returns the first Ethernet interface name found in
+ * the system, or NULL if none is found
+ *
+ * NOTE: This is the ifreq version (before Solaris 8).
+ */
+char *
+get_first_ethernet()
+{
+ struct ifconf ifc;
+ struct ifreq *pifreq;
+ struct ifreq ifr;
+ int fd, num_ifs, i, found;
+ uint_t fl, req_size;
+ char *req;
+
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (fd < 0) {
+ return 0;
+ }
+
+ /*
+ * Find out how many interfaces are running
+ */
+ if (ioctl(fd, SIOCGIFNUM, (char *)&num_ifs) < 0) {
+ num_ifs = MAXIFS;
+ }
+
+ req_size = num_ifs * sizeof(struct ifreq);
+ req = malloc(req_size);
+ if (req == NULL) {
+ close(fd);
+ error("out of memory");
+ return 0;
+ }
+
+ /*
+ * Get interface configuration info for all interfaces
+ */
+ ifc.ifc_len = req_size;
+ ifc.ifc_buf = req;
+ if (ioctl(fd, SIOCGIFCONF, &ifc) < 0) {
+ close(fd);
+ free(req);
+ error("SIOCGIFCONF: %m");
+ return 0;
+ }
+
+ /*
+ * And traverse each interface to look specifically for the first
+ * occurence of an Ethernet interface which has been marked up
+ */
+ pifreq = ifc.ifc_req;
+ found = 0;
+ for (i = ifc.ifc_len / sizeof(struct ifreq); i > 0; i--, pifreq++) {
+
+ if (strchr(pifreq->ifr_name, ':') != NULL)
+ continue;
+
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, pifreq->ifr_name, sizeof(ifr.ifr_name));
+ if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
+ close(fd);
+ free(req);
+ error("SIOCGIFFLAGS: %m");
+ return 0;
+ }
+ fl = ifr.ifr_flags;
+
+ if ((fl & (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
+ != (IFF_UP | IFF_BROADCAST))
+ continue;
+
+ found = 1;
+ break;
+ }
+ free(req);
+ close(fd);
+
+ if (found) {
+ strncpy(first_ether_name, ifr.ifr_name, sizeof(first_ether_name));
+ return (char *)first_ether_name;
+ } else
+ return NULL;
+}
+#endif /* defined(SOL2) && defined(INET6) */
+
+#if defined(SOL2)
+/*
+ * get_if_hwaddr - get the hardware address for the specified
+ * network interface device.
+ */
+int
+get_if_hwaddr(u_char *addr, char *if_name)
+{
+ struct sockaddr s_eth_addr;
+ struct ether_addr *eth_addr = (struct ether_addr *)&s_eth_addr.sa_data;
+
+ if (if_name == NULL)
+ return -1;
+
+ /*
+ * Send DL_INFO_REQ to the driver to solicit its MAC address
+ */
+ if (!get_hw_addr_dlpi(if_name, &s_eth_addr)) {
+ error("could not obtain hardware address for %s", if_name);
+ return -1;
+ }
+
+ memcpy(addr, eth_addr->ether_addr_octet, 6);
+ return 1;
+}
+#endif /* SOL2 */
+
+#if defined(SOL2) && defined(INET6)
+/*
+ * slifname - Sets interface ppa and flags
+ *
+ * in addition to the comments stated in sifppa(), IFF_IPV6 bit must
+ * be set in order to declare this as an IPv6 interface
+ */
+static int
+slifname(fd, ppa)
+ int fd;
+ int ppa;
+{
+ struct lifreq lifr;
+ int ret;
+
+ memset(&lifr, 0, sizeof(lifr));
+ ret = ioctl(fd, SIOCGLIFFLAGS, &lifr);
+ if (ret < 0)
+ goto slifname_done;
+
+ lifr.lifr_flags |= IFF_IPV6;
+ lifr.lifr_flags &= ~(IFF_BROADCAST | IFF_IPV4);
+ lifr.lifr_ppa = ppa;
+ strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
+
+ ret = ioctl(fd, SIOCSLIFNAME, &lifr);
+
+slifname_done:
+ return ret;
+
+
+}
+
+
+/*
+ * ether_to_eui64 - Convert 48-bit Ethernet address into 64-bit EUI
+ *
+ * walks the list of valid ethernet interfaces, and convert the first
+ * found 48-bit MAC address into EUI 64. caller also assumes that
+ * the system has a properly configured Ethernet interface for this
+ * function to return non-zero.
+ */
+int
+ether_to_eui64(eui64_t *p_eui64)
+{
+ struct sockaddr s_eth_addr;
+ struct ether_addr *eth_addr = (struct ether_addr *)&s_eth_addr.sa_data;
+ char *if_name;
+
+ if ((if_name = get_first_ethernet()) == NULL) {
error("no persistent id can be found");
return 0;
}
/*
* Send DL_INFO_REQ to the driver to solicit its MAC address
*/
- if (!get_hw_addr_dlpi(plifreq->lifr_name, &s_eth_addr)) {
- error("could not obtain hardware address for %s", plifreq->lifr_name);
+ if (!get_hw_addr_dlpi(if_name, &s_eth_addr)) {
+ error("could not obtain hardware address for %s", if_name);
return 0;
}
return stat(PPP_DEV_NAME, &buf) >= 0;
}
+/*
+ * any_compressions - see if compression is enabled or not
+ *
+ * In the STREAMS implementation of kernel-portion pppd,
+ * the comp STREAMS module performs the ACFC, PFC, as well
+ * CCP and VJ compressions. However, if the user has explicitly
+ * declare to not enable them from the command line, there is
+ * no point of having the comp module be pushed on the stream.
+ */
+static int
+any_compressions()
+{
+ if ((!lcp_wantoptions[0].neg_accompression) &&
+ (!lcp_wantoptions[0].neg_pcompression) &&
+ (!ccp_protent.enabled_flag) &&
+ (!ipcp_wantoptions[0].neg_vj)) {
+ return 0;
+ }
+ return 1;
+}
+
/*
* establish_ppp - Turn the serial port into a ppp interface.
*/
i = PPPDBG_LOG + PPPDBG_AHDLC;
strioctl(pppfd, PPPIO_DEBUG, &i, sizeof(int), 0);
}
- if (ioctl(fd, I_PUSH, COMP_MOD_NAME) < 0)
- error("Couldn't push PPP compression module: %m");
- else
- ++tty_npushed;
+ /*
+ * There's no need to push comp module if we don't intend
+ * to compress anything
+ */
+ if (any_compressions()) {
+ if (ioctl(fd, I_PUSH, COMP_MOD_NAME) < 0)
+ error("Couldn't push PPP compression module: %m");
+ else
+ ++tty_npushed;
+ }
+
if (kdebugflag & 2) {
- i = PPPDBG_LOG + PPPDBG_COMP;
+ i = PPPDBG_LOG;
+ if (any_compressions())
+ i += PPPDBG_COMP;
strioctl(pppfd, PPPIO_DEBUG, &i, sizeof(int), 0);
}
int retries;
struct pollfd pfd;
- if (debug)
- dbglog("sent %P", p, len);
+ dump_packet("sent", p, len);
+ if (snoop_send_hook) snoop_send_hook(p, len);
data.len = len;
data.buf = (caddr_t) p;
}
cf[0] = (pcomp? COMP_PROT: 0) + (accomp? COMP_AC: 0);
cf[1] = COMP_PROT | COMP_AC;
- if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
+ if (any_compressions() &&
+ strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
error("Couldn't set prot/AC compression: %m");
}
}
}
cf[0] = (pcomp? DECOMP_PROT: 0) + (accomp? DECOMP_AC: 0);
cf[1] = DECOMP_PROT | DECOMP_AC;
- if (strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
+ if (any_compressions() &&
+ strioctl(pppfd, PPPIO_CFLAGS, cf, sizeof(cf), sizeof(int)) < 0) {
error("Couldn't set prot/AC decompression: %m");
}
}
{
struct ppp_stats s;
- if (strioctl(pppfd, PPPIO_GETSTAT, &s, 0, sizeof(s)) < 0) {
+ if (!sync_serial &&
+ strioctl(pppfd, PPPIO_GETSTAT, &s, 0, sizeof(s)) < 0) {
error("Couldn't get link statistics: %m");
return 0;
}