+#if defined(INET6)
+ close(i6fd);
+#endif /* defined(INET6) */
+ fatal("Can't I_PLINK PPP device to IP: %m");
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+ sprintf(ifr.ifr_name, "%s", ifname);
+ ifr.ifr_ip_muxid = ipmuxid;
+
+ /*
+ * In Sol 8 and later, STREAMS dynamic module plumbing feature exists.
+ * This is so that an arbitrary module can be inserted, or deleted,
+ * between ip module and the device driver without tearing down the
+ * existing stream. Such feature requires the mux ids, which is set
+ * by SIOCSIFMUXID (or SIOCLSIFMUXID).
+ */
+ if (ioctl(ipfd, SIOCSIFMUXID, &ifr) < 0) {
+ ioctl(ipfd, I_PUNLINK, ipmuxid);
+#if defined(INET6)
+ close(i6fd);
+#endif /* defined(INET6) */
+ fatal("SIOCSIFMUXID: %m");
+ }
+
+#else /* else if !defined(SOL2) */
+
+ if (dlpi_attach(ifd, ifunit) < 0 ||
+ dlpi_get_reply(ifd, &reply.prim, DL_OK_ACK, sizeof(reply)) < 0) {
+ close(ifd);
+ fatal("Can't attach to ppp%d: %m", ifunit);
+ }
+
+ ipmuxid = ioctl(ipfd, I_LINK, ifd);
+ close(ifd);
+ if (ipmuxid < 0)
+ fatal("Can't link PPP device to IP: %m");
+#endif /* defined(SOL2) */
+
+#if defined(INET6) && defined(SOL2)
+ ip6muxid = ioctl(ip6fd, I_PLINK, i6fd);
+ close(i6fd);
+ if (ip6muxid < 0) {
+ ioctl(ipfd, I_PUNLINK, ipmuxid);
+ fatal("Can't I_PLINK PPP device to IP (2): %m");
+ }
+
+ memset(&lifr, 0, sizeof(lifr));
+ sprintf(lifr.lifr_name, "%s", ifname);
+ lifr.lifr_ip_muxid = ip6muxid;
+
+ /*
+ * Let IP know of the mux id [see comment for SIOCSIFMUXID above]
+ */
+ if (ioctl(ip6fd, SIOCSLIFMUXID, &lifr) < 0) {
+ ioctl(ipfd, I_PUNLINK, ipmuxid);
+ ioctl(ip6fd, I_PUNLINK, ip6muxid);
+ fatal("Can't link PPP device to IP (2): %m");
+ }
+#endif /* defined(INET6) && defined(SOL2) */
+
+#if !defined(SOL2)
+ /* Set the interface name for the link. */
+ slprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "ppp%d", ifunit);
+ ifr.ifr_metric = ipmuxid;
+ if (strioctl(ipfd, SIOCSIFNAME, (char *)&ifr, sizeof ifr, 0) < 0)
+ fatal("Can't set interface name %s: %m", ifr.ifr_name);
+#endif /* !defined(SOL2) */
+
+ n_pollfds = 0;
+}
+
+/*
+ * sys_cleanup - restore any system state we modified before exiting:
+ * mark the interface down, delete default route and/or proxy arp entry.
+ * This should call die() because it's called from die().
+ */
+void
+sys_cleanup()
+{
+#if defined(SOL2)
+ struct ifreq ifr;
+#if defined(INET6)
+ struct lifreq lifr;
+#endif /* defined(INET6) */
+#endif /* defined(SOL2) */
+
+#if defined(SOL2) && defined(INET6)
+ if (if6_is_up)
+ sif6down(0);
+#endif /* defined(SOL2) && defined(INET6) */
+ if (if_is_up)
+ sifdown(0);
+ if (default_route_gateway)
+ cifdefaultroute(0, default_route_gateway, default_route_gateway);
+ if (proxy_arp_addr)
+ cifproxyarp(0, proxy_arp_addr);
+#if defined(SOL2)
+ /*
+ * Make sure we ask ip what the muxid, because 'ifconfig modlist' will
+ * unlink and re-link the modules, causing the muxid to change.
+ */
+ memset(&ifr, 0, sizeof(ifr));
+ sprintf(ifr.ifr_name, "%s", ifname);
+ if (ioctl(ipfd, SIOCGIFFLAGS, &ifr) < 0) {
+ error("SIOCGIFFLAGS: %m");
+ return;
+ }
+
+ if (ioctl(ipfd, SIOCGIFMUXID, &ifr) < 0) {
+ error("SIOCGIFMUXID: %m");
+ return;
+ }
+
+ ipmuxid = ifr.ifr_ip_muxid;
+
+ if (ioctl(ipfd, I_PUNLINK, ipmuxid) < 0) {
+ error("Can't I_PUNLINK PPP from IP: %m");
+ return;
+ }
+#if defined(INET6)
+ /*
+ * Make sure we ask ip what the muxid, because 'ifconfig modlist' will
+ * unlink and re-link the modules, causing the muxid to change.
+ */
+ memset(&lifr, 0, sizeof(lifr));
+ sprintf(lifr.lifr_name, "%s", ifname);
+ if (ioctl(ip6fd, SIOCGLIFFLAGS, &lifr) < 0) {
+ error("SIOCGLIFFLAGS: %m");
+ return;
+ }
+
+ if (ioctl(ip6fd, SIOCGLIFMUXID, &lifr) < 0) {
+ error("SIOCGLIFMUXID: %m");
+ return;
+ }
+
+ ip6muxid = lifr.lifr_ip_muxid;
+
+ if (ioctl(ip6fd, I_PUNLINK, ip6muxid) < 0) {
+ error("Can't I_PUNLINK PPP from IP (2): %m");
+ }
+#endif /* defined(INET6) */
+#endif /* defined(SOL2) */
+}
+
+/*
+ * sys_close - Clean up in a child process before execing.
+ */
+void
+sys_close()
+{
+ close(ipfd);
+#if defined(INET6) && defined(SOL2)
+ close(ip6fd);
+#endif /* defined(INET6) && defined(SOL2) */
+ if (pppfd >= 0)
+ close(pppfd);
+}
+
+/*
+ * sys_check_options - check the options that the user specified
+ */
+int
+sys_check_options()
+{
+ return 1;
+}
+
+#if 0
+/*
+ * daemon - Detach us from controlling terminal session.
+ */
+int
+daemon(nochdir, noclose)
+ int nochdir, noclose;
+{
+ int pid;
+
+ if ((pid = fork()) < 0)
+ return -1;
+ if (pid != 0)
+ exit(0); /* parent dies */
+ setsid();
+ if (!nochdir)
+ chdir("/");
+ if (!noclose) {
+ fclose(stdin); /* don't need stdin, stdout, stderr */
+ fclose(stdout);
+ fclose(stderr);
+ }
+ return 0;
+}
+#endif
+
+/*
+ * ppp_available - check whether the system has any ppp interfaces
+ */
+int
+ppp_available()
+{
+ struct stat buf;
+
+ 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;