X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=pppd%2Fsys-str.c;h=780b27f95d643403798c57e64f33a8a21add2979;hp=ecee95b576ff8b001a92ea4a9d013aa749991631;hb=55d1aee00ea64ce0abaa0accd5bfab65d39a1f7d;hpb=0b63a24d54ba4708c88e31bdd74b0145956c1478 diff --git a/pppd/sys-str.c b/pppd/sys-str.c index ecee95b..780b27f 100644 --- a/pppd/sys-str.c +++ b/pppd/sys-str.c @@ -22,8 +22,14 @@ * TODO: */ +#include #include #include +#include +#include +#include +#include +#include #include #include #include @@ -38,7 +44,7 @@ #include "pppd.h" #include "ppp.h" -#include "ppp_str.h" +#include #ifndef ifr_mtu #define ifr_mtu ifr_metric @@ -49,8 +55,61 @@ static struct modlist { char modname[FMNAMESZ+1]; } str_modules[MAXMODULES]; static int str_module_count = 0; +static int pushed_ppp; +static int closed_stdio; + +extern int hungup; /* has the physical layer been disconnected? */ +extern int kdebugflag; +extern int default_device; +extern int restore_term; + +#define PAI_FLAGS_B7_0 0x100 +#define PAI_FLAGS_B7_1 0x200 +#define PAI_FLAGS_PAR_EVEN 0x400 +#define PAI_FLAGS_PAR_ODD 0x800 +#define PAI_FLAGS_HIBITS 0xF00 + +/* + * daemon - Detach us from the 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; +} + + +/* + * ppp_available - check if this kernel supports PPP. + */ +int +ppp_available() +{ + int fd, ret; + + fd = open("/dev/tty", O_RDONLY, 0); + if (fd < 0) + return 1; /* can't find out - assume we have ppp */ + ret = ioctl(fd, I_FIND, "pppasync") >= 0; + close(fd); + return ret; +} -extern int hungup; /* * establish_ppp - Turn the serial port into a ppp interface. @@ -68,33 +127,27 @@ establish_ppp() str_module_count++; } - MAINDEBUG((LOG_INFO, "about to push modules...")); - /* now push the async/fcs module */ if (ioctl(fd, I_PUSH, "pppasync") < 0) { syslog(LOG_ERR, "ioctl(I_PUSH, ppp_async): %m"); die(1); } + /* push the compress module */ + if (ioctl(fd, I_PUSH, "pppcomp") < 0) { + syslog(LOG_WARNING, "ioctl(I_PUSH, ppp_comp): %m"); + } /* finally, push the ppp_if module that actually handles the */ /* network interface */ if (ioctl(fd, I_PUSH, "pppif") < 0) { syslog(LOG_ERR, "ioctl(I_PUSH, ppp_if): %m"); die(1); } - if (ioctl(fd, I_SETSIG, S_INPUT) < 0) { - syslog(LOG_ERR, "ioctl(I_SETSIG, S_INPUT): %m"); - die(1); - } + pushed_ppp = 1; /* read mode, message non-discard mode */ if (ioctl(fd, I_SRDOPT, RMSGN) < 0) { syslog(LOG_ERR, "ioctl(I_SRDOPT, RMSGN): %m"); die(1); } - /* Flush any waiting messages, or we'll never get SIGPOLL */ - if (ioctl(fd, I_FLUSH, FLUSHRW) < 0) { - syslog(LOG_ERR, "ioctl(I_FLUSH, FLUSHRW): %m"); - die(1); - } /* * Find out which interface we were given. * (ppp_if handles this ioctl) @@ -104,15 +157,20 @@ establish_ppp() die(1); } - /* if debug, set debug flags in driver */ - { - int flags = debug ? 0x3 : 0; - if (ioctl(fd, SIOCSIFDEBUG, &flags) < 0) { - syslog(LOG_ERR, "ioctl(SIOCSIFDEBUG): %m"); - } + /* Set debug flags in driver */ + if (ioctl(fd, SIOCSIFDEBUG, &kdebugflag) < 0) { + syslog(LOG_ERR, "ioctl(SIOCSIFDEBUG): %m"); } - MAINDEBUG((LOG_INFO, "done pushing modules, ifunit %d", ifunit)); + /* close stdin, stdout, stderr if they might refer to the device */ + if (default_device && !closed_stdio) { + int i; + + for (i = 0; i <= 2; ++i) + if (i != fd && i != s) + close(i); + closed_stdio = 1; + } } /* @@ -123,21 +181,52 @@ establish_ppp() void disestablish_ppp() { - /*EMPTY*/ + int flags; + char *s; if (hungup) { /* we can't push or pop modules after the stream has hung up */ str_module_count = 0; + restore_term = 0; /* nor can we fix up terminal settings */ return; } + if (pushed_ppp) { + /* + * Check whether the link seems not to be 8-bit clean. + */ + if (ioctl(fd, SIOCGIFDEBUG, (caddr_t) &flags) == 0) { + s = NULL; + switch (~flags & PAI_FLAGS_HIBITS) { + case PAI_FLAGS_B7_0: + s = "bit 7 set to 1"; + break; + case PAI_FLAGS_B7_1: + s = "bit 7 set to 0"; + break; + case PAI_FLAGS_PAR_EVEN: + s = "odd parity"; + break; + case PAI_FLAGS_PAR_ODD: + s = "even parity"; + break; + } + if (s != NULL) { + syslog(LOG_WARNING, "Serial link is not 8-bit clean:"); + syslog(LOG_WARNING, "All received characters had %s", s); + } + } + } + while (ioctl(fd, I_POP, 0) == 0) /* pop any we pushed */ ; + pushed_ppp = 0; for (; str_module_count > 0; str_module_count--) { if (ioctl(fd, I_PUSH, str_modules[str_module_count-1].modname)) { - syslog(LOG_ERR, "str_restore: couldn't push module %s: %m", - str_modules[str_module_count-1].modname); + if (errno != ENXIO) + syslog(LOG_WARNING, "str_restore: couldn't push module %s: %m", + str_modules[str_module_count-1].modname); } else { MAINDEBUG((LOG_INFO, "str_restore: pushed module %s", str_modules[str_module_count-1].modname)); @@ -159,16 +248,35 @@ output(unit, p, len) if (unit != 0) MAINDEBUG((LOG_WARNING, "output: unit != 0!")); + if (debug) + log_packet(p, len, "sent "); str.len = len; str.buf = (caddr_t) p; - if(putmsg(fd, NULL, &str, 0) < 0) { - syslog(LOG_ERR, "putmsg: %m"); - die(1); + if (putmsg(fd, NULL, &str, 0) < 0) { + if (errno != ENXIO) { + syslog(LOG_ERR, "putmsg: %m"); + die(1); + } } } +wait_input(timo) + struct timeval *timo; +{ + int t; + struct pollfd pfd; + + t = timo == NULL? -1: timo->tv_sec * 1000 + timo->tv_usec / 1000; + pfd.fd = fd; + pfd.events = POLLIN | POLLPRI | POLLHUP; + if (poll(&pfd, 1, t) < 0 && errno != EINTR) { + syslog(LOG_ERR, "poll: %m"); + die(1); + } +} + /* * read_packet - get a PPP packet from the serial device. */ @@ -176,13 +284,16 @@ int read_packet(buf) u_char *buf; { - struct strbuf str; + struct strbuf str, ctl; int len, i; + unsigned char ctlbuf[16]; str.maxlen = MTU+DLLHEADERLEN; str.buf = (caddr_t) buf; + ctl.maxlen = sizeof(ctlbuf); + ctl.buf = (caddr_t) ctlbuf; i = 0; - len = getmsg(fd, NULL, &str, &i); + len = getmsg(fd, &ctl, &str, &i); if (len < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { return -1; @@ -192,6 +303,9 @@ read_packet(buf) } if (len) MAINDEBUG((LOG_DEBUG, "getmsg returned 0x%x",len)); + if (ctl.len > 0) + syslog(LOG_NOTICE, "got ctrl msg len %d %x %x\n", ctl.len, + ctlbuf[0], ctlbuf[1]); if (str.len < 0) { MAINDEBUG((LOG_DEBUG, "getmsg short return length %d", str.len)); @@ -227,22 +341,36 @@ ppp_send_config(unit, mtu, asyncmap, pcomp, accomp) quit(); } - c = pcomp; + c = (pcomp? 1: 0); if(ioctl(fd, SIOCSIFCOMPPROT, &c) < 0) { syslog(LOG_ERR, "ioctl(SIOCSIFCOMPPROT): %m"); quit(); } - c = accomp; + c = (accomp? 1: 0); if(ioctl(fd, SIOCSIFCOMPAC, &c) < 0) { syslog(LOG_ERR, "ioctl(SIOCSIFCOMPAC): %m"); quit(); } } + +/* + * ppp_set_xaccm - set the extended transmit ACCM for the interface. + */ +void +ppp_set_xaccm(unit, accm) + int unit; + ext_accm accm; +{ + if (ioctl(fd, SIOCSIFXASYNCMAP, accm) < 0 && errno != ENOTTY) + syslog(LOG_WARNING, "ioctl(set extended ACCM): %m"); +} + + /* * ppp_recv_config - configure the receive-side characteristics of - * the ppp interface. At present this just sets the MRU. + * the ppp interface. */ void ppp_recv_config(unit, mru, asyncmap, pcomp, accomp) @@ -256,28 +384,64 @@ ppp_recv_config(unit, mru, asyncmap, pcomp, accomp) syslog(LOG_ERR, "ioctl(SIOCSIFMRU): %m"); } -#ifdef notyet - if(ioctl(fd, SIOCSIFRASYNCMAP, (caddr_t) &asyncmap) < 0) { + if (ioctl(fd, SIOCSIFRASYNCMAP, (caddr_t) &asyncmap) < 0) { syslog(LOG_ERR, "ioctl(SIOCSIFRASYNCMAP): %m"); } - c = accomp; - if(ioctl(fd, SIOCSIFRCOMPAC, &c) < 0) { - syslog(LOG_ERR, "ioctl(SIOCSIFRCOMPAC): %m"); - quit(); + c = 2 + (pcomp? 1: 0); + if(ioctl(fd, SIOCSIFCOMPPROT, &c) < 0) { + syslog(LOG_ERR, "ioctl(SIOCSIFCOMPPROT): %m"); + } + + c = 2 + (accomp? 1: 0); + if (ioctl(fd, SIOCSIFCOMPAC, &c) < 0) { + syslog(LOG_ERR, "ioctl(SIOCSIFCOMPAC): %m"); } -#endif /* notyet */ +} + +/* + * ccp_test - ask kernel whether a given compression method + * is acceptable for use. + */ +ccp_test(unit, opt_ptr, opt_len, for_transmit) + int unit, opt_len, for_transmit; + u_char *opt_ptr; +{ + struct ppp_option_data data; + + if ((unsigned) opt_len > MAX_PPP_OPTION) + opt_len = MAX_PPP_OPTION; + data.length = opt_len; + data.transmit = for_transmit; + BCOPY(opt_ptr, data.opt_data, opt_len); + return ioctl(fd, SIOCSCOMPRESS, (caddr_t) &data) >= 0; +} + +/* + * ccp_flags_set - inform kernel about the current state of CCP. + */ +void +ccp_flags_set(unit, isopen, isup) + int unit, isopen, isup; +{ + int x; + + x = (isopen? 1: 0) + (isup? 2: 0); + if (ioctl(fd, SIOCSIFCOMP, (caddr_t) &x) < 0 && errno != ENOTTY) + syslog(LOG_ERR, "ioctl (SIOCSIFCOMP): %m"); } /* * sifvjcomp - config tcp header compression */ int -sifvjcomp(u, vjcomp, cidcomp) +sifvjcomp(u, vjcomp, cidcomp, maxcid) + int u, vjcomp, cidcomp, maxcid; { - char x = vjcomp; + char x; - if(ioctl(fd, SIOCSIFVJCOMP, (caddr_t) &x) < 0) { + x = (vjcomp? 1: 0) + (cidcomp? 0: 2) + (maxcid << 4); + if (ioctl(fd, SIOCSIFVJCOMP, (caddr_t) &x) < 0) { syslog(LOG_ERR, "ioctl(SIOCSIFVJCOMP): %m"); return 0; } @@ -289,6 +453,7 @@ sifvjcomp(u, vjcomp, cidcomp) */ int sifup(u) + int u; { struct ifreq ifr; @@ -310,6 +475,7 @@ sifup(u) */ int sifdown(u) + int u; { struct ifreq ifr; strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); @@ -337,6 +503,8 @@ sifdown(u) */ int sifaddr(u, o, h, m) + int u; + u_long o, h, m; { int ret; struct ifreq ifr; @@ -371,6 +539,8 @@ sifaddr(u, o, h, m) */ int cifaddr(u, o, h) + int u; + u_long o, h; { struct rtentry rt; @@ -391,6 +561,8 @@ cifaddr(u, o, h) */ int sifdefaultroute(u, g) + int u; + u_long g; { struct rtentry rt; @@ -410,6 +582,8 @@ sifdefaultroute(u, g) */ int cifdefaultroute(u, g) + int u; + u_long g; { struct rtentry rt; @@ -441,7 +615,7 @@ sifproxyarp(unit, hisaddr) * as our local address. */ if (!get_ether_addr(hisaddr, &arpreq.arp_ha)) { - syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP"); + syslog(LOG_WARNING, "Cannot determine ethernet address for proxy ARP"); return 0; } @@ -480,7 +654,7 @@ cifproxyarp(unit, hisaddr) * get_ether_addr - get the hardware address of an interface on the * the same subnet as ipaddr. Code borrowed from myetheraddr.c * in the cslip-2.6 distribution, which is subject to the following - * copyright notice: + * copyright notice (which also applies to logwtmp below): * * Copyright (c) 1990, 1992 The Regents of the University of California. * All rights reserved. @@ -526,7 +700,7 @@ cifproxyarp(unit, hisaddr) static struct nlist nl[] = { #define N_IFNET 0 { "_ifnet" }, - 0 + { 0 } }; static void kread(); @@ -622,3 +796,26 @@ get_ether_addr(ipaddr, hwaddr) /* couldn't find one */ return 0; } + +#define WTMPFILE "/usr/adm/wtmp" + +int +logwtmp(line, name, host) + char *line, *name, *host; +{ + int fd; + struct stat buf; + struct utmp ut; + + if ((fd = open(WTMPFILE, O_WRONLY|O_APPEND, 0)) < 0) + return; + if (!fstat(fd, &buf)) { + (void)strncpy(ut.ut_line, line, sizeof(ut.ut_line)); + (void)strncpy(ut.ut_name, name, sizeof(ut.ut_name)); + (void)strncpy(ut.ut_host, host, sizeof(ut.ut_host)); + (void)time(&ut.ut_time); + if (write(fd, (char *)&ut, sizeof(struct utmp)) != sizeof(struct utmp)) + (void)ftruncate(fd, buf.st_size); + } + close(fd); +}