]> git.ozlabs.org Git - ppp.git/blobdiff - pppd/sys-svr4.c
Remove the requirement that redistributions in binary form reproduce
[ppp.git] / pppd / sys-svr4.c
index 0743da189060271b1194ff54726f242d9dc3e1b9..1230cc6e275b4049c511ceb90deefabd9ddf3733 100644 (file)
@@ -1,31 +1,91 @@
 /*
  * System-dependent procedures for pppd under Solaris 2.
  *
- * Copyright (c) 1994 The Australian National University.
+ * 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.  This software is provided without any
- * warranty, express or implied. The Australian National University
- * makes no representations about the suitability of this software for
- * any purpose.
+ * 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) 1995-2002 Paul Mackerras. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. The name(s) of the authors of this software must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission.
+ *
+ * 3. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by Paul Mackerras
+ *     <paulus@samba.org>".
+ *
+ * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
+ * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Derived from main.c and pppd.h, which are:
+ *
+ * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
  *
- * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
- * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
- * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
  *
- * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
- * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
- * OR MODIFICATIONS.
+ * 3. The name "Carnegie Mellon University" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For permission or any legal
+ *    details, please contact
+ *      Office of Technology Transfer
+ *      Carnegie Mellon University
+ *      5000 Forbes Avenue
+ *      Pittsburgh, PA  15213-3890
+ *      (412) 268-4387, fax: (412) 268-7395
+ *      tech-transfer@andrew.cmu.edu
+ *
+ * 4. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by Computing Services
+ *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
+ *
+ * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
+ * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
+ * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#define RCSID  "$Id: sys-svr4.c,v 1.41 2000/02/11 03:09:19 masputra Exp $"
+#define RCSID  "$Id: sys-svr4.c,v 1.46 2004/11/04 10:02:26 paulus Exp $"
 
 #include <limits.h>
 #include <stdio.h>
@@ -140,6 +200,13 @@ static int if6_is_up = 0;  /* IPv6 interface has been marked up */
 
 #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
@@ -208,47 +275,13 @@ sifppa(fd, ppa)
 
 #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;
@@ -257,8 +290,6 @@ ether_to_eui64(eui64_t *p_eui64)
     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) {
@@ -305,7 +336,7 @@ ether_to_eui64(eui64_t *p_eui64)
      */
     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;
@@ -330,7 +361,177 @@ ether_to_eui64(eui64_t *p_eui64)
     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;
     }
@@ -338,8 +539,8 @@ ether_to_eui64(eui64_t *p_eui64)
     /*
      * 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;
     }
 
@@ -1139,8 +1340,8 @@ output(unit, p, len)
     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;