/* * PPPCMD.C -- PPP related user commands * * This implementation of PPP is declared to be in the public domain. * * Jan 91 Bill_Simpson@um.cc.umich.edu * Computer Systems Consulting Services * * Acknowledgements and correction history may be found in PPP.C */ #include #include #include "global.h" #include "mbuf.h" #include "iface.h" #include "pktdrvr.h" #include "ppp.h" #include "pppfsm.h" #include "pppipcp.h" #include "ppppap.h" #include "ppplcp.h" #include "cmdparse.h" static struct iface *ppp_lookup __ARGS((char *ifname)); static int doppp_quick __ARGS((int argc, char *argv[], void *p)); static int doppp_trace __ARGS((int argc, char *argv[], void *p)); static void genstat __ARGS((struct ppp_s *ppp_p)); static void lcpstat __ARGS((struct fsm_s *fsm_p)); static void papstat __ARGS((struct fsm_s *fsm_p)); static void ipcpstat __ARGS((struct fsm_s *fsm_p)); static int dotry_nak __ARGS((int argc, char *argv[], void *p)); static int dotry_req __ARGS((int argc, char *argv[], void *p)); static int dotry_terminate __ARGS((int argc, char *argv[], void *p)); static char *uptime __ARGS((long first, long second)); /* "ppp" subcommands */ static struct cmds Pppcmds[] = { "ipcp", doppp_ipcp, 0, 0, NULLCHAR, "lcp", doppp_lcp, 0, 0, NULLCHAR, "pap", doppp_pap, 0, 0, NULLCHAR, "quick", doppp_quick, 0, 0, NULLCHAR, "trace", doppp_trace, 0, 0, NULLCHAR, NULLCHAR, }; /* "ppp try" subcommands */ static struct cmds PppTrycmds[] = { "configure", dotry_req, 0, 0, NULLCHAR, "failure", dotry_nak, 0, 0, NULLCHAR, "terminate", dotry_terminate, 0, 0, NULLCHAR, NULLCHAR, }; static char *PPPStatus[] = { "Physical Line Down", "Link Control Phase", "Authentication Phase", "Ready for traffic", "Termination Phase" }; static char *NCPStatus[] = { "Closed", "Listen -- waiting for remote host to attempt open", "Starting configuration exchange", "Remote host accepted our request; waiting for remote request", "We accepted remote request; waiting for reply to our request", "Open", "Terminate request sent to remote host" }; int PPPtrace; /****************************************************************************/ static struct iface * ppp_lookup(ifname) char *ifname; { register struct iface *ifp; if ((ifp = if_lookup(ifname)) == NULLIF) { tprintf("%s: Interface unknown\n",ifname); return(NULLIF); } if (ifp->type != CL_PPP) { tprintf("%s: not a PPP interface\n",ifp->name); return(NULLIF); } return(ifp); } /****************************************************************************/ int doppp_commands(argc,argv,p) int argc; char *argv[]; void *p; { register struct iface *ifp; if (argc < 2) { tprintf( "ppp required\n" ); return -1; } if ((ifp = ppp_lookup(argv[1])) == NULLIF) return -1; if (argc == 2 ) return ppp_status( ifp ); return subcmd(Pppcmds, argc - 1, &argv[1], ifp); } /* Close connection on PPP interface */ int doppp_close(argc,argv,p) int argc; char *argv[]; void *p; { register struct fsm_s *fsm_p = p; fsm_p->flags &= ~(FSM_ACTIVE | FSM_PASSIVE); fsm_close( fsm_p ); return 0; } int doppp_passive(argc,argv,p) int argc; char *argv[]; void *p; { register struct fsm_s *fsm_p = p; fsm_p->flags &= ~FSM_ACTIVE; fsm_p->flags |= FSM_PASSIVE; fsm_start(fsm_p); return 0; } int doppp_active(argc,argv,p) int argc; char *argv[]; void *p; { register struct fsm_s *fsm_p = p; fsm_p->flags &= ~FSM_PASSIVE; fsm_p->flags |= FSM_ACTIVE; if ( fsm_p->state < fsmLISTEN ) { fsm_p->state = fsmLISTEN; } return 0; } static int doppp_quick(argc,argv,p) int argc; char *argv[]; void *p; { register struct iface *ifp = p; register struct ppp_s *ppp_p = ifp->extension; struct lcp_s *lcp_p = ppp_p->fsm[Lcp].pdv; struct ipcp_s *ipcp_p = ppp_p->fsm[IPcp].pdv; lcp_p->local.want.accm = 0L; lcp_p->local.want.negotiate |= LCP_N_ACCM; lcp_p->local.want.magic_number = Clock | 0x80000000L; lcp_p->local.want.negotiate |= LCP_N_MAGIC; lcp_p->local.want.negotiate |= LCP_N_ACFC; lcp_p->local.want.negotiate |= LCP_N_PFC; ipcp_p->local.want.compression = PPP_COMPR_PROTOCOL; ipcp_p->local.want.slots = 16; ipcp_p->local.want.slot_compress = 1; ipcp_p->local.want.negotiate |= IPCP_N_COMPRESS; doppp_active( 0, NULL, &(ppp_p->fsm[IPcp]) ); return 0; } /****************************************************************************/ int ppp_discard(ifp,bp) struct iface *ifp; struct mbuf *bp; { struct ppp_s *ppp_p = ifp->extension; return fsm_send(&(ppp_p->fsm[Lcp]), DISCARD_REQ, 0, bp); } int ppp_echo(ifp,bp) struct iface *ifp; struct mbuf *bp; { struct ppp_s *ppp_p = ifp->extension; return fsm_send(&(ppp_p->fsm[Lcp]), ECHO_REQ, 0, bp); } /****************************************************************************/ int ppp_status(ifp) struct iface *ifp; { register struct ppp_s *ppp_p = ifp->extension; genstat(ppp_p); if ( ppp_p->fsm[Lcp].pdv != NULL ) lcpstat(&(ppp_p->fsm[Lcp])); if ( ppp_p->fsm[Pap].pdv != NULL ) papstat(&(ppp_p->fsm[Pap])); if ( ppp_p->fsm[IPcp].pdv != NULL ) ipcpstat(&(ppp_p->fsm[IPcp])); return 0; } static void genstat(ppp_p) register struct ppp_s *ppp_p; { tprintf("%s", ppp_p->iface->name, PPPStatus[ppp_p->phase]); if (ppp_p->phase == pppREADY) { tprintf("\t(open for %s)", uptime(ppp_p->upsince,time(0L))); } tprintf("\n"); tprintf(" In" "\t%10ld Pkts,%10ld Flag,%6d Err,%6d ChksumErr\n", ppp_p->InRxPacketCount, ppp_p->InOpenFlag, ppp_p->InError, ppp_p->InChecksum); tprintf("\t%10ld Ip, %6d Lcp,%6d Pap,%6d IPcp,%6d Unknown\n", ppp_p->InIP, ppp_p->InNCP[Lcp], ppp_p->InNCP[Pap], ppp_p->InNCP[IPcp], ppp_p->InUnknown); tprintf(" Out" "\t%10ld Pkts,%10ld Flag,%6d Err\n", ppp_p->OutTxPacketCount, ppp_p->OutOpenFlag, ppp_p->OutError); tprintf("\t%10ld Ip, %6d Lcp,%6d Pap,%6d IPcp\n", ppp_p->OutIP, ppp_p->OutNCP[Lcp], ppp_p->OutNCP[Pap], ppp_p->OutNCP[IPcp]); } static void lcpstat(fsm_p) struct fsm_s *fsm_p; { struct lcp_s *lcp_p = fsm_p->pdv; struct lcp_value_s *localp = &(lcp_p->local.work); struct lcp_value_s *remotep = &(lcp_p->remote.work); tprintf("LCP %s\n", NCPStatus[fsm_p->state]); tprintf("\t\tMRU\tACCM\t\tAP\tPFC ACFC Magic\n"); tprintf("\tLocal:\t"); if ( localp->negotiate & LCP_N_MRU ) { tprintf( "%4d\t", localp->mru ); } else { tprintf( "default\t" ); } if ( localp->negotiate & LCP_N_ACCM ) { tprintf( "0x%08lx\t", localp->accm ); } else { tprintf( "default\t\t" ); } if ( localp->negotiate & LCP_N_AUTHENT ) { switch ( localp->authentication ) { case PPP_PAP_PROTOCOL: tprintf("Pap\t"); break; default: tprintf("0x%04x\t", localp->authentication); break; }; } else { tprintf("None\t"); } tprintf((localp->negotiate & LCP_N_PFC) ? "Yes " : "No "); tprintf((localp->negotiate & LCP_N_ACFC) ? "Yes " : "No "); if ( localp->magic_number != 0L ) { tprintf( " 0x%08lx\n", localp->magic_number ); } else { tprintf( " unused\n" ); } tprintf("\tRemote:\t"); if ( remotep->negotiate & LCP_N_MRU ) { tprintf( "%4d\t", remotep->mru ); } else { tprintf( "default\t" ); } if ( remotep->negotiate & LCP_N_ACCM ) { tprintf( "0x%08lx\t", remotep->accm ); } else { tprintf( "default\t\t" ); } if ( remotep->negotiate & LCP_N_AUTHENT ) { switch ( remotep->authentication ) { case PPP_PAP_PROTOCOL: tprintf("Pap\t"); break; default: tprintf("0x%04x\t", remotep->authentication); break; }; } else { tprintf("None\t"); } tprintf((remotep->negotiate & LCP_N_PFC) ? "Yes " : "No "); tprintf((remotep->negotiate & LCP_N_ACFC) ? "Yes " : "No "); if ( remotep->negotiate & LCP_N_MAGIC ) { tprintf( " 0x%08lx\n", remotep->magic_number ); } else { tprintf( " unused\n" ); } } static void papstat(fsm_p) struct fsm_s *fsm_p; { struct pap_s *pap_p = fsm_p->pdv; tprintf("PAP %s\n", NCPStatus[fsm_p->state]); tprintf( "\tMessage: '%s'\n", (pap_p->message == NULL) ? "none" : pap_p->message ); } static void ipcpstat(fsm_p) struct fsm_s *fsm_p; { struct ipcp_s *ipcp_p = fsm_p->pdv; struct ipcp_value_s *localp = &(ipcp_p->local.work); struct ipcp_value_s *remotep = &(ipcp_p->remote.work); tprintf("IPCP %s\n", NCPStatus[fsm_p->state]); tprintf("\tlocal IP address: %s", inet_ntoa(localp->address)); tprintf("\tremote IP address: %s\n", inet_ntoa(localp->other)); if (localp->negotiate & IPCP_N_COMPRESS) { tprintf(" In\tTCP header compression enabled:" " slots = %d, flag = 0x%02x\n", localp->slots, localp->slot_compress); slhc_i_status(ipcp_p->slhcp); } if (remotep->negotiate & IPCP_N_COMPRESS) { tprintf(" Out\tTCP header compression enabled:" " slots = %d, flag = 0x%02x\n", remotep->slots, remotep->slot_compress); slhc_o_status(ipcp_p->slhcp); } } /****************************************************************************/ /* Set timeout interval when waiting for response from remote peer */ int doppp_timeout(argc,argv,p) int argc; char *argv[]; void *p; { struct fsm_s *fsm_p = p; struct timer *t = &(fsm_p->timer); if (argc < 2) { tprintf("%d\n",dur_timer(t)/1000L); } else { int x = (int)strtol( argv[1], NULLCHARP, 0 ); if (x <= 0) { tprintf("Timeout value %s (%d) must be > 0\n", argv[1], x); return -1; } else { set_timer(t, x * 1000L); } } return 0; } int doppp_try(argc,argv,p) int argc; char *argv[]; void *p; { return subcmd(PppTrycmds, argc, argv, p); } static int dotry_nak(argc,argv,p) int argc; char *argv[]; void *p; { struct fsm_s *fsm_p = p; if (argc < 2) { tprintf("%d\n",fsm_p->try_nak); } else { int x = (int)strtol( argv[1], NULLCHARP, 0 ); if (x <= 0) { tprintf("Value %s (%d) must be > 0\n", argv[1], x); return -1; } else { fsm_p->try_nak = x; } } return 0; } static int dotry_req(argc,argv,p) int argc; char *argv[]; void *p; { struct fsm_s *fsm_p = p; if (argc < 2) { tprintf("%d\n",fsm_p->try_req); } else { int x = (int)strtol( argv[1], NULLCHARP, 0 ); if (x <= 0) { tprintf("Value %s (%d) must be > 0\n", argv[1], x); return -1; } else { fsm_p->try_req = x; } } return 0; } static int dotry_terminate(argc,argv,p) int argc; char *argv[]; void *p; { struct fsm_s *fsm_p = p; if (argc < 2) { tprintf("%d\n",fsm_p->try_terminate); } else { int x = (int)strtol( argv[1], NULLCHARP, 0 ); if (x <= 0) { tprintf("Value %s (%d) must be > 0\n", argv[1], x); return -1; } else { fsm_p->try_terminate = x; } } return 0; } static int doppp_trace(argc,argv,p) int argc; char *argv[]; void *p; { register struct iface *ifp = p; register struct ppp_s *ppp_p = ifp->extension; int tracing = ppp_p->trace; int result = setint(&tracing,"PPP tracing",argc,argv); ppp_p->trace = tracing; return result; } /****************************************************************************/ /* Break a time differential, measured in seconds, into weeks, days */ /* hours, minutes, and seconds. Store ASCII description in static buffer */ #define SECS_MIN 60L #define SECS_HR 3600L #define SECS_DAY 86400L #define SECS_WEEK 604800L static char utbuf[128]; static char * uptime(first, second) long first; long second; { int found = 0; long diff; long part; utbuf[0] = '\0'; diff = second - first; if ((diff > SECS_DAY)||(found)) { part = diff / SECS_DAY; sprintf(&(utbuf[strlen(utbuf)]), "%ld day%s ",part,((part==1)?",":"s,")); diff -= (part * SECS_DAY); found = 100; } if ((diff > SECS_HR)||(found)) { part = diff / SECS_HR; sprintf(&(utbuf[strlen(utbuf)]), "%ld hr%s ",part,((part==1)?",":"s,")); diff -= (part * SECS_HR); ++found; } if ((diff > SECS_MIN)||(found)) { part = diff / SECS_MIN; sprintf(&(utbuf[strlen(utbuf)]),"%ld mi%s",part, ((found < 100)?"n, ":"n")); diff -= (part * SECS_MIN); } if (found < 100) sprintf(&(utbuf[strlen(utbuf)]),"%ld sec",diff); return(utbuf); }