This is ppp.c in view mode; [Download] [Up]
/* * ppp.c - Point-to-Point Protocol. * * Copyright (c) 1989 Carnegie Mellon University. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by Carnegie Mellon University. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ /* * TODO: * Don't prompt for passwd on /dev/tty (go into server mode). * Might want to choose IP addresses from config file based on user id * if the server, or based on remote host if tip'd client. * Way to set asyncmap. * Wait for tty queue to empty before exiting in quit. */ /* * There are three scenarios: * 1. ppp used as daemon started from /etc/rc or perhaps /etc/ttys. * a. server * b. authentication necessary * c. want to use constant local ip addr * d. want to use constant remote ip addr, constant ip addr based on * authenticated user, or request ip addr * 2. ppp used on /dev/tty after remote login. * a. server * b. no authentication necessary or allowed * c. want to use constant local ip addr * d. want to use constant remote ip addr, constant ip addr based on * authenticated user, or request ip addr * 3. ppp used on line after tip'ing out. * a. client * b. remote end may request authentication * c. want to use constant local ip addr or request ip addr * d. want to use constant remote ip addr based on tip'd host, or * request remote ip addr */ #include <string.h> #include <stdio.h> #include <signal.h> #include <errno.h> #include <fcntl.h> #ifndef STREAMS #include <sgtty.h> #endif #include <pwd.h> #include <syslog.h> #include <netdb.h> #include <utmp.h> #include <sys/param.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/socket.h> #include <sys/time.h> #include <sys/callout.h> #include <net/if.h> #ifdef STREAMS #include <sys/stream.h> #include <sys/stropts.h> #include <sys/termios.h> #include <sys/conf.h> #endif # define DEVNAME_SIZE 128 /* Buffer size for /dev/* filenames */ #ifdef sun /* * Get definition of SUNOS */ #include <pixrect/pr_impl_util.h> #endif #include "magic.h" #include "ppp.h" #include "fsm.h" #include "lcp.h" #include "ipcp.h" #include "upap.h" #include "patchlevel.h" #ifdef __NeXT__ struct callout { int c_time; /* incremental time */ void *c_arg; /* argument to routine */ func c_func; /* routine */ struct callout *c_next; }; #endif #define PPPHOSTS "/etc/hosts.ppp" int dial = 0; char dial_cmd[256]; int debug = 0; /* Debug flag */ int fsm_debug = 0; /* FSM debug flag */ int lcp_debug = 0; /* LCP debug flag */ int ipcp_debug = 0; /* IPCP debug flag */ int upap_debug = 0; /* UPAP debug flag */ char *progname; /* Name of this program */ char devname[DEVNAME_SIZE] = "/dev/tty"; /* Device name */ char ifname[IFNAMSIZ]; /* Interface name */ int ifunit; /* Interface unit number */ char inspeed = 0, outspeed = 0; /* Input/Output speed */ int fd; /* Device file descriptor */ int s; /* Socket file descriptor */ int initdisc; /* Initial TTY discipline */ #ifndef STREAMS struct sgttyb initsgttyb; /* Initial TTY sgttyb */ #endif int initfdflags; /* Initial file descriptor flags */ #ifdef __NeXT__ int pid; /* Our pid */ #else pid_t pid; /* Our pid */ #endif #ifdef sun pid_t pgrpid; /* Process Group ID */ #endif char user[80]; /* User name */ void hup(), intr(), term(), alrm(), io(), incdebug(), nodebug(); int setdebug(), setpassive(), noopt(), novj(), noupap(), requpap(); int setspeed(), noaccomp(), noasyncmap(), noipaddr(), nomagicnumber(); int setasyncmap(), setold(), setdial(); int setmru(), nomru(), nopcomp(); void getuserpasswd(); #ifdef STREAMS extern char *ttyname(); #define MAXMODULES 10 /* max number of module names that we can save */ struct modlist { char modname[FMNAMESZ+1]; } str_modules[MAXMODULES]; int str_module_count = 0; #endif /* * Valid arguments. */ struct cmd { char *cmd_name; int (*cmd_func)(); } cmds[] = { "-all", noopt, /* Don't request/allow any options */ "-ac", noaccomp, /* Disable Address/Control compress */ "-am", noasyncmap, /* Disable asyncmap negotiation */ "-as", setasyncmap, /* set the desired async map */ "-d", setdebug, /* Increase debugging level */ "debug", setdebug, /* Increase debugging level */ "-ip", noipaddr, /* Disable IP address negotiation */ "-mn", nomagicnumber, /* Disable magic number negotiation */ "-mru", nomru, /* Disable mru negotiation */ "mru", setmru, /* Set MRU value for negotiation */ "-p", setpassive, /* Set passive mode */ "-pc", nopcomp, /* Disable protocol field compress */ "passive", setpassive, /* Set passive mode */ "+ua", requpap, /* Require UPAP authentication */ "-ua", noupap, /* Don't allow UPAP authentication */ "-vj", novj, /* Disable VJ compression */ "dial", setdial, /* Use dial to dialup */ "old", setold, /* Backward compatibility mode */ #if 0 "local", setlocalipaddr, "remote", setremoteipaddr, "test", enabletestline, #endif NULL }; /* * PPP Data Link Layer "protocol" table. * One entry per supported protocol. */ struct protent { u_short protocol; void (*init)(); void (*input)(); void (*protrej)(); } prottbl[] = { { LCP, lcp_init, lcp_input, lcp_protrej }, { IPCP, ipcp_init, ipcp_input, ipcp_protrej }, { UPAP, upap_init, upap_input, upap_protrej }, }; char *usage = "PPP patch level %d\n\ Usage: %s [ arguments ], where arguments are:\n\ -all Don't request/allow any options\n\ -ac Disable Address/Control compression\n\ -am Disable asyncmap negotiation\n\ -as <n> Set the desired async map to hex <n>\n\ -d Increase debugging level\n\ debug Increase debugging level\n\ -ip Disable IP address negotiation\n\ -mn Disable magic number negotiation\n\ -mru Disable mru negotiation\n\ mru <n> Set MRU value to <n> for negotiation\n\ -p Set passive mode\n\ -pc Disable protocol field compression\n\ passive Set passive mode\n\ +ua Require UPAP authentication\n\ -ua Don't allow UPAP authentication\n\ -vj Disable VJ compression\n\ old Backward compatibility mode for use with old PPP versions\n\ dial <cmd> Dial using cmd (stdin/out is the device)\n\ <device> Communicate over the named device\n\ <speed> Set the baud rate to <speed>\n\ <loc>:<rem> Set the local and/or remote interface IP\n\ addresses. Either one may be omitted.\n"; #ifdef STREAMS str_restore(ecode) int ecode; /* called by exit */ /* this module will attempt to reconstruct the stream with the previously popped modules */ { while(ioctl(fd, I_POP, 0) == 0); /* pop any we pushed */ for(; str_module_count > 0; str_module_count--) { if(ioctl(fd, I_PUSH, str_modules[str_module_count-1].modname)) { if(debug) fprintf(stderr, "str_restore: couldn't push module %s\n", str_modules[str_module_count-1].modname); } else { if(debug) fprintf(stderr, "str_restore: pushed module %s\n", str_modules[str_module_count-1].modname); } } } #endif main(argc, argv) int argc; char *argv[]; { int mask, i; #ifdef STREAMS struct termios tios; #else int pppdisc = PPPDISC; struct sgttyb sgttyb; #endif struct sigvec sv; struct cmd *cmdp; pid = getpid(); /* * Initialize syslog system and magic number package. */ #if BSD >= 43 openlog("ppp", LOG_PID | LOG_NDELAY, LOG_DAEMON); setlogmask(LOG_UPTO(LOG_WARNING)); #else openlog("ppp", LOG_PID); #define LOG_UPTO(x) (x) #define setlogmask(x) (x) #endif #ifdef STREAMS if (ttyname(fileno(stdin))) strcpy(devname, ttyname(fileno(stdin))); #endif magic_init(); /* * Initialize to the standard option set and then parse the command * line arguments. */ for (i = 0; i < sizeof (prottbl) / sizeof (struct protent); i++) (*prottbl[i].init)(0); progname = *argv; for (argc--, argv++; argc; ) { /* * First see if it's a command. */ for (cmdp = cmds; cmdp->cmd_name; cmdp++) if (!strcmp(*argv, cmdp->cmd_name) && (*cmdp->cmd_func)(&argc, &argv)) break; /* * Maybe a tty name, speed or IP address? */ if (cmdp->cmd_name == NULL && !setdevname(&argc, &argv) && !setspeed(&argc, &argv) && !setipaddr(&argc, &argv)) { fprintf(stderr, usage, PATCHLEVEL, progname); exit(1); } } /* * Initialize state. */ #if defined(sun) && defined(SUNOS) && SUNOS >= 41 if ((pgrpid = setsid()) < 0) pgrpid = getpgrp(0); #endif #ifdef __NeXT__ if (strcmp(devname, "/dev/tty")) { int f; if ((f = open ("/dev/tty", O_RDWR)) != -1) { ioctl (f, TIOCNOTTY, (char *)0); close (f); } } #endif if ((fd = open(devname, O_RDWR /*| O_NDELAY*/)) < 0) { perror(devname); exit(1); } #ifdef __NeXT__ if (ioctl (fd, TIOCSPGRP, &pid) == -1) { perror("TIOCSPGRP"); _exit(1); } dup2(fd, 0); dup2(fd, 1); setpgrp (0, pid); #endif if (dial) { char cmd[1024]; sprintf(cmd, "%s %d", dial_cmd, getpid()); if (system(cmd)) { fprintf(stderr, "dial command '%s' failed\n", cmd); exit(1); } } #if defined(sun) && defined(SUNOS) && SUNOS >= 41 if (getpid() != pgrpid && tcsetpgrp(fd, pgrpid) < 0) { perror("ppp: tcsetpgrp()"); exit(1); } #endif if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("ppp: socket"); exit(1); } #ifdef STREAMS while(1) { /* go through and save the name of all the modules, then pop em */ if(!ioctl(fd, I_LOOK, str_modules[str_module_count].modname)) if(debug) fprintf(stderr, "popped stream module : %s\n", str_modules[str_module_count].modname); if(!ioctl(fd, I_POP, 0)) str_module_count++; else break; } on_exit(str_restore,NULL); /* if we exit, then try and restore the stream */ if(ioctl(fd, TCGETS, (caddr_t) &tios) < 0) { perror("ppp: ioctl(TCGETS)"); exit(1); } tios.c_cflag = CRTSCTS | (inspeed ? inspeed : (tios.c_cflag & CBAUD)); tios.c_cflag |= CS8|CREAD|HUPCL; tios.c_iflag = IGNBRK; if(ioctl(fd, TCSETS, (caddr_t) &tios) < 0) { perror("ppp: ioctl(TCSETS)"); exit(1); } /* now push the async/fcs module */ if(ioctl(fd, I_PUSH, "pppasync") < 0) { perror("ppp: ioctl(I_PUSH, ppp_async)"); exit(1); } /* finally, push the ppp_if module that actually handles the network interface */ if(ioctl(fd, I_PUSH, "pppif") < 0) { perror("ppp: ioctl(I_PUSH, ppp_if)"); exit(1); } if(ioctl(fd, I_SETSIG, S_INPUT) < 0) { perror("ppp: ioctl(I_SETSIG, S_INPUT)"); exit(1); } /* read mode, message non-discard mode */ if(ioctl(fd, I_SRDOPT, RMSGN) < 0) { perror("ppp: ioctl(I_SRDOPT, RMSGN)"); exit(1); } /* Flush any waiting messages, or we'll never get SIGPOLL */ if(ioctl(fd, I_FLUSH, FLUSHRW) < 0) { perror("ppp: ioctl(I_FLUSH, FLUSHRW)"); exit(1); } #else /* * Put the tty in raw mode and set the discipline to PPP. */ if (ioctl(fd, TIOCGETP, &initsgttyb) < 0) { perror("ppp: ioctl(TIOCGETP)"); exit(1); } sgttyb = initsgttyb; sgttyb.sg_flags = RAW | ANYP; if (inspeed) sgttyb.sg_ispeed = inspeed; if (outspeed) sgttyb.sg_ospeed = outspeed; if (ioctl(fd, TIOCSETP, &sgttyb) < 0) { perror("ppp: ioctl(TIOCSETP)"); exit(1); } if (ioctl(fd, TIOCGETD, &initdisc) < 0) { perror("ppp: ioctl(TIOCGETD)"); exit(1); } if (ioctl(fd, TIOCSETD, &pppdisc) < 0) { perror("ppp: ioctl(TIOCSETD)"); exit(1); } #endif /* * Find out which interface we were given. */ #ifdef STREAMS if (ioctl(fd, SIOCGETU, &ifunit) < 0) { /* in streams, ppp_if handles this ioctl */ perror("ppp: ioctl(SIOCGETU)"); exit(1); } #else if (ioctl(fd, TIOCGETD, &ifunit) < 0) { perror("ppp: ioctl(TIOCGETD)"); exit(1); } #endif sprintf(ifname, "ppp%d", ifunit); if (debug) fprintf(stderr, "Interface %s.\n", ifname); if (debug) fprintf(stderr, "Pid %d.\n", pid); # if !defined(sun) || !defined(SUNOS) || SUNOS < 41 if (ioctl(fd, TIOCSPGRP, &pid) < 0) { perror("ppp: ioctl(TIOCSPGRP)"); exit(1); } # endif /* * Compute mask of all interesting signals and install signal handlers * for each. Only one signal handler may be active at a time. Therefore, * all other signals should be masked when any handler is executing. */ mask = sigmask(SIGHUP) | sigmask(SIGINT) | sigmask(SIGALRM) | sigmask(SIGIO); #ifdef STREAMS mask |= sigmask(SIGPOLL); #endif sv.sv_handler = hup; /* Hangup */ sv.sv_mask = mask; sv.sv_flags = 0; if (sigvec(SIGHUP, &sv, NULL)) { perror("ppp: sigvec(SIGHUP)"); exit(1); } sv.sv_handler = intr; /* Interrupt */ sv.sv_mask = mask; sv.sv_flags = 0; if (sigvec(SIGINT, &sv, NULL)) { perror("ppp: sigvec(SIGINT)"); exit(1); } sv.sv_handler = term; /* Terminate */ sv.sv_mask = mask; sv.sv_flags = 0; if (sigvec(SIGTERM, &sv, NULL)) { perror("ppp: sigvec(SIGTERM)"); exit(1); } sv.sv_handler = alrm; /* Timeout */ sv.sv_mask = mask; sv.sv_flags = 0; if (sigvec(SIGALRM, &sv, NULL)) { perror("ppp: sigvec(SIGALRM)"); exit(1); } sv.sv_handler = io; /* Input available */ sv.sv_mask = mask; sv.sv_flags = 0; if (sigvec(SIGIO, &sv, NULL)) { perror("ppp: sigvec(SIGIO)"); exit(1); } #ifdef STREAMS sv.sv_handler = io; /* Input available */ sv.sv_mask = mask; sv.sv_flags = 0; if (sigvec(SIGPOLL, &sv, NULL)) { perror("ppp: sigvec(SIGPOLL)"); exit(1); } #endif (void) signal(SIGUSR1, incdebug); /* Increment debug flag */ (void) signal(SIGUSR2, nodebug); /* Reset debug flag */ /* * Record initial device flags, then set device to cause SIGIO * signals to be generated. */ if ((initfdflags = fcntl(fd, F_GETFL)) == -1) { perror("ppp: fcnt(F_GETFL)"); exit(1); } if (fcntl(fd, F_SETFL, FNDELAY | FASYNC) == -1) { perror("ppp: fcnt(F_SETFL, FNDELAY | FASYNC)"); exit(1); } /* * Block all signals, start opening the connection, and wait for * incoming signals (reply, timeout, etc.). */ syslog (LOG_DEBUG, "connect: %s %s", ifname, devname); sigblock(mask); /* Block signals now */ lcp_lowerup(0); /* XXX Well, sort of... */ if (lcp_wantoptions[0].passive) lcp_passiveopen(0); /* Start protocol in passive mode */ else lcp_activeopen(0); /* Start protocol in active mode */ for (;;) { sigpause(0); /* Wait for next signal */ /* Need to read user/passwd? */ if (upap[0].us_flags & UPAPF_UPPENDING) { sigsetmask(0); /* Allow other signals to occur */ getuserpasswd(); /* Get user and passwd */ upap[0].us_flags &= ~UPAPF_UPPENDING; upap[0].us_flags |= UPAPF_UPVALID; sigsetmask(mask); /* Diallow signals */ upap_authwithpeer(0); } } } /* * quit - Clean up state and exit. */ void quit() { if (fcntl(fd, F_SETFL, initfdflags) == -1) { perror("ppp: fcnt(F_SETFL, fdflags)"); exit(1); } #ifndef STREAMS if (ioctl(fd, TIOCSETP, &initsgttyb) < 0) { perror("ppp: ioctl(TIOCSETP)"); exit(1); } if (ioctl(fd, TIOCSETD, &initdisc) < 0) { perror("ppp: ioctl(TIOCSETD)"); exit(1); } #else if(ioctl(fd, I_FLUSH, FLUSHRW) < 0) { perror("ppp: quit ioctl(I_FLUSH,FLUSHRW)"); } str_restore(-1); #endif close(fd); if (dial) { char lockfile[256]; strcpy(lockfile, LCK_DIR); strcat(lockfile, "/LCK.."); if (rindex(devname, '/')) strcat(lockfile, rindex(devname , '/') + 1); else strcat(lockfile, devname); fprintf(stderr,"Unlinking %s\n", lockfile); unlink(lockfile); } exit(0); } struct callout *callout = NULL; /* Callout list */ struct timeval schedtime; /* Time last timeout was set */ /* * timeout - Schedule a timeout. * * Note that this timeout takes the number of seconds, NOT hz (as in * the kernel). */ void timeout(func1, arg, time) int (*func1)(); caddr_t arg; int time; { struct itimerval itv; struct callout *newp, **oldpp; if (debug > 2) fprintf(stderr, "Timeout %x:%x in %d seconds.\n", (int) func1, (int) arg, time); /* * Allocate timeout. */ if ((newp = (struct callout *) malloc(sizeof(struct callout))) == NULL) { fprintf(stderr, "ppp: Out of memory!\n"); exit(1); } newp->c_arg = arg; newp->c_func = func1; /* * Find correct place to link it in and decrement its time by the * amount of time used by preceding timeouts. */ for (oldpp = &callout; *oldpp && (*oldpp)->c_time <= time; oldpp = &(*oldpp)->c_next) time -= (*oldpp)->c_time; newp->c_time = time; newp->c_next = *oldpp; if (*oldpp) (*oldpp)->c_time -= time; *oldpp = newp; /* * If this is now the first callout then we have to set a new * itimer. */ if (callout == newp) { itv.it_interval.tv_sec = itv.it_interval.tv_usec = itv.it_value.tv_usec = 0; itv.it_value.tv_sec = callout->c_time; if (debug > 2) fprintf(stderr, "Setting itimer for %d seconds.\n", itv.it_value.tv_sec); if (setitimer(ITIMER_REAL, &itv, NULL)) { perror("ppp: setitimer(ITIMER_REAL)"); exit(1); } if (gettimeofday(&schedtime, NULL)) { perror("ppp: gettimeofday"); exit(1); } } } /* * untimeout - Unschedule a timeout. */ void untimeout(func1, arg) int (*func1)(); caddr_t arg; { struct itimerval itv; struct callout **copp, *freep; int reschedule = 0; if (debug > 2) fprintf(stderr, "Untimeout %x:%x.\n", (int) func1, (int) arg); /* * If the first callout is unscheduled then we have to set a new * itimer. */ if (callout && callout->c_func == func1 && callout->c_arg == arg) reschedule = 1; /* * Find first matching timeout. Add its time to the next timeouts * time. */ for (copp = &callout; *copp; copp = &(*copp)->c_next) if ((*copp)->c_func == func1 && (*copp)->c_arg == arg) { freep = *copp; *copp = freep->c_next; if (*copp) (*copp)->c_time += freep->c_time; free(freep); break; } if (reschedule) { itv.it_interval.tv_sec = itv.it_interval.tv_usec = itv.it_value.tv_usec = 0; itv.it_value.tv_sec = callout ? callout->c_time : 0; if (debug > 2) fprintf(stderr, "Setting itimer for %d seconds.\n", itv.it_value.tv_sec); if (setitimer(ITIMER_REAL, &itv, NULL)) { perror("ppp: setitimer(ITIMER_REAL)"); exit(1); } if (gettimeofday(&schedtime, NULL)) { perror("ppp: gettimeofday"); exit(1); } } } /* * adjtimeout - Decrement the first timeout by the amount of time since * it was scheduled. */ void adjtimeout() { struct timeval tv; int timediff; if (callout == NULL) return; /* * Make sure that the clock hasn't been warped dramatically. * Account for recently expired, but blocked timer by adding * small fudge factor. */ if (gettimeofday(&tv, NULL)) { perror("ppp: gettimeofday"); exit(1); } timediff = tv.tv_sec - schedtime.tv_sec; if (timediff < 0 || timediff > callout->c_time + 1) return; callout->c_time -= timediff; /* OK, Adjust time */ } /* * output - Output PPP packet. */ void output(unit, p, len) int unit; u_char *p; int len; { #ifdef STREAMS struct strbuf str; #endif if (unit != 0) { fprintf(stderr, "ppp: output: unit != 0!\n"); abort(); } #ifdef STREAMS str.len = len; str.buf = (caddr_t) p; if(putmsg(fd, NULL, &str, 0) < 0) { perror("ppp: putmsg"); exit(1); } #else if (write(fd, p, len) < 0) { perror("ppp: write"); exit(1); } #endif free(p); } /* * hup - Catch SIGHUP signal. * * Indicates that the physical layer has been disconnected. */ void hup() { if (debug > 1) fprintf(stderr, "Hangup\n"); adjtimeout(); /* Adjust timeouts */ lcp_lowerdown(0); /* Reset connection */ } /* * term - Catch SIGTERM signal. * * Indicates that we should initiate a graceful disconnect and exit. */ void term() { if (debug > 1) fprintf(stderr, "Terminate\n"); adjtimeout(); /* Adjust timeouts */ lcp_close(0); /* Close connection */ } /* * intr - Catch SIGINT signal (DEL/^C). * * Indicates that we should initiate a graceful disconnect and exit. */ void intr() { if (debug > 1) fprintf(stderr, "Interrupt\n"); adjtimeout(); /* Adjust timeouts */ lcp_close(0); /* Close connection */ } /* * alrm - Catch SIGALRM signal. * * Indicates a timeout. */ void alrm() { struct itimerval itv; struct callout *freep; if (debug > 1) fprintf(stderr, "Alarm\n"); /* * Call and free first scheduled timeout and any that were scheduled * for the same time. */ while (callout) { freep = callout; /* Remove entry before calling */ callout = freep->c_next; (*freep->c_func)(freep->c_arg); free(freep); if (callout->c_time) break; } /* * Set a new itimer if there are more timeouts scheduled. */ if (callout) { itv.it_interval.tv_sec = itv.it_interval.tv_usec = itv.it_value.tv_usec = 0; itv.it_value.tv_sec = callout->c_time; if (debug > 2) fprintf(stderr, "Setting itimer for %d seconds.\n", itv.it_value.tv_sec); if (setitimer(ITIMER_REAL, &itv, NULL)) { perror("ppp: setitimer(ITIMER_REAL)"); exit(1); } if (gettimeofday(&schedtime, NULL)) { perror("ppp: gettimeofday"); exit(1); } } } /* * io - Catch SIGIO signal. * * Indicates that incoming data is available. */ void io() { int len, i; u_char *p; u_short protocol; #ifdef STREAMS struct strbuf str; #endif if (debug > 1) fprintf(stderr, "IO\n"); adjtimeout(); /* Adjust timeouts */ for (;;) { /* Read all available packets */ p = (u_char *) malloc(MTU + DLLHEADERLEN); #ifdef STREAMS str.maxlen = MTU+DLLHEADERLEN; str.buf = (caddr_t) p; i = 0; len = getmsg(fd, NULL, &str, &i); if(len < 0) { if(errno == EAGAIN || errno == EWOULDBLOCK) { if(debug > 2) perror("ppp: getmsg(fd)"); return; } perror("ppp: getmsg(fd)"); exit(1); } else if(len && debug > 2) fprintf(stderr, "ppp: getmsg returns 0x%x\n",len); if(str.len < 0) { if(debug > 2) fprintf(stderr, "ppp: getmsg short return length %d\n", str.len); return; } len = str.len; #else if ((len = read(fd, p, MTU + DLLHEADERLEN)) < 0) { if (errno == EWOULDBLOCK) { if (debug > 2) perror("ppp: read(fd)"); return; } else { perror("ppp: read(fd)"); exit(1); } } else #endif if (len == 0) { fprintf(stderr, "ppp: End of file on fd!\n"); exit(1); } if (len < DLLHEADERLEN) { if (debug) fprintf(stderr, "ppp: input: Received short packet.\n"); return; } p += 2; /* Skip address and control */ GETSHORT(protocol, p); len -= DLLHEADERLEN; /* * Toss all non-LCP packets unless LCP is OPEN. */ if (protocol != LCP && lcp_fsm[0].state != OPEN) { free(p - DLLHEADERLEN); return; } /* * Upcall the proper protocol input routine. */ for (i = 0; i < sizeof (prottbl) / sizeof (struct protent); i++) if (prottbl[i].protocol == protocol) { (*prottbl[i].input)(0, p, len); break; } if (i == sizeof (prottbl) / sizeof (struct protent)) { if (debug) fprintf(stderr, "ppp: input: Unknown protocol (%x) received!\n", protocol); p -= DLLHEADERLEN; len += DLLHEADERLEN; lcp_sprotrej(0, p, len); } } } /* * demuxprotrej - Demultiplex a Protocol-Reject. */ void demuxprotrej(unit, protocol) int unit; u_short protocol; { int i; /* * Upcall the proper Protocol-Reject routine. */ for (i = 0; i < sizeof (prottbl) / sizeof (struct protent); i++) if (prottbl[i].protocol == protocol) { (*prottbl[i].protrej)(unit); return; } if (debug) fprintf(stderr, "ppp: demuxprotrej: Unrecognized Protocol-Reject!\n"); } /* * incdebug - Catch SIGUSR1 signal. * * Increment debug flag. */ void incdebug() { debug++; } /* * nodebug - Catch SIGUSR2 signal. * * Turn off debugging. */ void nodebug() { debug = 0; } /* * setdebug - Set debug (command line argument). */ int setdebug(argcp, argvp) int *argcp; char ***argvp; { debug++; fsm_debug++; lcp_debug++; ipcp_debug++; upap_debug++; --*argcp, ++*argvp; return (1); } /* * setdial - Set dial (command line argument). */ int setdial(argcp, argvp) int *argcp; char ***argvp; { dial++; --*argcp, ++*argvp; strncpy(dial_cmd, **argvp, 256); --*argcp, ++*argvp; return (1); } /* * noopt - Disable all options. */ int noopt(argcp, argvp) int *argcp; char ***argvp; { bzero(&lcp_wantoptions[0], sizeof (struct lcp_options)); bzero(&lcp_allowoptions[0], sizeof (struct lcp_options)); bzero(&ipcp_wantoptions[0], sizeof (struct ipcp_options)); bzero(&ipcp_allowoptions[0], sizeof (struct ipcp_options)); --*argcp, ++*argvp; return (1); } /* * noaccomp - Disable Address/Control field compression negotiation. */ int noaccomp(argcp, argvp) int *argcp; char ***argvp; { lcp_wantoptions[0].neg_accompression = 0; lcp_allowoptions[0].neg_accompression = 0; --*argcp, ++*argvp; return (1); } /* * noasyncmap - Disable async map negotiation. */ int noasyncmap(argcp, argvp) int *argcp; char ***argvp; { lcp_wantoptions[0].neg_asyncmap = 0; lcp_allowoptions[0].neg_asyncmap = 0; --*argcp, ++*argvp; return (1); } /* * noipaddr - Disable IP address negotiation. */ int noipaddr(argcp, argvp) int *argcp; char ***argvp; { ipcp_wantoptions[0].neg_addrs = 0; ipcp_allowoptions[0].neg_addrs = 0; --*argcp, ++*argvp; return (1); } /* * nomagicnumber - Disable magic number negotiation. */ int nomagicnumber(argcp, argvp) int *argcp; char ***argvp; { lcp_wantoptions[0].neg_magicnumber = 0; lcp_allowoptions[0].neg_magicnumber = 0; --*argcp, ++*argvp; return (1); } /* * nomru - Disable mru negotiation. */ int nomru(argcp, argvp) int *argcp; char ***argvp; { lcp_wantoptions[0].neg_mru = 0; lcp_allowoptions[0].neg_mru = 0; --*argcp, ++*argvp; return (1); } /* * setmru - Set MRU for negotiation. */ int setmru(argcp, argvp) int *argcp; char ***argvp; { --*argcp, ++*argvp; lcp_wantoptions[0].mru = atoi(**argvp); --*argcp, ++*argvp; return (1); } /* * nopcomp - Disable Protocol field compression negotiation. */ int nopcomp(argcp, argvp) int *argcp; char ***argvp; { lcp_wantoptions[0].neg_pcompression = 0; lcp_allowoptions[0].neg_pcompression = 0; --*argcp, ++*argvp; return (1); } /* * setpassive - Set passive mode. */ int setpassive(argcp, argvp) int *argcp; char ***argvp; { lcp_wantoptions[0].passive = 1; --*argcp, ++*argvp; return (1); } /* * noupap - Disable UPAP authentication. */ int noupap(argcp, argvp) int *argcp; char ***argvp; { lcp_allowoptions[0].neg_upap = 0; --*argcp, ++*argvp; return (1); } /* * requpap - Require UPAP authentication. */ int requpap(argcp, argvp) int *argcp; char ***argvp; { lcp_wantoptions[0].neg_upap = 1; lcp_allowoptions[0].neg_upap = 0; --*argcp, ++*argvp; return (1); } /* * novj - Disable Van Jacobson style IP header compression. */ int novj(argcp, argvp) int *argcp; char ***argvp; { ipcp_wantoptions[0].neg_vj = 0; ipcp_allowoptions[0].neg_vj = 0; --*argcp, ++*argvp; return (1); } /* * setold - Set backward compatibility mode */ int setold(argcp, argvp) int *argcp; char ***argvp; { extern short ip_vj_comp; ip_vj_comp = 0x0037; --*argcp, ++*argvp; return (1); } /* * Valid speeds. */ struct speed { int speed_int, speed_val; } speeds[] = { #ifdef B50 { 50, B50 }, #endif #ifdef B75 { 75, B75 }, #endif #ifdef B110 { 110, B110 }, #endif #ifdef B150 { 150, B150 }, #endif #ifdef B200 { 200, B200 }, #endif #ifdef B300 { 300, B300 }, #endif #ifdef B600 { 600, B600 }, #endif #ifdef B1200 { 1200, B1200 }, #endif #ifdef B1800 { 1800, B1800 }, #endif #ifdef B2000 { 2000, B2000 }, #endif #ifdef B2400 { 2400, B2400 }, #endif #ifdef B3600 { 3600, B3600 }, #endif #ifdef B4800 { 4800, B4800 }, #endif #ifdef B7200 { 7200, B7200 }, #endif #ifdef B9600 { 9600, B9600 }, #endif #ifdef EXTA { 19200, EXTA }, #endif #ifdef EXTB { 38400, EXTB }, #endif { 0, 0 } }; int setasyncmap(argcp, argvp) int *argcp; char ***argvp; { unsigned long asyncmap; asyncmap = 0xffffffff; ++*argvp; sscanf(**argvp,"%lx",&asyncmap); ++*argvp; lcp_wantoptions[0].asyncmap = asyncmap; *argcp -= 2; return(1); } /* * setspeed - Set the speed. */ int setspeed(argcp, argvp) int *argcp; char ***argvp; { int speed; struct speed *speedp; speed = atoi(**argvp); for (speedp = speeds; speedp->speed_int; speedp++) if (speed == speedp->speed_int) { inspeed = speedp->speed_val; --*argcp, ++*argvp; return (1); } return (0); } /* * setdevname - Set the device name. */ int setdevname(argcp, argvp) int *argcp; char ***argvp; { char dev[DEVNAME_SIZE]; char *cp = **argvp; struct stat statbuf; char *tty, *ttyname(); if (strncmp("/dev/", cp, sizeof ("/dev/") - 1)) { (void) sprintf(dev, "/dev/%s", cp); cp = dev; } /* * Check if there is a device by this name. */ if (stat(cp, &statbuf) < 0) { if (errno == ENOENT) return (0); perror(cp); exit(1); } strcpy(devname, cp); --*argcp, ++*argvp; /* * If we haven't already decided to require authentication, * or we are running ppp on the control terminal, then we can * allow authentication to be requested. */ if ((tty = ttyname(fileno(stdin))) == NULL) tty = ""; /* running from init means no stdin. Null kills strcmp -KWK */ if (lcp_wantoptions[0].neg_upap == 0 && strcmp(devname, "/dev/tty") && strcmp(devname, tty)) { lcp_wantoptions[0].neg_upap = 0; lcp_allowoptions[0].neg_upap = 1; } return (1); } /* * setipaddr - Set the IP address */ int setipaddr(argcp, argvp) int *argcp; char ***argvp; { u_long local, remote; struct hostent *hp; char *colon, *index(); /* * IP address pair separated by ":". */ if ((colon = index(**argvp, ':')) == NULL) return (0); /* * If colon first character, then no local addr. */ if (colon == **argvp) { local = 0l; ++colon; } else { *colon++ = '\0'; if ((local = inet_addr(**argvp)) == -1) { if ((hp = gethostbyname(**argvp)) == NULL) { fprintf(stderr, "unknown host: %s\n", **argvp); goto ret; } bcopy(hp->h_addr, (char *) &local, hp->h_length); } } /* * If colon last character, then no remote addr. */ if (*colon == '\0') remote = 0l; else { if ((remote = inet_addr(colon)) == -1) { if ((hp = gethostbyname(colon)) == NULL) { fprintf(stderr, "unknown host: %s\n", colon); goto ret; } bcopy(hp->h_addr, (char *) &remote, hp->h_length); } } ipcp_wantoptions[0].neg_addrs = 1; ipcp_wantoptions[0].ouraddr = local; ipcp_wantoptions[0].hisaddr = remote; ret: --*argcp, ++*argvp; return (1); } /* * getuserpasswd - Get the user name and passwd. */ void getuserpasswd() { struct passwd *pw, *getpwuid(); char *getlogin(), *getpass(); /* * Prompt for user name with a default value. Default is * the last value if any, or the login name or the user name. */ if (upap[0].us_user == NULL && (upap[0].us_user = getlogin()) == NULL && (pw = getpwuid(getuid())) != NULL) upap[0].us_user = pw->pw_name; printf("Login (%s): ", upap[0].us_user); fgets(user, sizeof (user) - 1, stdin); user[strlen(user) - 1] = '\0'; if (user[0] != '\0') /* Choosing the default? */ upap[0].us_user = user; upap[0].us_userlen = strlen(upap[0].us_user); upap[0].us_passwd = getpass("Password: "); upap[0].us_passwdlen = strlen(upap[0].us_passwd); } /* * login - Check the user name and passwd and login the user. * * returns: * UPAP_AUTHNAK: Login failed. * UPAP_AUTHACK: Login succeeded. * In either case, msg points to an appropriate message. */ u_char login(user, userlen, passwd, passwdlen, msg, msglen) char *user; int userlen; char *passwd; int passwdlen; char **msg; int *msglen; { struct passwd *pw; char *epasswd, *crypt(); static int attempts = 0; char *tty, *rindex(); *(user + userlen) = '\0'; *(passwd + passwdlen) = '\0'; if ((pw = getpwnam(user)) == NULL) { *msg = "Login incorrect"; *msglen = strlen(*msg); if(debug > 2) fprintf(stderr,"ppp: upap login userid '%s' incorrect\n",user); return (UPAP_AUTHNAK); } /* * XXX If no passwd, let them login without one. */ if (pw->pw_passwd == '\0') { *msg = "Login ok"; *msglen = strlen(*msg); return (UPAP_AUTHACK); } epasswd = crypt(passwd, pw->pw_passwd); if (strcmp(epasswd, pw->pw_passwd)) { *msg = "Login incorrect"; *msglen = strlen(*msg); if(debug > 2) fprintf(stderr, "ppp: upap login password '%s' incorrect\n", passwd); /* * Frustrate passwd stealer programs. * Allow 10 tries, but start backing off after 3 (stolen from login). * On 10'th, drop the connection. */ if (attempts++ >= 10) { syslog(LOG_NOTICE, "%d LOGIN FAILURES ON %s, %s", attempts, devname, user); lcp_close(0); /* Drop DTR? */ } if (attempts > 3) sleep((u_int) (attempts - 3) * 5); return (UPAP_AUTHNAK); } attempts = 0; /* Reset count */ *msg = "Login ok"; *msglen = strlen(*msg); if(debug > 2) fprintf(stderr,"ppp: upap login and password OK\n"); tty = rindex(devname, '/'); if (tty == NULL) tty = devname; else tty++; logwtmp(tty, user, ""); /* Add wtmp login entry */ return (UPAP_AUTHACK); } /* * logout - Logout the user. */ void logout() { char *tty; tty = rindex(devname, '/'); if (tty == NULL) tty = devname; else tty++; logwtmp(tty, "", ""); /* Add wtmp logout entry */ } /* * getuseropt - Get the options from /etc/hosts.ppp for this user. */ int getuseropt(user) char *user; { char buf[1024], *s; FILE *fp; int rc = 0; if ((fp = fopen(PPPHOSTS, "r")) == NULL) return (0);; /* * Loop till we find an entry for this user. */ for (;;) { if (fgets(buf, sizeof (buf), fp) == NULL) { if (feof(fp)) break; else { perror("fgets"); exit(1); } } if ((s = index(buf, ' ')) == NULL) continue; *s++ = '\0'; if (!strcmp(user, buf)) { rc = 1; break; } } fclose(fp); return (rc); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.