summaryrefslogtreecommitdiffstats
path: root/usr.sbin/pppd/sys-bsd.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/pppd/sys-bsd.c')
-rw-r--r--usr.sbin/pppd/sys-bsd.c130
1 files changed, 129 insertions, 1 deletions
diff --git a/usr.sbin/pppd/sys-bsd.c b/usr.sbin/pppd/sys-bsd.c
index 3ca43c0..ccb13c8 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
OpenPOWER on IntegriCloud