// NOTE // NOTE // NOTE // NOTE // NOTE // NOTE // NOTE // NOTE // NOTE // // // This is only meant as an example of the new pppd plugins right now... // it won't work with the current PPPoATM code for the kernel (as // distributed by Jens Axboe), it is meant to work with a new version // of the in-kernel PPPoATM backend which I am working on. As such // it will neither compile nor work in this present form. // -- mitch@xxxxxxxxxx // // NOTE // NOTE // NOTE // NOTE // NOTE // NOTE // NOTE // NOTE // NOTE // /* pppoatm.c - pppd plugin to implement PPPoATM protocol. * * Copyright 2000 Mitchell Blank Jr. * Based in part on work from Jens Axboe and Paul Mackerras. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ #include "pppd.h" #include static struct sockaddr_atmpvc pvcaddr; static char *qosstr = NULL; static int pppoatm_accept = 0; static bool llc_encaps = 0; static bool vc_encaps = 0; static option_t my_options[] = { #if 0 { "accept", o_bool, &pppoatm_accept, "set PPPoATM socket to accept incoming connections", 1 }, #endif { "llc-encaps", o_bool, &llc_encaps, "use LLC encapsulation for PPPoATM", 1}, { "vc-encaps", o_bool, &vc_encaps, "use VC multiplexing for PPPoATM (default)", 1}, { "qos", o_str, &qosstr, "set QoS for PPPoATM connection", 1}, { NULL } }; /* returns: * -1 if there's a problem with setting the device * 0 if we can't parse "cp" as a valid name of a device * 1 if "cp" is a reasonable thing to name a device * Note that we don't actually open the device at this point * We do need to fill in: * devnam: a string representation of the device * devstat: a stat structure of the device. In this case * we're not opening a device, so we just make sure * to set up S_ISCHR(devstat.st_mode) != 1, so we * don't get confused that we're on stdin. */ static int setdevname_pppoatm(const char *cp) { struct sockaddr_atmpvc addr; extern struct stat devstat; info("PPPoATM setdevname_pppoatm"); memset(&addr, 0, sizeof addr); if (text2atm(cp, (struct sockaddr *) &addr, sizeof(addr), T2A_PVC | T2A_NAME) < 0) return 0; if (!dev_set_ok()) return -1; memcpy(&pvcaddr, &addr, sizeof pvcaddr); strlcpy(devnam, cp, sizeof devname); devstat.st_mode = S_IFSOCK; info("PPPoATM setdevname_pppoatm - SUCCESS"); return 1; } static int setspeed_pppoatm(const char *cp) { return 0; } static int options_for_pppoatm(void) { return options_from_devfile(_PATH_ATMOPT, devnam); } #define pppoatm_overhead() (llc_encaps ? 6 : 2) static int open_device_pppoatm(void) { int fd; struct atm_qos qos; fd = socket(AF_ATMPVC, SOCK_DGRAM, 0); if (fd < 0) fatal("failed to create socket: %m"); memset(&qos, 0, sizeof qos); /* TODO: support simplified QoS setting */ if (qosstr != NULL) if (text2qos(qosstr, &qos, 0)) fatal("Can't parse QoS: \"%s\""); qos.txtp.max_sdu = mtu + pppoatm_overhead(); qos.rxtp.max_sdu = mru + pppoatm_overhead(); qos.aal = ATM_AAL5; if (setsockopt(fd, SOL_ATM, SO_ATMQOS, &qos, sizeof(qos)) < 0) fatal("setsockopt(SO_ATMQOS): %m"); /* TODO: accept on SVCs... */ if (connect(fd, (struct sockaddr *) &addr, sizeof(struct sockaddr_atmpvc)) fatal("connect(%s): %m", devnam); return fd; } static void post_open_setup_pppoatm(void) { /* NOTHING */ } static void pre_close_restore_pppoatm(void) { /* NOTHING */ } static void no_device_given_pppoatm(void) { fatal("No vpi.vci specified"); } static void set_line_discipline_pppoatm(int fd) { int encaps; if (ioctl(fd, ATM_SET_HANDLER, ATM_HANDLER_PPP) < 0) fatal("ioctl(ATM_SET_HANDLER, ATM_HANDLER_PPP): %m"); if (!llc_encaps) encaps = PPPOATM_ENCAPS_VC; else if (!vc_encaps) encaps = PPPOATM_ENCAPS_LLC; else encaps = PPPOATM_ENCAPS_AUTODETECT; if (ioctl(fd, PPPOATM_SET_ENCAPS, encaps) < 0) fatal("ioctl(PPPOATM_SET_ENCAPS): %m"); } static void unset_line_discipline_pppoatm(int fd) { if (ioctl(fd, ATM_SET_HANDLER, ATM_HANDLER_RAW) < 0) fatal("ioctl(ATM_SET_HANDLER, ATM_HANDLER_RAW): %m"); } static void send_config_pppoatm(int unit, int mtu, u_int32_t asyncmap, int pcomp, int accomp) { int sock; struct ifreq ifr; if (mtu > pppoatm_max_mtu) error("Couldn't increase MTU to %d", mtu); sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) fatal("Couldn't create IP socket: %m"); strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); ifr.ifr_mtu = mtu; if (ioctl(sock, SIOCSIFMTU, (caddr_t) &ifr) < 0) fatal("ioctl(SIOCSIFMTU): %m"); (void) close (sock); } static void recv_config_pppoatm(int unit, int mru, u_int32_t asyncmap, int pcomp, int accomp) { if (mru > pppoatm_max_mru) error("Couldn't increase MRU to %d", mru); } static void set_xaccm_pppoatm(int unit, ext_accm accm) { /* NOTHING */ } void plugin_init(void) { #if _linux_ extern int new_style_driver; /* From sys-linux.c */ #endif static char *bad_options[] = { "noaccomp", "-ac", "default-asyncmap", "-am", "asyncmap", "-as", "escape", "receive-all", "crtscts", "-crtscts", "nocrtscts", "cdtrcts", "nocdtrcts", "xonxoff", "modem", "local", "sync", NULL }; #if _linux_ if (!new_style_driver) fatal("Kernel doesn't support ppp_generic needed for PPPoATM"); #else fatal("No PPPoATM support on this OS"); #endif info("PPPoATM plugin_init"); add_options(my_options); setdevname_hook = setdevname_pppoatm; setspeed_hook = setspeed_pppoatm; options_from_device_hook = options_for_pppoatm; open_device_hook = open_device_pppoatm; post_open_setup_hook = post_open_setup_pppoatm; pre_close_restore_hook = pre_close_restore_pppoatm; no_device_given_hook = no_device_given_pppoatm; set_line_discipline_hook = set_line_discipline_pppoatm; reset_line_discipline_hook = reset_line_discipline_pppoatm; send_config_hook = send_config_pppoatm; recv_config_hook = recv_config_pppoatm; set_xaccm_hook = set_xaccm_pppoatm; { char **a; for (a = bad_options; *a != NULL; a++) remove_option(*a); } modem = 0; lcp_wantoptions[0].neg_accompression = 0; lcp_allowoptions[0].neg_accompression = 0; lcp_wantoptions[0].neg_asyncmap = 0; lcp_allowoptions[0].neg_asyncmap = 0; lcp_wantoptions[0].neg_pcompression = 0; }