aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin/pppd
diff options
context:
space:
mode:
authorHajimu UMEMOTO <ume@FreeBSD.org>2006-11-12 17:36:58 +0000
committerHajimu UMEMOTO <ume@FreeBSD.org>2006-11-12 17:36:58 +0000
commitda525eb2e7be828a240c72655fa8827f6d74329b (patch)
tree05937561403a5398bf451b11d2cefcf5cbc84a4d /usr.sbin/pppd
parent39383a88d2975c183fecaf6d98f995207c80efcb (diff)
downloadsrc-da525eb2e7be828a240c72655fa8827f6d74329b.tar.gz
src-da525eb2e7be828a240c72655fa8827f6d74329b.zip
Teach an IPV6CP to pppd(8).
The eui64.[ch] and ipv6cp.[ch] were taken from ppp-2.3.11. However, our stock pppd(8) doesn't provide option_t nor some utility functions. So, I made some hacks to adjust to our stock pppd(8). The sys_bsd.c part was taken from NetBSD with some modifications to adjust to our stock pppd(8). MFC after: 1 week
Notes
Notes: svn path=/head/; revision=164222
Diffstat (limited to 'usr.sbin/pppd')
-rw-r--r--usr.sbin/pppd/Makefile5
-rw-r--r--usr.sbin/pppd/eui64.c6
-rw-r--r--usr.sbin/pppd/ipv6cp.c99
-rw-r--r--usr.sbin/pppd/ipv6cp.h3
-rw-r--r--usr.sbin/pppd/main.c6
-rw-r--r--usr.sbin/pppd/options.c113
-rw-r--r--usr.sbin/pppd/pathnames.h5
-rw-r--r--usr.sbin/pppd/pppd.849
-rw-r--r--usr.sbin/pppd/pppd.h16
-rw-r--r--usr.sbin/pppd/sys-bsd.c130
10 files changed, 351 insertions, 81 deletions
diff --git a/usr.sbin/pppd/Makefile b/usr.sbin/pppd/Makefile
index 3a09d271a720..2df0330337cd 100644
--- a/usr.sbin/pppd/Makefile
+++ b/usr.sbin/pppd/Makefile
@@ -39,6 +39,11 @@ LDADD+= -lcrypto
DPADD+= ${LIBCRYPTO}
.endif
+.if ${MK_INET6_SUPPORT} != "no"
+CFLAGS+=-DINET6
+SRCS+= eui64.c ipv6cp.c
+.endif
+
.if defined(RELEASE_CRUNCH)
# We must create these objects because crunchgen will link them,
# and we don't want any unused symbols to spoil the final link.
diff --git a/usr.sbin/pppd/eui64.c b/usr.sbin/pppd/eui64.c
index a59186d8d565..28335a3797ff 100644
--- a/usr.sbin/pppd/eui64.c
+++ b/usr.sbin/pppd/eui64.c
@@ -18,11 +18,17 @@
$Id: eui64.c,v 1.3 1999/08/25 04:15:51 paulus Exp $
*/
+#ifndef lint
#define RCSID "$Id: eui64.c,v 1.3 1999/08/25 04:15:51 paulus Exp $"
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
#include "pppd.h"
+#ifdef RCSID
static const char rcsid[] = RCSID;
+#endif
/*
* eui64_ntoa - Make an ascii representation of an interface identifier
diff --git a/usr.sbin/pppd/ipv6cp.c b/usr.sbin/pppd/ipv6cp.c
index 326ff65d572c..0be6dc4e116e 100644
--- a/usr.sbin/pppd/ipv6cp.c
+++ b/usr.sbin/pppd/ipv6cp.c
@@ -93,7 +93,11 @@
* $Id: ipv6cp.c,v 1.7 1999/10/08 01:08:18 masputra Exp $
*/
+#ifndef lint
#define RCSID "$Id: ipv6cp.c,v 1.7 1999/10/08 01:08:18 masputra Exp $"
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
/*
* TODO:
@@ -107,6 +111,7 @@
#include <stdio.h>
#include <string.h>
+#include <syslog.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/param.h>
@@ -122,7 +127,11 @@
#include "magic.h"
#include "pathnames.h"
+#define s6_addr32 __u6_addr.__u6_addr32
+
+#ifdef RCSID
static const char rcsid[] = RCSID;
+#endif
/* global vars */
ipv6cp_options ipv6cp_wantoptions[NUM_PPP]; /* Options that we want to request */
@@ -168,41 +177,6 @@ static fsm_callbacks ipv6cp_callbacks = { /* IPV6CP callback routines */
"IPV6CP" /* String name of protocol */
};
-/*
- * Command-line options.
- */
-static int setifaceid __P((char **arg));
-
-static option_t ipv6cp_option_list[] = {
- { "ipv6", o_special, setifaceid,
- "Set interface identifiers for IPV6" },
- { "noipv6", o_bool, &ipv6cp_protent.enabled_flag,
- "Disable IPv6 and IPv6CP" },
- { "-ipv6", o_bool, &ipv6cp_protent.enabled_flag,
- "Disable IPv6 and IPv6CP" },
- { "+ipv6", o_bool, &ipv6cp_protent.enabled_flag,
- "Enable IPv6 and IPv6CP", 1 },
-
- { "ipv6cp-accept-local", o_bool, &ipv6cp_allowoptions[0].accept_local,
- "Accept peer's interface identifier for us", 1 },
- { "ipv6cp-use-ipaddr", o_bool, &ipv6cp_allowoptions[0].use_ip,
- "Use (default) IPv4 address as interface identifier", 0 },
-#if defined(SOL2)
- { "ipv6cp-use-persistent", o_bool, &ipv6cp_wantoptions[0].use_persistent,
- "Use uniquely-available persistent value for link local address", 1 },
-#endif /* defined(SOL2) */
- { "ipv6cp-restart", o_int, &ipv6cp_fsm[0].timeouttime,
- "Set timeout for IPv6CP" },
- { "ipv6cp-max-terminate", o_int, &ipv6cp_fsm[0].maxtermtransmits,
- "Set max #xmits for term-reqs" },
- { "ipv6cp-max-configure", o_int, &ipv6cp_fsm[0].maxconfreqtransmits,
- "Set max #xmits for conf-reqs" },
- { "ipv6cp-max-failure", o_int, &ipv6cp_fsm[0].maxnakloops,
- "Set max #conf-naks for IPv6CP" },
-
- { NULL }
-};
-
/*
* Protocol entry points from main code.
@@ -233,8 +207,6 @@ struct protent ipv6cp_protent = {
NULL,
0,
"IPV6CP",
- "IPV6",
- ipv6cp_option_list,
ipv6_check_options,
ipv6_demand_conf,
ipv6_active_pkt
@@ -242,7 +214,6 @@ struct protent ipv6cp_protent = {
static void ipv6cp_clear_addrs __P((int, eui64_t, eui64_t));
static void ipv6cp_script __P((char *));
-static void ipv6cp_script_done __P((void *));
/*
* Lengths of configuration options.
@@ -262,12 +233,11 @@ static enum script_state {
s_down,
s_up,
} ipv6cp_script_state;
-static pid_t ipv6cp_script_pid;
/*
* setifaceid - set the interface identifiers manually
*/
-static int
+int
setifaceid(argv)
char **argv;
{
@@ -1069,9 +1039,9 @@ ipv6_demand_conf(u)
if (!sifnpmode(u, PPP_IPV6, NPMODE_QUEUE))
return 0;
- notice("ipv6_demand_conf");
- notice("local LL address %s", llv6_ntoa(wo->ourid));
- notice("remote LL address %s", llv6_ntoa(wo->hisid));
+ syslog(LOG_NOTICE, "ipv6_demand_conf");
+ syslog(LOG_NOTICE, "local LL address %s", llv6_ntoa(wo->ourid));
+ syslog(LOG_NOTICE, "remote LL address %s", llv6_ntoa(wo->hisid));
return 1;
}
@@ -1100,17 +1070,17 @@ ipv6cp_up(f)
if(!no_ifaceid_neg) {
if (eui64_iszero(ho->hisid)) {
- error("Could not determine remote LL address");
+ syslog(LOG_ERR, "Could not determine remote LL address");
ipv6cp_close(f->unit, "Could not determine remote LL address");
return;
}
if (eui64_iszero(go->ourid)) {
- error("Could not determine local LL address");
+ syslog(LOG_ERR, "Could not determine local LL address");
ipv6cp_close(f->unit, "Could not determine local LL address");
return;
}
if (eui64_equals(go->ourid, ho->hisid)) {
- error("local and remote LL addresses are equal");
+ syslog(LOG_ERR, "local and remote LL addresses are equal");
ipv6cp_close(f->unit, "local and remote LL addresses are equal");
return;
}
@@ -1191,8 +1161,8 @@ ipv6cp_up(f)
#endif
sifnpmode(f->unit, PPP_IPV6, NPMODE_PASS);
- notice("local LL address %s", llv6_ntoa(go->ourid));
- notice("remote LL address %s", llv6_ntoa(ho->hisid));
+ syslog(LOG_NOTICE, "local LL address %s", llv6_ntoa(go->ourid));
+ syslog(LOG_NOTICE, "remote LL address %s", llv6_ntoa(ho->hisid));
}
np_up(f->unit, PPP_IPV6);
@@ -1202,7 +1172,7 @@ ipv6cp_up(f)
* Execute the ipv6-up script, like this:
* /etc/ppp/ipv6-up interface tty speed local-LL remote-LL
*/
- if (ipv6cp_script_state == s_down && ipv6cp_script_pid == 0) {
+ if (ipv6cp_script_state == s_down) {
ipv6cp_script_state = s_up;
ipv6cp_script(_PATH_IPV6UP);
}
@@ -1220,7 +1190,6 @@ ipv6cp_down(f)
fsm *f;
{
IPV6CPDEBUG(("ipv6cp: down"));
- update_link_stats(f->unit);
if (ipv6cp_is_up) {
ipv6cp_is_up = 0;
np_down(f->unit, PPP_IPV6);
@@ -1253,7 +1222,7 @@ ipv6cp_down(f)
}
/* Execute the ipv6-down script */
- if (ipv6cp_script_state == s_up && ipv6cp_script_pid == 0) {
+ if (ipv6cp_script_state == s_up) {
ipv6cp_script_state = s_down;
ipv6cp_script(_PATH_IPV6DOWN);
}
@@ -1286,32 +1255,6 @@ ipv6cp_finished(f)
/*
- * ipv6cp_script_done - called when the ipv6-up or ipv6-down script
- * has finished.
- */
-static void
-ipv6cp_script_done(arg)
- void *arg;
-{
- ipv6cp_script_pid = 0;
- switch (ipv6cp_script_state) {
- case s_up:
- if (ipv6cp_fsm[0].state != OPENED) {
- ipv6cp_script_state = s_down;
- ipv6cp_script(_PATH_IPV6DOWN);
- }
- break;
- case s_down:
- if (ipv6cp_fsm[0].state == OPENED) {
- ipv6cp_script_state = s_up;
- ipv6cp_script(_PATH_IPV6UP);
- }
- break;
- }
-}
-
-
-/*
* ipv6cp_script - Execute a script with arguments
* interface-name tty-name speed local-LL remote-LL.
*/
@@ -1335,7 +1278,7 @@ ipv6cp_script(script)
argv[6] = ipparam;
argv[7] = NULL;
- ipv6cp_script_pid = run_program(script, argv, 0, ipv6cp_script_done, NULL);
+ run_program(script, argv, 0);
}
/*
diff --git a/usr.sbin/pppd/ipv6cp.h b/usr.sbin/pppd/ipv6cp.h
index d800d5d5da4b..2641008e99ad 100644
--- a/usr.sbin/pppd/ipv6cp.h
+++ b/usr.sbin/pppd/ipv6cp.h
@@ -91,6 +91,7 @@
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* $Id: ipv6cp.h,v 1.3 1999/09/30 19:57:45 masputra Exp $
+ * $FreeBSD$
*/
/*
@@ -124,3 +125,5 @@ extern ipv6cp_options ipv6cp_allowoptions[];
extern ipv6cp_options ipv6cp_hisoptions[];
extern struct protent ipv6cp_protent;
+
+extern int setifaceid __P((char **arg));
diff --git a/usr.sbin/pppd/main.c b/usr.sbin/pppd/main.c
index c2d0abfbc3c4..7bb104dde65a 100644
--- a/usr.sbin/pppd/main.c
+++ b/usr.sbin/pppd/main.c
@@ -46,6 +46,9 @@ static char rcsid[] = "$FreeBSD$";
#include "fsm.h"
#include "lcp.h"
#include "ipcp.h"
+#ifdef INET6
+#include "ipv6cp.h"
+#endif
#include "upap.h"
#include "chap.h"
#include "ccp.h"
@@ -152,6 +155,9 @@ struct protent *protocols[] = {
&cbcp_protent,
#endif
&ipcp_protent,
+#ifdef INET6
+ &ipv6cp_protent,
+#endif
&ccp_protent,
#ifdef IPX_CHANGE
&ipxcp_protent,
diff --git a/usr.sbin/pppd/options.c b/usr.sbin/pppd/options.c
index d1e679b2aa43..00ad006ef4d1 100644
--- a/usr.sbin/pppd/options.c
+++ b/usr.sbin/pppd/options.c
@@ -55,6 +55,10 @@ static char rcsid[] = "$FreeBSD$";
#include "cbcp.h"
#endif
+#ifdef INET6
+#include "ipv6cp.h"
+#endif
+
#ifdef IPX_CHANGE
#include "ipxcp.h"
#endif /* IPX_CHANGE */
@@ -227,6 +231,7 @@ static int setpapcrypt __P((char **));
static int setidle __P((char **));
static int setholdoff __P((char **));
static int setdnsaddr __P((char **));
+static int resetipv6proto __P((char **));
static int resetipxproto __P((char **));
static int setwinsaddr __P((char **));
static int showversion __P((char **));
@@ -238,6 +243,19 @@ static int setpassfilter __P((char **));
static int setactivefilter __P((char **));
#endif
+#ifdef INET6
+static int setipv6cp_accept_local __P((char **));
+static int setipv6cp_use_ip __P((char **));
+#if defined(SOL2)
+static int setipv6cp_use_persistent __P((char **));
+#endif
+static int setipv6cptimeout __P((char **));
+static int setipv6cpterm __P((char **));
+static int setipv6cpconf __P((char **));
+static int setipv6cpfails __P((char **));
+static int setipv6proto __P((char **));
+#endif /* INET6 */
+
#ifdef IPX_CHANGE
static int setipxproto __P((char **));
static int setipxanet __P((char **));
@@ -388,6 +406,8 @@ static struct cmd {
/* end compat hack */
{"ms-dns", 1, setdnsaddr}, /* DNS address for the peer's use */
{"ms-wins", 1, setwinsaddr}, /* Nameserver for SMB over TCP/IP for peer */
+ {"noipv6", 0, resetipv6proto}, /* Disable IPv6 and IPv6CP */
+ {"-ipv6", 0, resetipv6proto}, /* Disable IPv6 and IPv6CP */
{"noipx", 0, resetipxproto}, /* Disable IPXCP (and IPX) */
{"-ipx", 0, resetipxproto}, /* Disable IPXCP (and IPX) */
{"--version", 0, showversion}, /* Show version number */
@@ -400,6 +420,20 @@ static struct cmd {
{"active-filter", 1, setactivefilter}, /* set filter for active pkts */
#endif
+#ifdef INET6
+ {"ipv6", 1, setifaceid}, /* Set interface id for IPV6" */
+ {"+ipv6", 0, setipv6proto}, /* Enable IPv6 and IPv6CP */
+ {"ipv6cp-accept-local", 0, setipv6cp_accept_local}, /* Accept peer's iface id for us */
+ {"ipv6cp-use-ipaddr", 0, setipv6cp_use_ip}, /* Use IPv4 addr as iface id */
+#if defined(SOL2)
+ {"ipv6cp-use-persistent", 0, setipv6cp_use_persistent}, /* Use uniquely-available persistent value for link local addr */
+#endif
+ {"ipv6cp-restart", 1, setipv6cptimeout}, /* Set timeout for IPv6CP */
+ {"ipv6cp-max-terminate", 1, setipv6cpterm}, /* max #xmits for term-reqs */
+ {"ipv6cp-max-configure", 1, setipv6cpconf}, /* max #xmits for conf-reqs */
+ {"ipv6cp-max-failure", 1, setipv6cpfails}, /* max #conf-naks for IPv6CP */
+#endif
+
#ifdef IPX_CHANGE
{"ipx-network", 1, setipxnetwork}, /* IPX network number */
{"ipxcp-accept-network", 0, setipxanet}, /* Accept peer netowrk */
@@ -2374,6 +2408,85 @@ setwinsaddr(argv)
return (1);
}
+#ifdef INET6
+static int
+setipv6cp_accept_local(argv)
+ char **argv;
+{
+ ipv6cp_allowoptions[0].accept_local = 1;
+ return 1;
+}
+
+static int
+setipv6cp_use_ip(argv)
+ char **argv;
+{
+ ipv6cp_allowoptions[0].use_ip = 1;
+ return 1;
+}
+
+#if defined(SOL2)
+static int
+setipv6cp_use_persistent(argv)
+ char **argv;
+{
+ ipv6cp_wantoptions[0].use_persistent = 1;
+ return 1;
+}
+#endif
+
+static int
+setipv6cptimeout(argv)
+ char **argv;
+{
+ return int_option(*argv, &ipv6cp_fsm[0].timeouttime);
+}
+
+static int
+setipv6cpterm(argv)
+ char **argv;
+{
+ return int_option(*argv, &ipv6cp_fsm[0].maxtermtransmits);
+}
+
+static int
+setipv6cpconf(argv)
+ char **argv;
+{
+ return int_option(*argv, &ipv6cp_fsm[0].maxconfreqtransmits);
+}
+
+static int
+setipv6cpfails(argv)
+ char **argv;
+{
+ return int_option(*argv, &ipv6cp_fsm[0].maxnakloops);
+}
+
+static int
+setipv6proto(argv)
+ char **argv;
+{
+ ipv6cp_protent.enabled_flag = 1;
+ return 1;
+}
+
+static int
+resetipv6proto(argv)
+ char **argv;
+{
+ ipv6cp_protent.enabled_flag = 0;
+ return 1;
+}
+#else
+static int
+resetipv6proto(argv)
+ char **argv;
+{
+ return 1;
+}
+#endif /* INET6 */
+
#ifdef IPX_CHANGE
static int
setipxrouter (argv)
diff --git a/usr.sbin/pppd/pathnames.h b/usr.sbin/pppd/pathnames.h
index 147ae38ab40f..5d09b0b2fa18 100644
--- a/usr.sbin/pppd/pathnames.h
+++ b/usr.sbin/pppd/pathnames.h
@@ -26,6 +26,11 @@
#define _PATH_PPPDENY "/etc/ppp/ppp.deny"
#define _PATH_PPPSHELLS "/etc/ppp/ppp.shells"
+#ifdef INET6
+#define _PATH_IPV6UP "/etc/ppp/ipv6-up"
+#define _PATH_IPV6DOWN "/etc/ppp/ipv6-down"
+#endif
+
#ifdef IPX_CHANGE
#define _PATH_IPXUP "/etc/ppp/ipx-up"
#define _PATH_IPXDOWN "/etc/ppp/ipx-down"
diff --git a/usr.sbin/pppd/pppd.8 b/usr.sbin/pppd/pppd.8
index 6becff62cdfa..ba55f2119d1f 100644
--- a/usr.sbin/pppd/pppd.8
+++ b/usr.sbin/pppd/pppd.8
@@ -142,13 +142,14 @@ Pppd
will ask the peer to send packets of no more than \fIn\fR bytes. The
minimum MRU value is 128. The default MRU value is 1500. A value of
296 is recommended for slow links (40 bytes for TCP/IP header + 256
-bytes of data).
+bytes of data). (Note that for IPv6 MRU must be at least 1280)
.TP
.B mtu \fIn
Set the MTU [Maximum Transmit Unit] value to \fIn\fR. Unless the
peer requests a smaller value via MRU negotiation, pppd will
request that the kernel networking code send data packets of no more
-than \fIn\fR bytes through the PPP network interface.
+than \fIn\fR bytes through the PPP network interface. (Note that for
+IPv6 MTU must be at least 1280)
.TP
.B passive
Enables the "passive" option in the LCP. With this option, pppd will
@@ -171,6 +172,17 @@ will not accept a different value from the peer in the IPCP
negotiation, unless the \fIipcp-accept-local\fR and/or
\fIipcp-accept-remote\fR options are given, respectively.
.TP
+.B ipv6 \fI<local_interface_identifier>\fR,\fI<remote_interface_identifier>
+Set the local and/or remote 64-bit interface identifier. Either one may be
+omitted. The identifier must be specified in standard ascii notation of
+IPv6 addresses (e.g. ::dead:beef). If the
+\fIipv6cp-use-ipaddr\fR
+option is given, the local identifier is the local IPv4 address (see above).
+On systems which supports a unique persistent id, such as EUI-48 derived
+from the Ethernet MAC address, \fIipv6cp-use-persistent\fR option can be
+used to replace the \fIipv6 <local>,<remote>\fR option. Otherwise the
+identifier is randomized.
+.TP
.B bsdcomp \fInr,nt
Request that the peer compress packets that it sends, using the
BSD-Compress scheme, with a maximum code size of \fInr\fR bits, and
@@ -300,6 +312,22 @@ Provides an extra parameter to the ip-up and ip-down scripts. If this
option is given, the \fIstring\fR supplied is given as the 6th
parameter to those scripts.
.TP
+.B ipv6cp-max-configure \fIn
+Set the maximum number of IPv6CP configure-request transmissions to
+\fIn\fR (default 10).
+.TP
+.B ipv6cp-max-failure \fIn
+Set the maximum number of IPv6CP configure-NAKs returned before starting
+to send configure-Rejects instead to \fIn\fR (default 10).
+.TP
+.B ipv6cp-max-terminate \fIn
+Set the maximum number of IPv6CP terminate-request transmissions to
+\fIn\fR (default 3).
+.TP
+.B ipv6cp-restart \fIn
+Set the IPv6CP restart interval (retransmission timeout) to \fIn\fR
+seconds (default 3).
+.TP
.B ipx
Enable the IPXCP and IPX protocols. This option is presently only
supported under Linux, and only if your kernel has been configured to
@@ -526,6 +554,11 @@ Disable IPCP negotiation and IP communication. This option should
only be required if the peer is buggy and gets confused by requests
from pppd for IPCP negotiation.
.TP
+.B noipv6
+Disable IPv6CP negotiation and IPv6 communication. This option should
+only be required if the peer is buggy and gets confused by requests
+from pppd for IPv6CP negotiation.
+.TP
.B noipdefault
Disables the default behaviour when no local IP address is specified,
which is to determine (if possible) the local IP address from the
@@ -1063,6 +1096,18 @@ used for undoing the effects of the /etc/ppp/ip-up script. It is
invoked in the same manner and with the same parameters as the ip-up
script.
.TP
+.B /etc/ppp/ipv6-up
+Like /etc/ppp/ip-up, except that it is executed when the link is available
+for sending and receiving IPv6 packets. It is executed with the parameters
+.IP
+\fIinterface-name tty-device speed local-link-local-address
+remote-link-local-address ipparam\fR
+.TP
+.B /etc/ppp/ipv6-down
+Similar to /etc/ppp/ip-down, but it is executed when IPv6 packets can no
+longer be transmitted on the link. It is executed with the same parameters
+as the ipv6-up script.
+.TP
.B /etc/ppp/ipx-up
A program or script which is executed when the link is available for
sending and receiving IPX packets (that is, IPXCP has come up). It is
diff --git a/usr.sbin/pppd/pppd.h b/usr.sbin/pppd/pppd.h
index 248556d381e8..48e2eb01eacc 100644
--- a/usr.sbin/pppd/pppd.h
+++ b/usr.sbin/pppd/pppd.h
@@ -41,6 +41,10 @@
#define const
#endif
+#ifdef INET6
+#include "eui64.h"
+#endif
+
/*
* Limits.
*/
@@ -285,6 +289,12 @@ int sifaddr __P((int, u_int32_t, u_int32_t, u_int32_t));
/* Configure IP addresses for i/f */
int cifaddr __P((int, u_int32_t, u_int32_t));
/* Reset i/f IP addresses */
+#ifdef INET6
+int sif6addr __P((int, eui64_t, eui64_t));
+ /* Configure IPv6 addresses for i/f */
+int cif6addr __P((int, eui64_t, eui64_t));
+ /* Remove an IPv6 address from i/f */
+#endif
int sifdefaultroute __P((int, u_int32_t, u_int32_t));
/* Create default route through i/f */
int cifdefaultroute __P((int, u_int32_t, u_int32_t));
@@ -457,6 +467,12 @@ extern struct option_info devnam_info;
#define IPCPDEBUG(x)
#endif
+#ifdef DEBUGIPV6CP
+#define IPV6CPDEBUG(x) if (debug) syslog x
+#else
+#define IPV6CPDEBUG(x)
+#endif
+
#ifdef DEBUGUPAP
#define UPAPDEBUG(x) if (debug) syslog x
#else
diff --git a/usr.sbin/pppd/sys-bsd.c b/usr.sbin/pppd/sys-bsd.c
index 3ca43c0cb2ed..ccb13c8cc001 100644
--- a/usr.sbin/pppd/sys-bsd.c
+++ b/usr.sbin/pppd/sys-bsd.c
@@ -58,6 +58,10 @@ static char rcsid[] = "$FreeBSD$";
#include <net/route.h>
#include <net/if_dl.h>
#include <netinet/in.h>
+#include <net/if_var.h>
+#include <netinet6/in6_var.h>
+#include <netinet6/nd6.h>
+#include <ifaddrs.h>
#ifdef IPX_CHANGE
#include <netipx/ipx.h>
@@ -100,6 +104,9 @@ static char loop_name[20];
static unsigned char inbuf[512]; /* buffer for chars read from loopback */
static int sockfd; /* socket for doing interface ioctls */
+#ifdef INET6
+static int sock6_fd = -1; /* socket for doing ipv6 interface ioctls */
+#endif /* INET6 */
static int if_is_up; /* the interface is currently up */
static u_int32_t ifaddrs[2]; /* local and remote addresses we set */
@@ -122,6 +129,13 @@ sys_init()
syslog(LOG_ERR, "Couldn't create IP socket: %m");
die(1);
}
+
+#ifdef INET6
+ if ((sock6_fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+ /* check it at runtime */
+ sock6_fd = -1;
+ }
+#endif
}
/*
@@ -156,7 +170,12 @@ sys_cleanup()
void
sys_close()
{
- close(sockfd);
+ if (sockfd >= 0)
+ close(sockfd);
+#ifdef INET6
+ if (sock6_fd >= 0)
+ close(sock6_fd);
+#endif
if (loop_slave >= 0) {
close(loop_slave);
close(loop_master);
@@ -476,6 +495,115 @@ int fd, on;
ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);
}
+#ifdef INET6
+/*
+ * sif6addr - Config the interface with an IPv6 link-local address
+ */
+int
+sif6addr(int unit, eui64_t our_eui64, eui64_t his_eui64)
+{
+ int ifindex;
+ struct in6_aliasreq addreq6;
+
+ if (sock6_fd < 0) {
+ syslog(LOG_ERR, "No IPv6 socket available");
+ die(1);
+ /*NOTREACHED*/
+ }
+
+ /* actually, this part is not kame local - RFC2553 conformant */
+ ifindex = if_nametoindex(ifname);
+ if (ifindex == 0) {
+ syslog(LOG_ERR, "sifaddr6: no interface %s", ifname);
+ return 0;
+ }
+
+ memset(&addreq6, 0, sizeof(addreq6));
+ strlcpy(addreq6.ifra_name, ifname, sizeof(addreq6.ifra_name));
+
+ /* my addr */
+ addreq6.ifra_addr.sin6_family = AF_INET6;
+ addreq6.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
+ addreq6.ifra_addr.sin6_addr.s6_addr[0] = 0xfe;
+ addreq6.ifra_addr.sin6_addr.s6_addr[1] = 0x80;
+ memcpy(&addreq6.ifra_addr.sin6_addr.s6_addr[8], &our_eui64,
+ sizeof(our_eui64));
+ /* KAME ifindex hack */
+ *(u_int16_t *)&addreq6.ifra_addr.sin6_addr.s6_addr[2] = htons(ifindex);
+
+ /* his addr */
+ addreq6.ifra_dstaddr.sin6_family = AF_INET6;
+ addreq6.ifra_dstaddr.sin6_len = sizeof(struct sockaddr_in6);
+ addreq6.ifra_dstaddr.sin6_addr.s6_addr[0] = 0xfe;
+ addreq6.ifra_dstaddr.sin6_addr.s6_addr[1] = 0x80;
+ memcpy(&addreq6.ifra_dstaddr.sin6_addr.s6_addr[8], &his_eui64,
+ sizeof(our_eui64));
+ /* KAME ifindex hack */
+ *(u_int16_t *)&addreq6.ifra_dstaddr.sin6_addr.s6_addr[2] = htons(ifindex);
+
+ /* prefix mask: 128bit */
+ addreq6.ifra_prefixmask.sin6_family = AF_INET6;
+ addreq6.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
+ memset(&addreq6.ifra_prefixmask.sin6_addr, 0xff,
+ sizeof(addreq6.ifra_prefixmask.sin6_addr));
+
+ /* address lifetime (infty) */
+ addreq6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
+ addreq6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
+
+ if (ioctl(sock6_fd, SIOCAIFADDR_IN6, &addreq6) < 0) {
+ syslog(LOG_ERR, "sif6addr: ioctl(SIOCAIFADDR_IN6): %m");
+ return 0;
+ }
+
+ return 1;
+}
+
+
+/*
+ * cif6addr - Remove IPv6 address from interface
+ */
+int
+cif6addr(int unit, eui64_t our_eui64, eui64_t his_eui64)
+{
+ int ifindex;
+ struct in6_ifreq delreq6;
+
+ if (sock6_fd < 0) {
+ syslog(LOG_ERR, "No IPv6 socket available");
+ die(1);
+ /*NOTREACHED*/
+ }
+
+ /* actually, this part is not kame local - RFC2553 conformant */
+ ifindex = if_nametoindex(ifname);
+ if (ifindex == 0) {
+ syslog(LOG_ERR, "cifaddr6: no interface %s", ifname);
+ return 0;
+ }
+
+ memset(&delreq6, 0, sizeof(delreq6));
+ strlcpy(delreq6.ifr_name, ifname, sizeof(delreq6.ifr_name));
+
+ /* my addr */
+ delreq6.ifr_ifru.ifru_addr.sin6_family = AF_INET6;
+ delreq6.ifr_ifru.ifru_addr.sin6_len = sizeof(struct sockaddr_in6);
+ delreq6.ifr_ifru.ifru_addr.sin6_addr.s6_addr[0] = 0xfe;
+ delreq6.ifr_ifru.ifru_addr.sin6_addr.s6_addr[1] = 0x80;
+ memcpy(&delreq6.ifr_ifru.ifru_addr.sin6_addr.s6_addr[8], &our_eui64,
+ sizeof(our_eui64));
+ /* KAME ifindex hack */
+ *(u_int16_t *)&delreq6.ifr_ifru.ifru_addr.sin6_addr.s6_addr[2] =
+ htons(ifindex);
+
+ if (ioctl(sock6_fd, SIOCDIFADDR_IN6, &delreq6) < 0) {
+ syslog(LOG_ERR, "cif6addr: ioctl(SIOCDIFADDR_IN6): %m");
+ return 0;
+ }
+
+ return 1;
+}
+#endif /* INET6 */
/*
* open_ppp_loopback - open the device we use for getting