diff -ur ppp-2.3.11-clean/include/linux/if_ppp.h ppp-2.3.11/include/linux/if_ppp.h --- ppp-2.3.11-clean/include/linux/if_ppp.h Fri Jul 23 06:53:29 1999 +++ ppp-2.3.11/include/linux/if_ppp.h Sun Jan 16 19:03:37 2000 @@ -104,6 +104,12 @@ struct ppp_comp_stats stats; }; +/* For PPPIOCATTACHENCAPS */ +struct ifppp_unit_encaps { + int unit; + int encaps; +}; + #define ifr__name b.ifr_ifrn.ifrn_name #define stats_ptr b.ifr_ifru.ifru_data @@ -132,6 +138,7 @@ #define PPPIOCGIDLE _IOR('t', 63, struct ppp_idle) /* get idle time */ #define PPPIOCNEWUNIT _IOWR('t', 62, int) /* create new ppp unit */ #define PPPIOCATTACH _IOW('t', 61, int) /* attach to ppp unit */ +#define PPPIOCATTACHENCAPS _IOW('t', 91, struct ifppp_unit_encaps) #define PPPIOCDETACH _IOW('t', 60, int) /* detach from ppp unit */ #define SIOCGPPPSTATS (SIOCDEVPRIVATE + 0) diff -ur ppp-2.3.11-clean/pppd/main.c ppp-2.3.11/pppd/main.c --- ppp-2.3.11-clean/pppd/main.c Thu Dec 23 02:12:31 1999 +++ ppp-2.3.11/pppd/main.c Sun Jan 16 18:57:43 2000 @@ -40,7 +40,7 @@ #include #include #include - +#include #include "pppd.h" #include "magic.h" #include "fsm.h" @@ -368,7 +368,7 @@ modem = 0; if (notty && log_to_fd <= 1) log_to_fd = -1; - } else { + } else if (!pppoa) { /* * If the user has specified a device which is the same as * the one on stdin, pretend they didn't specify any. @@ -612,51 +612,55 @@ kill_link = 0; connector = doing_callback? callback_script: connect_script; if (devnam[0] != 0) { - for (;;) { - /* If the user specified the device name, become the - user before opening it. */ - int err; - if (!devnam_info.priv && !privopen) - seteuid(uid); - ttyfd = open(devnam, O_NONBLOCK | O_RDWR, 0); - err = errno; - if (!devnam_info.priv && !privopen) - seteuid(0); - if (ttyfd >= 0) - break; - errno = err; - if (err != EINTR) { - error("Failed to open %s: %m", devnam); - status = EXIT_OPEN_FAILED; + if (pppoa) { + ttyfd = connect_pppoa(devnam); + } else { + for (;;) { + /* If the user specified the device name, become the + user before opening it. */ + int err; + if (!devnam_info.priv && !privopen) + seteuid(uid); + ttyfd = open(devnam, O_NONBLOCK | O_RDWR, 0); + err = errno; + if (!devnam_info.priv && !privopen) + seteuid(0); + if (ttyfd >= 0) + break; + errno = err; + if (err != EINTR) { + error("Failed to open %s: %m", devnam); + status = EXIT_OPEN_FAILED; + } + if (!persist || err != EINTR) + goto fail; } - if (!persist || err != EINTR) - goto fail; + if ((fdflags = fcntl(ttyfd, F_GETFL)) == -1 + || fcntl(ttyfd, F_SETFL, fdflags & ~O_NONBLOCK) < 0) + warn("Couldn't reset non-blocking mode on device: %m"); + + /* + * Do the equivalent of `mesg n' to stop broadcast messages. + */ + if (fstat(ttyfd, &statbuf) < 0 + || fchmod(ttyfd, statbuf.st_mode & ~(S_IWGRP | S_IWOTH)) < 0) { + warn("Couldn't restrict write permissions to %s: %m", devnam); + } else + tty_mode = statbuf.st_mode; + + /* + * Set line speed, flow control, etc. + * If we have a non-null connection or initializer script, + * on most systems we set CLOCAL for now so that we can talk + * to the modem before carrier comes up. But this has the + * side effect that we might miss it if CD drops before we + * get to clear CLOCAL below. On systems where we can talk + * successfully to the modem with CLOCAL clear and CD down, + * we could clear CLOCAL at this point. + */ + set_up_tty(ttyfd, ((connector != NULL && connector[0] != 0) + || initializer != NULL)); } - if ((fdflags = fcntl(ttyfd, F_GETFL)) == -1 - || fcntl(ttyfd, F_SETFL, fdflags & ~O_NONBLOCK) < 0) - warn("Couldn't reset non-blocking mode on device: %m"); - - /* - * Do the equivalent of `mesg n' to stop broadcast messages. - */ - if (fstat(ttyfd, &statbuf) < 0 - || fchmod(ttyfd, statbuf.st_mode & ~(S_IWGRP | S_IWOTH)) < 0) { - warn("Couldn't restrict write permissions to %s: %m", devnam); - } else - tty_mode = statbuf.st_mode; - - /* - * Set line speed, flow control, etc. - * If we have a non-null connection or initializer script, - * on most systems we set CLOCAL for now so that we can talk - * to the modem before carrier comes up. But this has the - * side effect that we might miss it if CD drops before we - * get to clear CLOCAL below. On systems where we can talk - * successfully to the modem with CLOCAL clear and CD down, - * we could clear CLOCAL at this point. - */ - set_up_tty(ttyfd, ((connector != NULL && connector[0] != 0) - || initializer != NULL)); real_ttyfd = ttyfd; } @@ -737,20 +741,21 @@ if (doing_callback == CALLBACK_DIALIN) connector = NULL; } - - /* reopen tty if necessary to wait for carrier */ - if (connector == NULL && modem && devnam[0] != 0) { - for (;;) { - if ((i = open(devnam, O_RDWR)) >= 0) - break; - if (errno != EINTR) { - error("Failed to reopen %s: %m", devnam); - status = EXIT_OPEN_FAILED; + if (!pppoa) { + /* reopen tty if necessary to wait for carrier */ + if (connector == NULL && modem && devnam[0] != 0) { + for (;;) { + if ((i = open(devnam, O_RDWR)) >= 0) + break; + if (errno != EINTR) { + error("Failed to reopen %s: %m", devnam); + status = EXIT_OPEN_FAILED; + } + if (!persist || errno != EINTR || hungup || kill_link) + goto fail; } - if (!persist || errno != EINTR || hungup || kill_link) - goto fail; + close(i); } - close(i); } slprintf(numbuf, sizeof(numbuf), "%d", baud_rate); diff -ur ppp-2.3.11-clean/pppd/options.c ppp-2.3.11/pppd/options.c --- ppp-2.3.11-clean/pppd/options.c Thu Dec 23 01:28:52 1999 +++ ppp-2.3.11/pppd/options.c Sun Jan 16 18:55:14 2000 @@ -101,6 +101,10 @@ char linkname[MAXPATHLEN]; /* logical name for link */ bool tune_kernel; /* may alter kernel settings */ int connect_delay = 1000; /* wait this many ms after connect script */ +bool pppoa = 0; /* enable PPPoATM */ +int pppoa_accept = 0; /* accept an incoming PPPoATM connection */ +int vci = 101; /* PPPoATM VCI */ +bool llc_encaps = 0; /* use LLC encaps instead of VCMUX */ extern option_t auth_options[]; extern struct stat devstat; @@ -283,6 +287,12 @@ { "active-filter", 1, setactivefilter, "set filter for active pkts" }, #endif + { "pppoa_accept", o_bool, &pppoa_accept, + "set PPPoATM socket to accept incoming connection", 1 }, + { "vci", o_int, &vci, + "vci to use for PPPoATM" }, + { "llc-encaps", o_bool, &llc_encaps, + "use LLC encapsulation instead of VC multiplexing for PPPoATM", }, { NULL } }; @@ -1347,6 +1357,19 @@ if (*cp == 0) return 0; + + /* + * This just has to look like an ATM device. + */ + if ((strncmp("atm", cp, 3) == 0) && strncmp("ppp", cp, 3)) { + strlcpy(devnam, cp, sizeof(devnam)); + default_device = 0; + pppoa = 1; + using_pty = 0; + connect_script = NULL; + disconnect_script = NULL; + return 1; + } if (strncmp("/dev/", cp, 5) != 0) { strlcpy(dev, "/dev/", sizeof(dev)); diff -ur ppp-2.3.11-clean/pppd/pppd.h ppp-2.3.11/pppd/pppd.h --- ppp-2.3.11-clean/pppd/pppd.h Thu Dec 23 01:29:42 1999 +++ ppp-2.3.11/pppd/pppd.h Sun Jan 16 18:58:59 2000 @@ -32,6 +32,7 @@ #include /* for u_int32_t, if defined */ #include /* for struct timeval */ #include +#include #if defined(__STDC__) #include @@ -216,6 +217,11 @@ extern bool tune_kernel; /* May alter kernel settings as necessary */ extern int connect_delay; /* Time to delay after connect script */ +extern bool pppoa; /* enable PPPoATM */ +extern int pppoa_accept; /* accept an incoming pppd connection */ +extern int vci; /* PPPoATM VCI */ +extern bool llc_encaps; /* use LLC encaps instead of VCMUX */ + #ifdef PPP_FILTER extern struct bpf_program pass_filter; /* Filter for pkts to pass */ extern struct bpf_program active_filter; /* Filter for link-active pkts */ @@ -458,6 +464,9 @@ int int_option __P((char *, int *)); /* Simplified number_option for decimal ints */ void add_options __P((option_t *)); /* Add extra options */ + + +int connect_pppoa __P((char *devname)); /* * This structure is used to store information about certain diff -ur ppp-2.3.11-clean/pppd/sys-NeXT.c ppp-2.3.11/pppd/sys-NeXT.c --- ppp-2.3.11-clean/pppd/sys-NeXT.c Tue Aug 24 05:25:54 1999 +++ ppp-2.3.11/pppd/sys-NeXT.c Sun Jan 16 18:50:00 2000 @@ -1689,3 +1689,8 @@ fatal("select: %m"); } #endif + +int connect_pppoa(char *host_dev) +{ + fatal("PPPoATM is not supported on this architecture"); +} diff -ur ppp-2.3.11-clean/pppd/sys-bsd.c ppp-2.3.11/pppd/sys-bsd.c --- ppp-2.3.11-clean/pppd/sys-bsd.c Tue Aug 24 05:25:54 1999 +++ ppp-2.3.11/pppd/sys-bsd.c Sun Jan 16 18:50:04 2000 @@ -1525,3 +1525,8 @@ } } #endif + +int connect_pppoa(char *host_dev) +{ + fatal("PPPoATM is not supported on this architecture"); +} diff -ur ppp-2.3.11-clean/pppd/sys-linux.c ppp-2.3.11/pppd/sys-linux.c --- ppp-2.3.11-clean/pppd/sys-linux.c Wed Dec 22 23:51:31 1999 +++ ppp-2.3.11/pppd/sys-linux.c Thu Jan 20 16:34:17 2000 @@ -42,6 +42,9 @@ #include #include +#include +#include + /* This is in netdevice.h. However, this compile will fail miserably if you attempt to include netdevice.h because it has so many references to __memcpy functions which it should not attempt to do. So, since I @@ -355,6 +358,7 @@ int establish_ppp (int tty_fd) { int x; + struct ifppp_unit_encaps ue; /* * The current PPP device will be the tty file. @@ -365,9 +369,11 @@ /* * Ensure that the tty device is in exclusive mode. */ - if (ioctl(tty_fd, TIOCEXCL, 0) < 0) { - if ( ! ok_error ( errno )) - warn("ioctl(TIOCEXCL): %m"); + if (!pppoa) { + if (ioctl(tty_fd, TIOCEXCL, 0) < 0) { + if ( ! ok_error ( errno )) + warn("ioctl(TIOCEXCL): %m"); + } } /* * Demand mode - prime the old ppp device to relinquish the unit. @@ -402,10 +408,23 @@ } else { set_flags(ppp_dev_fd, get_flags(ppp_dev_fd) & ~SC_LOOP_TRAFFIC); } - if (ioctl(tty_fd, PPPIOCATTACH, &ifunit) < 0) { - if (errno == EIO) - return -1; - fatal("Couldn't attach tty to PPP unit %d: %m", ifunit); + if (!pppoa) { + if (ioctl(tty_fd, PPPIOCATTACH, &ifunit) < 0) { + if (errno == EIO) + return -1; + fatal("Couldn't attach tty to PPP unit %d: %m", ifunit); + } + } else { + /* PPPoATM is special here, because either LLC encapsulation + * or VC multiplexing can be used. + */ + ue.unit = ifunit; + ue.encaps = llc_encaps; + if (ioctl(tty_fd, PPPIOCATTACHENCAPS, &ue) < 0) { + if (errno == EIO) + return -1; + fatal("Couldn't attach tty to PPP unit %d: %m", ifunit); + } } } else { if (ioctl(tty_fd, PPPIOCGUNIT, &x) < 0) { @@ -939,12 +958,16 @@ void ppp_set_xaccm (int unit, ext_accm accm) { + int err; + SYSDEBUG ((LOG_DEBUG, "set_xaccm: %08lx %08lx %08lx %08lx\n", accm[0], accm[1], accm[2], accm[3])); if (!still_ppp()) return; - if (ioctl(ppp_fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY) { + /* some code (incorrectly) returns EINVAL for non-implemented ioctls */ + err = ioctl(ppp_fd, PPPIOCSXASYNCMAP, accm); + if ((err < 0) && (errno != EINVAL) && (errno != ENOTTY)) { if ( ! ok_error (errno)) warn("ioctl(set extended ACCM): %m(%d)", errno); } @@ -2512,4 +2535,70 @@ return 0; } return 1; +} + +int connect_pppoa(char *host_dev) +{ + int err, itf; + struct atm_qos qos; + struct sockaddr_atmpvc addr; + int fd; + + itf = host_dev[3] - '0'; + if ((itf == LONG_MIN) || (itf == LONG_MAX) || (itf < 0)) { + error("can't parse ATM dev %s %m", host_dev); + return -1; + } + + if ((fd = socket(AF_ATMPVC, SOCK_DGRAM, 0)) < 0) + fatal("failed to create socket %d", errno); + + memset(&addr, 0, sizeof(addr)); + addr.sap_family = PF_ATMPVC; + addr.sap_addr.itf = itf; + addr.sap_addr.vpi = 0; + addr.sap_addr.vci = vci; + + info("Communicating over ATM %d.%d.%d", addr.sap_addr.itf, + addr.sap_addr.vpi, + addr.sap_addr.vci); + + memset(&qos, 0, sizeof(qos)); + qos.aal = ATM_AAL5; + qos.txtp.traffic_class = ATM_UBR; + /* this is what Windows uses */ + qos.txtp.max_sdu = 1500; + qos.txtp.pcr = 301; + qos.rxtp = qos.txtp; + if (setsockopt(fd, SOL_ATM, SO_ATMQOS, &qos, sizeof(qos)) < 0) + fatal("setsockopt SO_ATMQOS %d %m", errno, errno); + + if (pppoa_accept) { + fd_set fds; + + warn("waiting for other end...\n"); + + err = bind(fd,(struct sockaddr *)&addr, sizeof(struct sockaddr_atmpvc)); if (err < 0) + fatal("failed to bind pppoatm socket %d %m", errno, errno); + + /* since we cannot use listen/accept to wait for an incoming + * connection (this ain't TCP/IP, you know!), we will just block + * in select until the other end sends us some data. + */ + FD_ZERO(&fds); + FD_SET(fd, &fds); + for (;;) { + err = select(1, &fds, NULL, NULL, NULL); + if (FD_ISSET(fd, &fds)); + break; + warn("select: %d %m", err); + } + } else { + err = connect(fd, (struct sockaddr*)&addr, sizeof(struct sockaddr_atmpvc)); + + if (err < 0) + fatal("failed to connect on socket: %d %m", errno, errno); + } + + return fd; } diff -ur ppp-2.3.11-clean/pppd/sys-osf.c ppp-2.3.11/pppd/sys-osf.c --- ppp-2.3.11-clean/pppd/sys-osf.c Thu Dec 23 01:35:28 1999 +++ ppp-2.3.11/pppd/sys-osf.c Sun Jan 16 18:54:08 2000 @@ -1753,3 +1753,8 @@ { return 0; } + +int connect_pppoa(char *host_dev) +{ + fatal("PPPoATM is not supported on this architecture"); +} diff -ur ppp-2.3.11-clean/pppd/sys-sunos4.c ppp-2.3.11/pppd/sys-sunos4.c --- ppp-2.3.11-clean/pppd/sys-sunos4.c Thu Dec 23 01:38:19 1999 +++ ppp-2.3.11/pppd/sys-sunos4.c Sun Jan 16 18:54:08 2000 @@ -1566,3 +1566,8 @@ slprintf(unknown, sizeof(unknown), "Error %d", n); return unknown; } + +int connect_pppoa(char *host_dev) +{ + fatal("PPPoATM is not supported on this architecture"); +} diff -ur ppp-2.3.11-clean/pppd/sys-svr4.c ppp-2.3.11/pppd/sys-svr4.c --- ppp-2.3.11-clean/pppd/sys-svr4.c Sun Nov 14 23:56:52 1999 +++ ppp-2.3.11/pppd/sys-svr4.c Sun Jan 16 18:54:08 2000 @@ -2530,3 +2530,9 @@ return 1; } + +int connect_pppoa(char *host_dev) +{ + fatal("PPPoATM is not supported on this architecture"); +} + diff -ur ppp-2.3.11-clean/pppd/sys-ultrix.c ppp-2.3.11/pppd/sys-ultrix.c --- ppp-2.3.11-clean/pppd/sys-ultrix.c Tue Aug 24 05:25:54 1999 +++ ppp-2.3.11/pppd/sys-ultrix.c Sun Jan 16 18:50:27 2000 @@ -1387,3 +1387,8 @@ } } #endif + +int connect_pppoa(char *host_dev) +{ + fatal("PPPoATM is not supported on this architecture"); +}