+/********************************************************************
+ *
+ * open_loopback - open the device we use for getting packets
+ * in demand mode. Under Linux, we use a pty master/slave pair.
+ */
+int
+open_ppp_loopback(void)
+{
+ int flags;
+
+ looped = 1;
+ if (new_style_driver) {
+ /* allocate ourselves a ppp unit */
+ if (make_ppp_unit() < 0)
+ die(1);
+ set_flags(ppp_dev_fd, SC_LOOP_TRAFFIC);
+ set_kdebugflag(kdebugflag);
+ ppp_fd = -1;
+ return ppp_dev_fd;
+ }
+
+ if (!get_pty(&master_fd, &slave_fd, loop_name, 0))
+ fatal("No free pty for loopback");
+ SYSDEBUG(("using %s for loopback", loop_name));
+
+ set_ppp_fd(slave_fd);
+
+ flags = fcntl(master_fd, F_GETFL);
+ if (flags == -1 ||
+ fcntl(master_fd, F_SETFL, flags | O_NONBLOCK) == -1)
+ warn("couldn't set master loopback to nonblock: %m(%d)", errno);
+
+ flags = fcntl(ppp_fd, F_GETFL);
+ if (flags == -1 ||
+ fcntl(ppp_fd, F_SETFL, flags | O_NONBLOCK) == -1)
+ warn("couldn't set slave loopback to nonblock: %m(%d)", errno);
+
+ if (ioctl(ppp_fd, TIOCSETD, &ppp_disc) < 0)
+ fatal("ioctl(TIOCSETD): %m(%d)", errno);
+/*
+ * Find out which interface we were given.
+ */
+ if (ioctl(ppp_fd, PPPIOCGUNIT, &ifunit) < 0)
+ fatal("ioctl(PPPIOCGUNIT): %m(%d)", errno);
+/*
+ * Enable debug in the driver if requested.
+ */
+ set_kdebugflag (kdebugflag);
+
+ return master_fd;
+}
+
+/********************************************************************
+ *
+ * restore_loop - reattach the ppp unit to the loopback.
+ *
+ * The kernel ppp driver automatically reattaches the ppp unit to
+ * the loopback if the serial port is set to a line discipline other
+ * than ppp, or if it detects a modem hangup. The former will happen
+ * in disestablish_ppp if the latter hasn't already happened, so we
+ * shouldn't need to do anything.
+ *
+ * Just to be sure, set the real serial port to the normal discipline.
+ */
+
+void
+restore_loop(void)
+{
+ looped = 1;
+ if (new_style_driver) {
+ set_flags(ppp_dev_fd, get_flags(ppp_dev_fd) | SC_LOOP_TRAFFIC);
+ return;
+ }
+ if (ppp_fd != slave_fd) {
+ (void) ioctl(ppp_fd, TIOCSETD, &tty_disc);
+ set_ppp_fd(slave_fd);
+ }
+}
+
+/********************************************************************
+ *
+ * sifnpmode - Set the mode for handling packets for a given NP.
+ */
+
+int
+sifnpmode(u, proto, mode)
+ int u;
+ int proto;
+ enum NPmode mode;
+{
+ struct npioctl npi;
+
+ npi.protocol = proto;
+ npi.mode = mode;
+ if (ioctl(ppp_dev_fd, PPPIOCSNPMODE, (caddr_t) &npi) < 0) {
+ if (! ok_error (errno))
+ error("ioctl(PPPIOCSNPMODE, %d, %d): %m (%d)",
+ proto, mode, errno);
+ return 0;
+ }
+ return 1;
+}
+
+\f
+/********************************************************************
+ *
+ * sipxfaddr - Config the interface IPX networknumber
+ */
+
+int sipxfaddr (int unit, unsigned long int network, unsigned char * node )
+{
+ int result = 1;
+
+#ifdef IPX_CHANGE
+ int skfd;
+ struct ifreq ifr;
+ struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &ifr.ifr_addr;
+
+ skfd = socket (AF_IPX, SOCK_DGRAM, 0);
+ if (skfd < 0) {
+ if (! ok_error (errno))
+ dbglog("socket(AF_IPX): %m (%d)", errno);
+ result = 0;
+ }
+ else {
+ memset (&ifr, '\0', sizeof (ifr));
+ strlcpy (ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+
+ memcpy (sipx->sipx_node, node, IPX_NODE_LEN);
+ sipx->sipx_family = AF_IPX;
+ sipx->sipx_port = 0;
+ sipx->sipx_network = htonl (network);
+ sipx->sipx_type = IPX_FRAME_ETHERII;
+ sipx->sipx_action = IPX_CRTITF;
+/*
+ * Set the IPX device
+ */
+ if (ioctl(skfd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
+ result = 0;
+ if (errno != EEXIST) {
+ if (! ok_error (errno))
+ dbglog("ioctl(SIOCSIFADDR, CRTITF): %m (%d)", errno);
+ }
+ else {
+ warn("ioctl(SIOCSIFADDR, CRTITF): Address already exists");
+ }
+ }
+ close (skfd);
+ }
+#endif
+ return result;
+}
+
+/********************************************************************
+ *
+ * cipxfaddr - Clear the information for the IPX network. The IPX routes
+ * are removed and the device is no longer able to pass IPX
+ * frames.
+ */
+
+int cipxfaddr (int unit)
+{
+ int result = 1;
+
+#ifdef IPX_CHANGE
+ int skfd;
+ struct ifreq ifr;
+ struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &ifr.ifr_addr;
+
+ skfd = socket (AF_IPX, SOCK_DGRAM, 0);
+ if (skfd < 0) {
+ if (! ok_error (errno))
+ dbglog("socket(AF_IPX): %m (%d)", errno);
+ result = 0;
+ }
+ else {
+ memset (&ifr, '\0', sizeof (ifr));
+ strlcpy (ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+
+ sipx->sipx_type = IPX_FRAME_ETHERII;
+ sipx->sipx_action = IPX_DLTITF;
+ sipx->sipx_family = AF_IPX;
+/*
+ * Set the IPX device
+ */
+ if (ioctl(skfd, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
+ if (! ok_error (errno))
+ info("ioctl(SIOCSIFADDR, IPX_DLTITF): %m (%d)", errno);
+ result = 0;
+ }
+ close (skfd);
+ }
+#endif
+ return result;