Import pppd onto the vendor branch from the ppp-2.2 package..

This commit is contained in:
Peter Wemm 1995-10-31 21:11:19 +00:00
parent 560c30efa3
commit 945f93070b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/cvs2svn/branches/MACKERAS/; revision=11981
26 changed files with 2344 additions and 3986 deletions

View File

@ -1,10 +1,14 @@
# From: Id: Makefile.bsd,v 1.4 1994/04/20 00:07:50 paulus Exp
# $Id$
# $Id: Makefile.bsd,v 1.7 1995/04/27 00:19:50 paulus Exp $
BINDIR?= /usr/sbin
CFLAGS+= -I.. -DHAVE_PATHS_H
PROG= pppd
SRCS= main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c \
auth.c options.c lock.c sys-bsd.c
MAN8= pppd.8
SRCS= main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c \
auth.c options.c sys-bsd.c
MAN8= pppd.0
# The next line is for NetBSD-current systems.
MAN= pppd.cat8
BINMODE=4555
BINOWN= root

View File

@ -33,11 +33,12 @@
*/
#ifndef lint
static char rcsid[] = "$Id: auth.c,v 1.6 1994/05/25 06:25:05 paulus Exp $";
static char rcsid[] = "$Id: auth.c,v 1.17 1995/08/16 01:37:22 paulus Exp $";
#endif
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <syslog.h>
#include <pwd.h>
#include <string.h>
@ -48,16 +49,24 @@ static char rcsid[] = "$Id: auth.c,v 1.6 1994/05/25 06:25:05 paulus Exp $";
#include <netinet/in.h>
#include <arpa/inet.h>
#include "ppp.h"
#ifdef HAS_SHADOW
#include <shadow.h>
#include <shadow/pwauth.h>
#ifndef PW_PPP
#define PW_PPP PW_LOGIN
#endif
#endif
#include "pppd.h"
#include "fsm.h"
#include "lcp.h"
#include "upap.h"
#include "chap.h"
#include "ipcp.h"
#include "ccp.h"
#include "pathnames.h"
#ifdef sparc
#if defined(sun) && defined(sparc)
#include <alloca.h>
#endif /*sparc*/
@ -76,20 +85,10 @@ struct wordlist {
#define FALSE 0
#define TRUE 1
extern char user[];
extern char passwd[];
extern char devname[];
extern char our_name[];
extern char remote_name[];
extern char hostname[];
extern int uselogin;
extern int usehostname;
extern int auth_required;
/* Records which authentication operations haven't completed yet. */
static int auth_pending[NPPP];
static int auth_pending[NUM_PPP];
static int logged_in;
static struct wordlist *addresses[NPPP];
static struct wordlist *addresses[NUM_PPP];
/* Bits in auth_pending[] */
#define UPAP_WITHPEER 1
@ -98,19 +97,20 @@ static struct wordlist *addresses[NPPP];
#define CHAP_PEER 8
/* Prototypes */
void check_access __ARGS((FILE *, char *));
void check_access __P((FILE *, char *));
static int login __ARGS((char *, char *, char **, int *));
static void logout __ARGS((void));
static int null_login __ARGS((int));
static int get_upap_passwd __ARGS((void));
static int have_upap_secret __ARGS((void));
static int have_chap_secret __ARGS((char *, char *));
static int scan_authfile __ARGS((FILE *, char *, char *, char *,
static void network_phase __P((int));
static int login __P((char *, char *, char **, int *));
static void logout __P((void));
static int null_login __P((int));
static int get_upap_passwd __P((void));
static int have_upap_secret __P((void));
static int have_chap_secret __P((char *, char *));
static int scan_authfile __P((FILE *, char *, char *, char *,
struct wordlist **, char *));
static void free_wordlist __ARGS((struct wordlist *));
static void free_wordlist __P((struct wordlist *));
extern char *crypt __ARGS((char *, char *));
extern char *crypt __P((char *, char *));
/*
* An Open on LCP has requested a change from Dead to Establish phase.
@ -130,6 +130,8 @@ void
link_terminated(unit)
int unit;
{
if (phase == PHASE_DEAD)
return;
if (logged_in)
logout();
phase = PHASE_DEAD;
@ -143,6 +145,8 @@ void
link_down(unit)
int unit;
{
ipcp_close(0);
ccp_close(0);
phase = PHASE_TERMINATE;
}
@ -165,7 +169,7 @@ link_established(unit)
* treat it as though it authenticated with PAP using a username
* of "" and a password of "". If that's not OK, boot it out.
*/
if (wo->neg_upap && !null_login(unit)) {
if (!wo->neg_upap || !null_login(unit)) {
syslog(LOG_WARNING, "peer refused to authenticate");
lcp_close(unit);
phase = PHASE_TERMINATE;
@ -191,10 +195,20 @@ link_established(unit)
}
auth_pending[unit] = auth;
if (!auth) {
phase = PHASE_NETWORK;
ipcp_open(unit);
}
if (!auth)
network_phase(unit);
}
/*
* Proceed to the network phase.
*/
static void
network_phase(unit)
int unit;
{
phase = PHASE_NETWORK;
ipcp_open(unit);
ccp_open(unit);
}
/*
@ -221,10 +235,10 @@ auth_peer_success(unit, protocol)
int bit;
switch (protocol) {
case CHAP:
case PPP_CHAP:
bit = CHAP_PEER;
break;
case UPAP:
case PPP_PAP:
bit = UPAP_PEER;
break;
default:
@ -240,6 +254,7 @@ auth_peer_success(unit, protocol)
if ((auth_pending[unit] &= ~bit) == 0) {
phase = PHASE_NETWORK;
ipcp_open(unit);
ccp_open(unit);
}
}
@ -267,10 +282,10 @@ auth_withpeer_success(unit, protocol)
int bit;
switch (protocol) {
case CHAP:
case PPP_CHAP:
bit = CHAP_WITHPEER;
break;
case UPAP:
case PPP_PAP:
bit = UPAP_WITHPEER;
break;
default:
@ -283,10 +298,8 @@ auth_withpeer_success(unit, protocol)
* If there is no more authentication still being done,
* proceed to the network phase.
*/
if ((auth_pending[unit] &= ~bit) == 0) {
phase = PHASE_NETWORK;
ipcp_open(unit);
}
if ((auth_pending[unit] &= ~bit) == 0)
network_phase(unit);
}
@ -386,7 +399,7 @@ check_passwd(unit, auser, userlen, apasswd, passwdlen, msg, msglen)
} else {
check_access(f, filename);
if (scan_authfile(f, user, our_name, secret, &addrs, filename) < 0
|| (secret[0] != 0 && strcmp(passwd, secret) != 0
|| (secret[0] != 0 && (cryptpap || strcmp(passwd, secret) != 0)
&& strcmp(crypt(passwd, secret), secret) != 0)) {
syslog(LOG_WARNING, "upap authentication failure for %s", user);
ret = UPAP_AUTHNAK;
@ -411,7 +424,7 @@ check_passwd(unit, auser, userlen, apasswd, passwdlen, msg, msglen)
*/
if (attempts++ >= 10) {
syslog(LOG_WARNING, "%d LOGIN FAILURES ON %s, %s",
attempts, devname, user);
attempts, devnam, user);
quit();
}
if (attempts > 3)
@ -452,10 +465,23 @@ login(user, passwd, msg, msglen)
char *epasswd;
char *tty;
#ifdef HAS_SHADOW
struct spwd *spwd;
struct spwd *getspnam();
#endif
if ((pw = getpwnam(user)) == NULL) {
return (UPAP_AUTHNAK);
}
#ifdef HAS_SHADOW
if ((spwd = getspnam(user)) == NULL) {
pw->pw_passwd = "";
} else {
pw->pw_passwd = spwd->sp_pwdp;
}
#endif
/*
* XXX If no passwd, let them login without one.
*/
@ -463,21 +489,27 @@ login(user, passwd, msg, msglen)
return (UPAP_AUTHACK);
}
#ifdef HAS_SHADOW
if ((pw->pw_passwd && pw->pw_passwd[0] == '@'
&& pw_auth (pw->pw_passwd+1, pw->pw_name, PW_PPP, NULL))
|| !valid (passwd, pw)) {
return (UPAP_AUTHNAK);
}
#else
epasswd = crypt(passwd, pw->pw_passwd);
if (strcmp(epasswd, pw->pw_passwd)) {
return (UPAP_AUTHNAK);
}
#endif
syslog(LOG_INFO, "user %s logged in", user);
/*
* Write a wtmp entry for this user.
*/
tty = strrchr(devname, '/');
if (tty == NULL)
tty = devname;
else
tty++;
tty = devnam;
if (strncmp(tty, "/dev/", 5) == 0)
tty += 5;
logwtmp(tty, user, ""); /* Add wtmp login entry */
logged_in = TRUE;
@ -492,11 +524,9 @@ logout()
{
char *tty;
tty = strrchr(devname, '/');
if (tty == NULL)
tty = devname;
else
tty++;
tty = devnam;
if (strncmp(tty, "/dev/", 5) == 0)
tty += 5;
logwtmp(tty, "", ""); /* Wipe out wtmp logout entry */
logged_in = FALSE;
}
@ -688,9 +718,9 @@ get_secret(unit, client, server, secret, secret_len, save_addrs)
int
auth_ip_addr(unit, addr)
int unit;
u_long addr;
u_int32_t addr;
{
u_long a;
u_int32_t a;
struct hostent *hp;
struct wordlist *addrs;
@ -711,7 +741,7 @@ auth_ip_addr(unit, addr)
addrs->word);
continue;
} else
a = *(u_long *)hp->h_addr;
a = *(u_int32_t *)hp->h_addr;
}
if (addr == a)
return 1;
@ -726,7 +756,7 @@ auth_ip_addr(unit, addr)
*/
int
bad_ip_adrs(addr)
u_long addr;
u_int32_t addr;
{
addr = ntohl(addr);
return (addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET

View File

@ -19,7 +19,7 @@
*/
#ifndef lint
static char rcsid[] = "$Id: chap.c,v 1.3 1994/04/18 04:01:07 paulus Exp $";
static char rcsid[] = "$Id: chap.c,v 1.8 1995/07/04 12:32:26 paulus Exp $";
#endif
/*
@ -27,30 +27,30 @@ static char rcsid[] = "$Id: chap.c,v 1.3 1994/04/18 04:01:07 paulus Exp $";
*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <syslog.h>
#include "ppp.h"
#include "pppd.h"
#include "chap.h"
#include "md5.h"
chap_state chap[NPPP]; /* CHAP state; one for each unit */
chap_state chap[NUM_PPP]; /* CHAP state; one for each unit */
static void ChapChallengeTimeout __ARGS((caddr_t));
static void ChapResponseTimeout __ARGS((caddr_t));
static void ChapReceiveChallenge __ARGS((chap_state *, u_char *, int, int));
static void ChapReceiveResponse __ARGS((chap_state *, u_char *, int, int));
static void ChapReceiveSuccess __ARGS((chap_state *, u_char *, int, int));
static void ChapReceiveFailure __ARGS((chap_state *, u_char *, int, int));
static void ChapSendStatus __ARGS((chap_state *, int));
static void ChapSendChallenge __ARGS((chap_state *));
static void ChapSendResponse __ARGS((chap_state *));
static void ChapGenChallenge __ARGS((chap_state *));
static void ChapChallengeTimeout __P((caddr_t));
static void ChapResponseTimeout __P((caddr_t));
static void ChapReceiveChallenge __P((chap_state *, u_char *, int, int));
static void ChapReceiveResponse __P((chap_state *, u_char *, int, int));
static void ChapReceiveSuccess __P((chap_state *, u_char *, int, int));
static void ChapReceiveFailure __P((chap_state *, u_char *, int, int));
static void ChapSendStatus __P((chap_state *, int));
static void ChapSendChallenge __P((chap_state *));
static void ChapSendResponse __P((chap_state *));
static void ChapGenChallenge __P((chap_state *));
extern double drand48 __ARGS((void));
extern void srand48 __ARGS((long));
extern double drand48 __P((void));
extern void srand48 __P((long));
/*
* ChapInit - Initialize a CHAP unit.
@ -67,7 +67,7 @@ ChapInit(unit)
cstate->serverstate = CHAPSS_INITIAL;
cstate->timeouttime = CHAP_DEFTIMEOUT;
cstate->max_transmits = CHAP_DEFTRANSMITS;
srand48((long) time(NULL)); /* joggle random number generator */
/* random number generator is initialized in magic_init */
}
@ -148,7 +148,7 @@ ChapChallengeTimeout(arg)
/* give up on peer */
syslog(LOG_ERR, "Peer failed to respond to CHAP challenge");
cstate->serverstate = CHAPSS_BADAUTH;
auth_peer_fail(cstate->unit, CHAP);
auth_peer_fail(cstate->unit, PPP_CHAP);
return;
}
@ -189,9 +189,6 @@ ChapRechallenge(arg)
ChapGenChallenge(cstate);
ChapSendChallenge(cstate);
cstate->serverstate = CHAPSS_RECHALLENGE;
if (cstate->chal_interval != 0)
TIMEOUT(ChapRechallenge, (caddr_t) cstate, cstate->chal_interval);
}
@ -258,10 +255,10 @@ ChapProtocolReject(unit)
if (cstate->serverstate != CHAPSS_INITIAL &&
cstate->serverstate != CHAPSS_CLOSED)
auth_peer_fail(unit, CHAP);
auth_peer_fail(unit, PPP_CHAP);
if (cstate->clientstate != CHAPCS_INITIAL &&
cstate->clientstate != CHAPCS_CLOSED)
auth_withpeer_fail(unit, CHAP);
auth_withpeer_fail(unit, PPP_CHAP);
ChapLowerDown(unit); /* shutdown chap */
}
@ -506,7 +503,7 @@ ChapReceiveResponse(cstate, inp, id, len)
MD5Final(&mdContext);
/* compare local and remote MDs and send the appropriate status */
if (bcmp (mdContext.digest, remmd, MD5_SIGNATURE_SIZE) == 0)
if (memcmp (mdContext.digest, remmd, MD5_SIGNATURE_SIZE) == 0)
code = CHAP_SUCCESS; /* they are the same! */
break;
@ -521,7 +518,7 @@ ChapReceiveResponse(cstate, inp, id, len)
old_state = cstate->serverstate;
cstate->serverstate = CHAPSS_OPEN;
if (old_state == CHAPSS_INITIAL_CHAL) {
auth_peer_success(cstate->unit, CHAP);
auth_peer_success(cstate->unit, PPP_CHAP);
}
if (cstate->chal_interval != 0)
TIMEOUT(ChapRechallenge, (caddr_t) cstate, cstate->chal_interval);
@ -529,7 +526,7 @@ ChapReceiveResponse(cstate, inp, id, len)
} else {
syslog(LOG_ERR, "CHAP peer authentication failed");
cstate->serverstate = CHAPSS_BADAUTH;
auth_peer_fail(cstate->unit, CHAP);
auth_peer_fail(cstate->unit, PPP_CHAP);
}
}
@ -567,7 +564,7 @@ ChapReceiveSuccess(cstate, inp, id, len)
cstate->clientstate = CHAPCS_OPEN;
auth_withpeer_success(cstate->unit, CHAP);
auth_withpeer_success(cstate->unit, PPP_CHAP);
}
@ -602,7 +599,7 @@ ChapReceiveFailure(cstate, inp, id, len)
PRINTMSG(inp, len);
syslog(LOG_ERR, "CHAP authentication failed");
auth_withpeer_fail(cstate->unit, CHAP);
auth_withpeer_fail(cstate->unit, PPP_CHAP);
}
@ -622,7 +619,7 @@ ChapSendChallenge(cstate)
outlen = CHAP_HEADERLEN + sizeof (u_char) + chal_len + name_len;
outp = outpacket_buf;
MAKEHEADER(outp, CHAP); /* paste in a CHAP header */
MAKEHEADER(outp, PPP_CHAP); /* paste in a CHAP header */
PUTCHAR(CHAP_CHALLENGE, outp);
PUTCHAR(cstate->chal_id, outp);
@ -634,7 +631,7 @@ ChapSendChallenge(cstate)
BCOPY(cstate->chal_name, outp, name_len); /* append hostname */
output(cstate->unit, outpacket_buf, outlen + DLLHEADERLEN);
output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN);
CHAPDEBUG((LOG_INFO, "ChapSendChallenge: Sent id %d.", cstate->chal_id));
@ -664,13 +661,13 @@ ChapSendStatus(cstate, code)
outlen = CHAP_HEADERLEN + msglen;
outp = outpacket_buf;
MAKEHEADER(outp, CHAP); /* paste in a header */
MAKEHEADER(outp, PPP_CHAP); /* paste in a header */
PUTCHAR(code, outp);
PUTCHAR(cstate->chal_id, outp);
PUTSHORT(outlen, outp);
BCOPY(msg, outp, msglen);
output(cstate->unit, outpacket_buf, outlen + DLLHEADERLEN);
output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN);
CHAPDEBUG((LOG_INFO, "ChapSendStatus: Sent code %d, id %d.", code,
cstate->chal_id));
@ -722,7 +719,7 @@ ChapSendResponse(cstate)
outlen = CHAP_HEADERLEN + sizeof (u_char) + md_len + name_len;
outp = outpacket_buf;
MAKEHEADER(outp, CHAP);
MAKEHEADER(outp, PPP_CHAP);
PUTCHAR(CHAP_RESPONSE, outp); /* we are a response */
PUTCHAR(cstate->resp_id, outp); /* copy id from challenge packet */
@ -735,7 +732,7 @@ ChapSendResponse(cstate)
BCOPY(cstate->resp_name, outp, name_len); /* append our name */
/* send the packet */
output(cstate->unit, outpacket_buf, outlen + DLLHEADERLEN);
output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN);
cstate->clientstate = CHAPCS_RESPONSE;
TIMEOUT(ChapResponseTimeout, (caddr_t) cstate, cstate->timeouttime);
@ -753,7 +750,7 @@ int
ChapPrintPkt(p, plen, printer, arg)
u_char *p;
int plen;
void (*printer) __ARGS((void *, char *, ...));
void (*printer) __P((void *, char *, ...));
void *arg;
{
int code, id, len;
@ -806,18 +803,3 @@ ChapPrintPkt(p, plen, printer, arg)
return len + CHAP_HEADERLEN;
}
#ifdef NO_DRAND48
double drand48()
{
return (double)random() / (double)0x7fffffffL; /* 2**31-1 */
}
void srand48(seedval)
long seedval;
{
srand((int)seedval);
}
#endif

View File

@ -15,7 +15,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* $Id: chap.h,v 1.2 1994/04/11 07:13:44 paulus Exp $
* $Id: chap.h,v 1.3 1994/09/21 06:47:37 paulus Exp $
*/
#ifndef __CHAP_INCLUDE__
@ -98,15 +98,15 @@ typedef struct chap_state {
extern chap_state chap[];
void ChapInit __ARGS((int));
void ChapAuthWithPeer __ARGS((int, char *, int));
void ChapAuthPeer __ARGS((int, char *, int));
void ChapLowerUp __ARGS((int));
void ChapLowerDown __ARGS((int));
void ChapInput __ARGS((int, u_char *, int));
void ChapProtocolReject __ARGS((int));
int ChapPrintPkt __ARGS((u_char *, int,
void (*) __ARGS((void *, char *, ...)), void *));
void ChapInit __P((int));
void ChapAuthWithPeer __P((int, char *, int));
void ChapAuthPeer __P((int, char *, int));
void ChapLowerUp __P((int));
void ChapLowerDown __P((int));
void ChapInput __P((int, u_char *, int));
void ChapProtocolReject __P((int));
int ChapPrintPkt __P((u_char *, int,
void (*) __P((void *, char *, ...)), void *));
#define __CHAP_INCLUDE__
#endif /* __CHAP_INCLUDE__ */

View File

@ -18,7 +18,7 @@
*/
#ifndef lint
static char rcsid[] = "$Id: fsm.c,v 1.3 1994/05/24 11:21:10 paulus Exp $";
static char rcsid[] = "$Id: fsm.c,v 1.8 1994/11/10 01:52:05 paulus Exp $";
#endif
/*
@ -28,27 +28,27 @@ static char rcsid[] = "$Id: fsm.c,v 1.3 1994/05/24 11:21:10 paulus Exp $";
*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <syslog.h>
#include "ppp.h"
#include "pppd.h"
#include "fsm.h"
extern char *proto_name();
static void fsm_timeout __ARGS((caddr_t));
static void fsm_rconfreq __ARGS((fsm *, int, u_char *, int));
static void fsm_rconfack __ARGS((fsm *, int, u_char *, int));
static void fsm_rconfnakrej __ARGS((fsm *, int, int, u_char *, int));
static void fsm_rtermreq __ARGS((fsm *, int));
static void fsm_rtermack __ARGS((fsm *));
static void fsm_rcoderej __ARGS((fsm *, u_char *, int));
static void fsm_sconfreq __ARGS((fsm *, int));
static void fsm_timeout __P((caddr_t));
static void fsm_rconfreq __P((fsm *, int, u_char *, int));
static void fsm_rconfack __P((fsm *, int, u_char *, int));
static void fsm_rconfnakrej __P((fsm *, int, int, u_char *, int));
static void fsm_rtermreq __P((fsm *, int));
static void fsm_rtermack __P((fsm *));
static void fsm_rcoderej __P((fsm *, u_char *, int));
static void fsm_sconfreq __P((fsm *, int));
#define PROTO_NAME(f) ((f)->callbacks->proto_name)
int peer_mru[NPPP];
int peer_mru[NUM_PPP];
/*
@ -446,15 +446,16 @@ fsm_rconfack(f, id, inp, len)
FSMDEBUG((LOG_INFO, "fsm_rconfack(%s): Rcvd id %d.",
PROTO_NAME(f), id));
if (id != f->reqid) /* Expected id? */
return; /* Nope, toss... */
if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len): (len == 0)) ){
if (id != f->reqid || f->seen_ack) /* Expected id? */
return; /* Nope, toss... */
if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len):
(len == 0)) ){
/* Ack is bad - ignore it */
FSMDEBUG((LOG_INFO, "%s: received bad Ack (length %d)",
PROTO_NAME(f), len));
return;
}
f->reqid = -1;
f->seen_ack = 1;
switch (f->state) {
case CLOSED:
@ -468,7 +469,8 @@ fsm_rconfack(f, id, inp, len)
break;
case ACKRCVD:
/* Huh? an extra Ack? oh well... */
/* Huh? an extra valid Ack? oh well... */
UNTIMEOUT(fsm_timeout, (caddr_t) f); /* Cancel timeout */
fsm_sconfreq(f, 0);
f->state = REQSENT;
break;
@ -507,16 +509,16 @@ fsm_rconfnakrej(f, code, id, inp, len)
FSMDEBUG((LOG_INFO, "fsm_rconfnakrej(%s): Rcvd id %d.",
PROTO_NAME(f), id));
if (id != f->reqid) /* Expected id? */
return; /* Nope, toss... */
if (id != f->reqid || f->seen_ack) /* Expected id? */
return; /* Nope, toss... */
proc = (code == CONFNAK)? f->callbacks->nakci: f->callbacks->rejci;
if( !proc || !proc(f, inp, len) ){
if (!proc || !proc(f, inp, len)) {
/* Nak/reject is bad - ignore it */
FSMDEBUG((LOG_INFO, "%s: received bad %s (length %d)",
PROTO_NAME(f), (code==CONFNAK? "Nak": "reject"), len));
return;
}
f->reqid = -1;
f->seen_ack = 1;
switch (f->state) {
case CLOSED:
@ -533,6 +535,7 @@ fsm_rconfnakrej(f, code, id, inp, len)
case ACKRCVD:
/* Got a Nak/reject when we had already had an Ack?? oh well... */
UNTIMEOUT(fsm_timeout, (caddr_t) f); /* Cancel timeout */
fsm_sconfreq(f, 0);
f->state = REQSENT;
break;
@ -590,11 +593,13 @@ fsm_rtermack(f)
switch (f->state) {
case CLOSING:
UNTIMEOUT(fsm_timeout, (caddr_t) f);
f->state = CLOSED;
if( f->callbacks->finished )
(*f->callbacks->finished)(f);
break;
case STOPPING:
UNTIMEOUT(fsm_timeout, (caddr_t) f);
f->state = STOPPED;
if( f->callbacks->finished )
(*f->callbacks->finished)(f);
@ -715,10 +720,12 @@ fsm_sconfreq(f, retransmit)
f->reqid = ++f->id;
}
f->seen_ack = 0;
/*
* Make up the request packet
*/
outp = outpacket_buf + DLLHEADERLEN + HEADERLEN;
outp = outpacket_buf + PPP_HDRLEN + HEADERLEN;
if( f->callbacks->cilen && f->callbacks->addci ){
cilen = (*f->callbacks->cilen)(f);
if( cilen > peer_mru[f->unit] - HEADERLEN )
@ -759,14 +766,14 @@ fsm_sdata(f, code, id, data, datalen)
outp = outpacket_buf;
if (datalen > peer_mru[f->unit] - HEADERLEN)
datalen = peer_mru[f->unit] - HEADERLEN;
if (datalen && data != outp + DLLHEADERLEN + HEADERLEN)
BCOPY(data, outp + DLLHEADERLEN + HEADERLEN, datalen);
if (datalen && data != outp + PPP_HDRLEN + HEADERLEN)
BCOPY(data, outp + PPP_HDRLEN + HEADERLEN, datalen);
outlen = datalen + HEADERLEN;
MAKEHEADER(outp, f->protocol);
PUTCHAR(code, outp);
PUTCHAR(id, outp);
PUTSHORT(outlen, outp);
output(f->unit, outpacket_buf, outlen + DLLHEADERLEN);
output(f->unit, outpacket_buf, outlen + PPP_HDRLEN);
FSMDEBUG((LOG_INFO, "fsm_sdata(%s): Sent code %d, id %d.",
PROTO_NAME(f), code, id));

View File

@ -16,7 +16,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* $Id: fsm.h,v 1.2 1994/04/11 07:18:35 paulus Exp $
* $Id: fsm.h,v 1.5 1995/05/19 03:17:35 paulus Exp $
*/
/*
@ -66,6 +66,7 @@ typedef struct fsm {
int flags; /* Contains option bits */
u_char id; /* Current id */
u_char reqid; /* Current request id */
u_char seen_ack; /* Have received valid Ack/Nak/Rej to Req */
int timeouttime; /* Timeout time in milliseconds */
int maxconfreqtransmits; /* Maximum Configure-Request transmissions */
int retransmits; /* Number of retransmissions left */
@ -105,20 +106,20 @@ typedef struct fsm {
#define DEFTIMEOUT 3 /* Timeout time in seconds */
#define DEFMAXTERMREQS 2 /* Maximum Terminate-Request transmissions */
#define DEFMAXCONFREQS 10 /* Maximum Configure-Request transmissions */
#define DEFMAXNAKLOOPS 10 /* Maximum number of nak loops */
#define DEFMAXNAKLOOPS 5 /* Maximum number of nak loops */
/*
* Prototypes
*/
void fsm_init __ARGS((fsm *));
void fsm_lowerup __ARGS((fsm *));
void fsm_lowerdown __ARGS((fsm *));
void fsm_open __ARGS((fsm *));
void fsm_close __ARGS((fsm *));
void fsm_input __ARGS((fsm *, u_char *, int));
void fsm_protreject __ARGS((fsm *));
void fsm_sdata __ARGS((fsm *, int, int, u_char *, int));
void fsm_init __P((fsm *));
void fsm_lowerup __P((fsm *));
void fsm_lowerdown __P((fsm *));
void fsm_open __P((fsm *));
void fsm_close __P((fsm *));
void fsm_input __P((fsm *, u_char *, int));
void fsm_protreject __P((fsm *));
void fsm_sdata __P((fsm *, int, int, u_char *, int));
/*

View File

@ -18,7 +18,7 @@
*/
#ifndef lint
static char rcsid[] = "$Id: ipcp.c,v 1.8 1994/05/26 06:37:34 paulus Exp $";
static char rcsid[] = "$Id: ipcp.c,v 1.20 1995/08/10 06:51:04 paulus Exp $";
#endif
/*
@ -30,41 +30,37 @@ static char rcsid[] = "$Id: ipcp.c,v 1.8 1994/05/26 06:37:34 paulus Exp $";
#include <syslog.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "pppd.h"
#include "ppp.h"
#include "fsm.h"
#include "ipcp.h"
#include "pathnames.h"
/* global vars */
ipcp_options ipcp_wantoptions[NPPP]; /* Options that we want to request */
ipcp_options ipcp_gotoptions[NPPP]; /* Options that peer ack'd */
ipcp_options ipcp_allowoptions[NPPP]; /* Options we allow peer to request */
ipcp_options ipcp_hisoptions[NPPP]; /* Options that we ack'd */
extern char ifname[];
extern char devname[];
extern int baud_rate;
ipcp_options ipcp_wantoptions[NUM_PPP]; /* Options that we want to request */
ipcp_options ipcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */
ipcp_options ipcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
ipcp_options ipcp_hisoptions[NUM_PPP]; /* Options that we ack'd */
/* local vars */
static int cis_received[NPPP]; /* # Conf-Reqs received */
static int cis_received[NUM_PPP]; /* # Conf-Reqs received */
/*
* Callbacks for fsm code. (CI = Configuration Information)
*/
static void ipcp_resetci __ARGS((fsm *)); /* Reset our CI */
static int ipcp_cilen __ARGS((fsm *)); /* Return length of our CI */
static void ipcp_addci __ARGS((fsm *, u_char *, int *)); /* Add our CI */
static int ipcp_ackci __ARGS((fsm *, u_char *, int)); /* Peer ack'd our CI */
static int ipcp_nakci __ARGS((fsm *, u_char *, int)); /* Peer nak'd our CI */
static int ipcp_rejci __ARGS((fsm *, u_char *, int)); /* Peer rej'd our CI */
static int ipcp_reqci __ARGS((fsm *, u_char *, int *, int)); /* Rcv CI */
static void ipcp_up __ARGS((fsm *)); /* We're UP */
static void ipcp_down __ARGS((fsm *)); /* We're DOWN */
static void ipcp_script __ARGS((fsm *, char *)); /* Run an up/down script */
static void ipcp_resetci __P((fsm *)); /* Reset our CI */
static int ipcp_cilen __P((fsm *)); /* Return length of our CI */
static void ipcp_addci __P((fsm *, u_char *, int *)); /* Add our CI */
static int ipcp_ackci __P((fsm *, u_char *, int)); /* Peer ack'd our CI */
static int ipcp_nakci __P((fsm *, u_char *, int)); /* Peer nak'd our CI */
static int ipcp_rejci __P((fsm *, u_char *, int)); /* Peer rej'd our CI */
static int ipcp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv CI */
static void ipcp_up __P((fsm *)); /* We're UP */
static void ipcp_down __P((fsm *)); /* We're DOWN */
static void ipcp_script __P((fsm *, char *)); /* Run an up/down script */
fsm ipcp_fsm[NPPP]; /* IPCP fsm structure */
fsm ipcp_fsm[NUM_PPP]; /* IPCP fsm structure */
static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */
ipcp_resetci, /* Reset our Configuration Information */
@ -103,7 +99,7 @@ static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */
*/
char *
ip_ntoa(ipaddr)
u_long ipaddr;
u_int32_t ipaddr;
{
static char b[64];
@ -130,7 +126,7 @@ ipcp_init(unit)
ipcp_options *ao = &ipcp_allowoptions[unit];
f->unit = unit;
f->protocol = IPCP;
f->protocol = PPP_IPCP;
f->callbacks = &ipcp_callbacks;
fsm_init(&ipcp_fsm[unit]);
@ -296,7 +292,7 @@ ipcp_addci(f, ucp, lenp)
if (neg) { \
int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \
if (len >= addrlen) { \
u_long l; \
u_int32_t l; \
PUTCHAR(opt, ucp); \
PUTCHAR(addrlen, ucp); \
l = ntohl(val1); \
@ -359,7 +355,7 @@ ipcp_ackci(f, p, len)
{
ipcp_options *go = &ipcp_gotoptions[f->unit];
u_short cilen, citype, cishort;
u_long cilong;
u_int32_t cilong;
u_char cimaxslotindex, cicflag;
/*
@ -394,7 +390,7 @@ ipcp_ackci(f, p, len)
#define ACKCIADDR(opt, neg, old, val1, val2) \
if (neg) { \
int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \
u_long l; \
u_int32_t l; \
if ((len -= addrlen) < 0) \
goto bad; \
GETCHAR(citype, p); \
@ -451,7 +447,7 @@ ipcp_nakci(f, p, len)
u_char cimaxslotindex, cicflag;
u_char citype, cilen, *next;
u_short cishort;
u_long ciaddr1, ciaddr2, l;
u_int32_t ciaddr1, ciaddr2, l;
ipcp_options no; /* options we've seen Naks for */
ipcp_options try; /* options to request next time */
@ -498,7 +494,7 @@ ipcp_nakci(f, p, len)
* Accept the peer's idea of {our,his} address, if different
* from our idea, only if the accept_{local,remote} flag is set.
*/
NAKCIADDR(CI_ADDR, neg_addr, go->old_addrs,
NAKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, go->old_addrs,
if (go->accept_local && ciaddr1) { /* Do we know our address? */
try.ouraddr = ciaddr1;
IPCPDEBUG((LOG_INFO, "local IP address %s",
@ -579,16 +575,15 @@ ipcp_nakci(f, p, len)
case CI_ADDR:
if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR)
goto bad;
try.neg_addr = 1;
try.old_addrs = 0;
GETLONG(l, p);
ciaddr1 = htonl(l);
if (ciaddr1 && go->accept_local)
try.ouraddr = ciaddr1;
if (try.ouraddr != 0)
try.neg_addr = 1;
no.neg_addr = 1;
break;
default:
goto bad;
}
p = next;
}
@ -623,7 +618,7 @@ ipcp_rejci(f, p, len)
ipcp_options *go = &ipcp_gotoptions[f->unit];
u_char cimaxslotindex, ciflag, cilen;
u_short cishort;
u_long cilong;
u_int32_t cilong;
ipcp_options try; /* options to request next time */
try = *go;
@ -637,7 +632,7 @@ ipcp_rejci(f, p, len)
len >= (cilen = old? CILEN_ADDRS: CILEN_ADDR) && \
p[1] == cilen && \
p[0] == opt) { \
u_long l; \
u_int32_t l; \
len -= cilen; \
INCPTR(2, p); \
GETLONG(l, p); \
@ -722,7 +717,7 @@ ipcp_reqci(f, inp, len, reject_if_disagree)
u_char *cip, *next; /* Pointer to current and next CIs */
u_short cilen, citype; /* Parsed len, type */
u_short cishort; /* Parsed short value */
u_long tl, ciaddr1, ciaddr2;/* Parsed address values */
u_int32_t tl, ciaddr1, ciaddr2;/* Parsed address values */
int rc = CONFACK; /* Final packet return code */
int orc; /* Individual option return code */
u_char *p; /* Pointer to next char to parse */
@ -778,10 +773,17 @@ ipcp_reqci(f, inp, len, reject_if_disagree)
&& (ciaddr1 == 0 || !wo->accept_remote)) {
orc = CONFNAK;
if (!reject_if_disagree) {
DECPTR(sizeof (long), p);
DECPTR(sizeof(u_int32_t), p);
tl = ntohl(wo->hisaddr);
PUTLONG(tl, p);
}
} else if (ciaddr1 == 0 && wo->hisaddr == 0) {
/*
* If neither we nor he knows his address, reject the option.
*/
orc = CONFREJ;
wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */
break;
}
/*
@ -795,7 +797,7 @@ ipcp_reqci(f, inp, len, reject_if_disagree)
if (ciaddr2 == 0 || !wo->accept_local) {
orc = CONFNAK;
if (!reject_if_disagree) {
DECPTR(sizeof (long), p);
DECPTR(sizeof(u_int32_t), p);
tl = ntohl(wo->ouraddr);
PUTLONG(tl, p);
}
@ -832,10 +834,17 @@ ipcp_reqci(f, inp, len, reject_if_disagree)
&& (ciaddr1 == 0 || !wo->accept_remote)) {
orc = CONFNAK;
if (!reject_if_disagree) {
DECPTR(sizeof (long), p);
DECPTR(sizeof(u_int32_t), p);
tl = ntohl(wo->hisaddr);
PUTLONG(tl, p);
}
} else if (ciaddr1 == 0 && wo->hisaddr == 0) {
/*
* Don't ACK an address of 0.0.0.0 - reject it instead.
*/
orc = CONFREJ;
wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */
break;
}
ho->neg_addr = 1;
@ -878,7 +887,7 @@ ipcp_reqci(f, inp, len, reject_if_disagree)
}
}
ho->maxslotindex = maxslotindex;
ho->cflag = wo->cflag;
ho->cflag = cflag;
} else {
ho->old_vj = 1;
ho->maxslotindex = MAX_STATES - 1;
@ -960,7 +969,7 @@ static void
ipcp_up(f)
fsm *f;
{
u_long mask;
u_int32_t mask;
ipcp_options *ho = &ipcp_hisoptions[f->unit];
ipcp_options *go = &ipcp_gotoptions[f->unit];
@ -1047,7 +1056,7 @@ static void
ipcp_down(f)
fsm *f;
{
u_long ouraddr, hisaddr;
u_int32_t ouraddr, hisaddr;
IPCPDEBUG((LOG_INFO, "ipcp: down"));
@ -1083,11 +1092,12 @@ ipcp_script(f, script)
argv[0] = script;
argv[1] = ifname;
argv[2] = devname;
argv[2] = devnam;
argv[3] = strspeed;
argv[4] = strlocal;
argv[5] = strremote;
argv[6] = NULL;
argv[6] = ipparam;
argv[7] = NULL;
run_program(script, argv, 0);
}
@ -1109,7 +1119,7 @@ ipcp_printpkt(p, plen, printer, arg)
int code, id, len, olen;
u_char *pstart, *optend;
u_short cishort;
u_long cilong;
u_int32_t cilong;
if (plen < HEADERLEN)
return 0;

View File

@ -16,7 +16,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* $Id: ipcp.h,v 1.3 1994/04/18 04:05:15 paulus Exp $
* $Id: ipcp.h,v 1.5 1994/09/21 06:47:37 paulus Exp $
*/
/*
@ -49,7 +49,7 @@ typedef struct ipcp_options {
int accept_remote : 1; /* accept peer's value for hisaddr */
u_short vj_protocol; /* protocol value to use in VJ option */
u_char maxslotindex, cflag; /* values for RFC1332 VJ compression neg. */
u_long ouraddr, hisaddr; /* Addresses in NETWORK BYTE ORDER */
u_int32_t ouraddr, hisaddr; /* Addresses in NETWORK BYTE ORDER */
} ipcp_options;
extern fsm ipcp_fsm[];
@ -58,11 +58,11 @@ extern ipcp_options ipcp_gotoptions[];
extern ipcp_options ipcp_allowoptions[];
extern ipcp_options ipcp_hisoptions[];
void ipcp_init __ARGS((int));
void ipcp_open __ARGS((int));
void ipcp_close __ARGS((int));
void ipcp_lowerup __ARGS((int));
void ipcp_lowerdown __ARGS((int));
void ipcp_input __ARGS((int, u_char *, int));
void ipcp_protrej __ARGS((int));
int ipcp_printpkt __ARGS((u_char *, int, void (*)(), void *));
void ipcp_init __P((int));
void ipcp_open __P((int));
void ipcp_close __P((int));
void ipcp_lowerup __P((int));
void ipcp_lowerdown __P((int));
void ipcp_input __P((int, u_char *, int));
void ipcp_protrej __P((int));
int ipcp_printpkt __P((u_char *, int, void (*)(), void *));

View File

@ -18,7 +18,7 @@
*/
#ifndef lint
static char rcsid[] = "$Id: lcp.c,v 1.8 1994/05/30 02:38:49 paulus Exp $";
static char rcsid[] = "$Id: lcp.c,v 1.21 1995/08/10 06:51:06 paulus Exp $";
#endif
/*
@ -36,7 +36,6 @@ static char rcsid[] = "$Id: lcp.c,v 1.8 1994/05/30 02:38:49 paulus Exp $";
#include <netinet/in.h>
#include "pppd.h"
#include "ppp.h"
#include "fsm.h"
#include "lcp.h"
#include "magic.h"
@ -45,51 +44,56 @@ static char rcsid[] = "$Id: lcp.c,v 1.8 1994/05/30 02:38:49 paulus Exp $";
#include "ipcp.h"
#ifdef _linux_ /* Needs ppp ioctls */
#include <linux/ppp.h>
#include <net/if.h>
#include <linux/if_ppp.h>
#endif
/* global vars */
fsm lcp_fsm[NPPP]; /* LCP fsm structure (global)*/
lcp_options lcp_wantoptions[NPPP]; /* Options that we want to request */
lcp_options lcp_gotoptions[NPPP]; /* Options that peer ack'd */
lcp_options lcp_allowoptions[NPPP]; /* Options we allow peer to request */
lcp_options lcp_hisoptions[NPPP]; /* Options that we ack'd */
u_long xmit_accm[NPPP][8]; /* extended transmit ACCM */
fsm lcp_fsm[NUM_PPP]; /* LCP fsm structure (global)*/
lcp_options lcp_wantoptions[NUM_PPP]; /* Options that we want to request */
lcp_options lcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */
lcp_options lcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
lcp_options lcp_hisoptions[NUM_PPP]; /* Options that we ack'd */
u_int32_t xmit_accm[NUM_PPP][8]; /* extended transmit ACCM */
static u_long lcp_echos_pending = 0; /* Number of outstanding echo msgs */
static u_long lcp_echo_number = 0; /* ID number of next echo frame */
static u_long lcp_echo_timer_running = 0; /* TRUE if a timer is running */
static u_int32_t lcp_echos_pending = 0; /* Number of outstanding echo msgs */
static u_int32_t lcp_echo_number = 0; /* ID number of next echo frame */
static u_int32_t lcp_echo_timer_running = 0; /* TRUE if a timer is running */
u_long lcp_echo_interval = 0;
u_long lcp_echo_fails = 0;
static u_char nak_buffer[PPP_MRU]; /* where we construct a nak packet */
#ifdef _linux_
u_int32_t idle_timer_running = 0;
extern int idle_time_limit;
#endif
/*
* Callbacks for fsm code. (CI = Configuration Information)
*/
static void lcp_resetci __ARGS((fsm *)); /* Reset our CI */
static int lcp_cilen __ARGS((fsm *)); /* Return length of our CI */
static void lcp_addci __ARGS((fsm *, u_char *, int *)); /* Add our CI to pkt */
static int lcp_ackci __ARGS((fsm *, u_char *, int)); /* Peer ack'd our CI */
static int lcp_nakci __ARGS((fsm *, u_char *, int)); /* Peer nak'd our CI */
static int lcp_rejci __ARGS((fsm *, u_char *, int)); /* Peer rej'd our CI */
static int lcp_reqci __ARGS((fsm *, u_char *, int *, int)); /* Rcv peer CI */
static void lcp_up __ARGS((fsm *)); /* We're UP */
static void lcp_down __ARGS((fsm *)); /* We're DOWN */
static void lcp_starting __ARGS((fsm *)); /* We need lower layer up */
static void lcp_finished __ARGS((fsm *)); /* We need lower layer down */
static int lcp_extcode __ARGS((fsm *, int, int, u_char *, int));
static void lcp_rprotrej __ARGS((fsm *, u_char *, int));
static void lcp_resetci __P((fsm *)); /* Reset our CI */
static int lcp_cilen __P((fsm *)); /* Return length of our CI */
static void lcp_addci __P((fsm *, u_char *, int *)); /* Add our CI to pkt */
static int lcp_ackci __P((fsm *, u_char *, int)); /* Peer ack'd our CI */
static int lcp_nakci __P((fsm *, u_char *, int)); /* Peer nak'd our CI */
static int lcp_rejci __P((fsm *, u_char *, int)); /* Peer rej'd our CI */
static int lcp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv peer CI */
static void lcp_up __P((fsm *)); /* We're UP */
static void lcp_down __P((fsm *)); /* We're DOWN */
static void lcp_starting __P((fsm *)); /* We need lower layer up */
static void lcp_finished __P((fsm *)); /* We need lower layer down */
static int lcp_extcode __P((fsm *, int, int, u_char *, int));
static void lcp_rprotrej __P((fsm *, u_char *, int));
/*
* routines to send LCP echos to peer
*/
static void lcp_echo_lowerup __ARGS((int));
static void lcp_echo_lowerdown __ARGS((int));
static void LcpEchoTimeout __ARGS((caddr_t));
static void lcp_received_echo_reply __ARGS((fsm *, int, u_char *, int));
static void LcpSendEchoRequest __ARGS((fsm *));
static void LcpLinkFailure __ARGS((fsm *));
static void lcp_echo_lowerup __P((int));
static void lcp_echo_lowerdown __P((int));
static void LcpEchoTimeout __P((caddr_t));
static void lcp_received_echo_reply __P((fsm *, int, u_char *, int));
static void LcpSendEchoRequest __P((fsm *));
static void LcpLinkFailure __P((fsm *));
static fsm_callbacks lcp_callbacks = { /* LCP callback routines */
lcp_resetci, /* Reset our Configuration Information */
@ -109,7 +113,7 @@ static fsm_callbacks lcp_callbacks = { /* LCP callback routines */
"LCP" /* String name of protocol */
};
int lcp_warnloops = DEFWARNLOOPS; /* Warn about a loopback this often */
int lcp_loopbackfail = DEFLOOPBACKFAIL;
/*
* Length of each type of configuration option (in octets)
@ -136,7 +140,7 @@ lcp_init(unit)
lcp_options *ao = &lcp_allowoptions[unit];
f->unit = unit;
f->protocol = LCP;
f->protocol = PPP_LCP;
f->callbacks = &lcp_callbacks;
fsm_init(f);
@ -216,6 +220,58 @@ lcp_close(unit)
fsm_close(&lcp_fsm[unit]);
}
#ifdef _linux_
static void IdleTimeCheck __P((caddr_t));
/*
* Timer expired for the LCP echo requests from this process.
*/
static void
RestartIdleTimer (f)
fsm *f;
{
u_long delta;
struct ppp_idle ddinfo;
/*
* Read the time since the last packet was received.
*/
if (ioctl (fd, PPPIOCGIDLE, &ddinfo) < 0) {
syslog (LOG_ERR, "ioctl(PPPIOCGIDLE): %m");
die (1);
}
/*
* Compute the time since the last packet was received. If the timer
* has expired then disconnect the line.
*/
delta = idle_time_limit - (u_long) ddinfo.recv_idle;
if (((int) delta <= 0L) && (f->state == OPENED)) {
syslog (LOG_NOTICE, "No IP frames received within idle time limit");
lcp_close(f->unit); /* Reset connection */
phase = PHASE_TERMINATE; /* Mark it down */
} else {
if ((int) delta <= 0L)
delta = (u_long) idle_time_limit;
assert (idle_timer_running==0);
TIMEOUT (IdleTimeCheck, (caddr_t) f, delta);
idle_timer_running = 1;
}
}
/*
* IdleTimeCheck - Timer expired on the IDLE detection for IP frames
*/
static void
IdleTimeCheck (arg)
caddr_t arg;
{
if (idle_timer_running != 0) {
idle_timer_running = 0;
RestartIdleTimer ((fsm *) arg);
}
}
#endif
/*
* lcp_lowerup - The lower layer is up.
@ -226,9 +282,9 @@ lcp_lowerup(unit)
{
sifdown(unit);
ppp_set_xaccm(unit, xmit_accm[unit]);
ppp_send_config(unit, MTU, 0xffffffff, 0, 0);
ppp_recv_config(unit, MTU, 0x00000000, 0, 0);
peer_mru[unit] = MTU;
ppp_send_config(unit, PPP_MRU, 0xffffffff, 0, 0);
ppp_recv_config(unit, PPP_MRU, 0x00000000, 0, 0);
peer_mru[unit] = PPP_MRU;
lcp_allowoptions[unit].asyncmap = xmit_accm[unit][0];
fsm_lowerup(&lcp_fsm[unit]);
@ -255,7 +311,23 @@ lcp_input(unit, p, len)
u_char *p;
int len;
{
fsm_input(&lcp_fsm[unit], p, len);
int oldstate;
fsm *f = &lcp_fsm[unit];
lcp_options *go = &lcp_gotoptions[f->unit];
oldstate = f->state;
fsm_input(f, p, len);
if (oldstate == REQSENT && f->state == ACKSENT) {
/*
* The peer will probably send us an ack soon and then
* immediately start sending packets with the negotiated
* options. So as to be ready when that happens, we set
* our receive side to accept packets as negotiated now.
*/
ppp_recv_config(f->unit, PPP_MRU,
go->neg_asyncmap? go->asyncmap: 0x00000000,
go->neg_pcompression, go->neg_accompression);
}
}
@ -282,8 +354,6 @@ lcp_extcode(f, code, id, inp, len)
LCPDEBUG((LOG_INFO, "lcp: Echo-Request, Rcvd id %d", id));
magp = inp;
PUTLONG(lcp_gotoptions[f->unit].magicnumber, magp);
if (len < CILEN_LONG)
len = CILEN_LONG;
fsm_sdata(f, ECHOREP, id, inp, len);
break;
@ -390,7 +460,7 @@ fsm *f;
lcp_wantoptions[f->unit].magicnumber = magic();
lcp_wantoptions[f->unit].numloops = 0;
lcp_gotoptions[f->unit] = lcp_wantoptions[f->unit];
peer_mru[f->unit] = MTU;
peer_mru[f->unit] = PPP_MRU;
}
@ -463,14 +533,14 @@ lcp_addci(f, ucp, lenp)
if (neg) { \
PUTCHAR(opt, ucp); \
PUTCHAR(CILEN_LQR, ucp); \
PUTSHORT(LQR, ucp); \
PUTSHORT(PPP_LQR, ucp); \
PUTLONG(val, ucp); \
}
ADDCISHORT(CI_MRU, go->neg_mru, go->mru);
ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap, go->asyncmap);
ADDCICHAP(CI_AUTHTYPE, go->neg_chap, CHAP, go->chap_mdtype);
ADDCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, UPAP);
ADDCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype);
ADDCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP);
ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
@ -500,7 +570,7 @@ lcp_ackci(f, p, len)
lcp_options *go = &lcp_gotoptions[f->unit];
u_char cilen, citype, cichar;
u_short cishort;
u_long cilong;
u_int32_t cilong;
/*
* CIs must be in exactly the same order that we sent.
@ -569,7 +639,7 @@ lcp_ackci(f, p, len)
citype != opt) \
goto bad; \
GETSHORT(cishort, p); \
if (cishort != LQR) \
if (cishort != PPP_LQR) \
goto bad; \
GETLONG(cilong, p); \
if (cilong != val) \
@ -578,8 +648,8 @@ lcp_ackci(f, p, len)
ACKCISHORT(CI_MRU, go->neg_mru, go->mru);
ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap, go->asyncmap);
ACKCICHAP(CI_AUTHTYPE, go->neg_chap, CHAP, go->chap_mdtype);
ACKCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, UPAP);
ACKCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype);
ACKCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP);
ACKCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
@ -614,12 +684,13 @@ lcp_nakci(f, p, len)
{
lcp_options *go = &lcp_gotoptions[f->unit];
lcp_options *wo = &lcp_wantoptions[f->unit];
u_char cilen, citype, cichar, *next;
u_char citype, cichar, *next;
u_short cishort;
u_long cilong;
u_int32_t cilong;
lcp_options no; /* options we've seen Naks for */
lcp_options try; /* options to request next time */
int looped_back = 0;
int cilen;
BZERO(&no, sizeof(no));
try = *go;
@ -697,21 +768,67 @@ lcp_nakci(f, p, len)
if (cishort <= wo->mru || cishort < DEFMRU)
try.mru = cishort;
);
/*
* Add any characters they want to our (receive-side) asyncmap.
*/
NAKCILONG(CI_ASYNCMAP, neg_asyncmap,
try.asyncmap = go->asyncmap | cilong;
);
/*
* If they can't cope with our CHAP hash algorithm, we'll have
* to stop asking for CHAP. We haven't got any other algorithm.
* If they've nak'd our authentication-protocol, check whether
* they are proposing a different protocol, or a different
* hash algorithm for CHAP.
*/
NAKCICHAP(CI_AUTHTYPE, neg_chap,
try.neg_chap = 0;
);
if ((go->neg_chap || go->neg_upap)
&& len >= CILEN_SHORT
&& p[0] == CI_AUTHTYPE && p[1] >= CILEN_SHORT) {
cilen = p[1];
INCPTR(2, p);
GETSHORT(cishort, p);
if (cishort == PPP_PAP && cilen == CILEN_SHORT) {
/*
* If they are asking for PAP, then they don't want to do CHAP.
* If we weren't asking for CHAP, then we were asking for PAP,
* in which case this Nak is bad.
*/
if (!go->neg_chap)
goto bad;
go->neg_chap = 0;
} else if (cishort == PPP_CHAP && cilen == CILEN_CHAP) {
GETCHAR(cichar, p);
if (go->neg_chap) {
/*
* We were asking for CHAP/MD5; they must want a different
* algorithm. If they can't do MD5, we'll have to stop
* asking for CHAP.
*/
if (cichar != go->chap_mdtype)
go->neg_chap = 0;
} else {
/*
* Stop asking for PAP if we were asking for it.
*/
go->neg_upap = 0;
}
} else {
/*
* We don't recognize what they're suggesting.
* Stop asking for what we were asking for.
*/
if (go->neg_chap)
go->neg_chap = 0;
else
go->neg_upap = 0;
p += cilen - CILEN_SHORT;
}
}
/*
* Peer shouldn't send Nak for UPAP, protocol compression or
* Peer shouldn't send Nak for protocol compression or
* address/control compression requests; they should send
* a Reject instead. If they send a Nak, treat it as a Reject.
*/
@ -720,23 +837,24 @@ lcp_nakci(f, p, len)
try.neg_upap = 0;
);
}
/*
* If they can't cope with our link quality protocol, we'll have
* to stop asking for LQR. We haven't got any other protocol.
* If they Nak the reporting period, take their value XXX ?
*/
NAKCILQR(CI_QUALITY, neg_lqr,
if (cishort != LQR)
if (cishort != PPP_LQR)
try.neg_lqr = 0;
else
try.lqr_period = cilong;
);
/*
* Check for a looped-back line.
*/
NAKCILONG(CI_MAGICNUMBER, neg_magicnumber,
try.magicnumber = magic();
++try.numloops;
looped_back = 1;
);
@ -760,11 +878,13 @@ lcp_nakci(f, p, len)
* `let me authenticate myself with you' which is a bit pointless.
* For the quality protocol, the Nak means `ask me to send you quality
* reports', but if we didn't ask for them, we don't want them.
* An option we don't recognize represents the peer asking to
* negotiate some option we don't support, so ignore it.
*/
while (len > CILEN_VOID) {
GETCHAR(citype, p);
GETCHAR(cilen, p);
if( (len -= cilen) < 0 )
if ((len -= cilen) < 0)
goto bad;
next = p + cilen - 2;
@ -800,8 +920,6 @@ lcp_nakci(f, p, len)
if (go->neg_lqr || no.neg_lqr || cilen != CILEN_LQR)
goto bad;
break;
default:
goto bad;
}
p = next;
}
@ -814,9 +932,14 @@ lcp_nakci(f, p, len)
* OK, the Nak is good. Now we can update state.
*/
if (f->state != OPENED) {
if (looped_back) {
if (++try.numloops >= lcp_loopbackfail) {
syslog(LOG_NOTICE, "Serial line is looped back.");
lcp_close(f->unit);
}
} else
try.numloops = 0;
*go = try;
if (looped_back && try.numloops % lcp_warnloops == 0)
LCPDEBUG((LOG_INFO, "The line appears to be looped back."));
}
return 1;
@ -845,7 +968,7 @@ lcp_rejci(f, p, len)
lcp_options *go = &lcp_gotoptions[f->unit];
u_char cichar;
u_short cishort;
u_long cilong;
u_int32_t cilong;
u_char *start = p;
int plen = len;
lcp_options try; /* options to request next time */
@ -894,6 +1017,7 @@ lcp_rejci(f, p, len)
if (cishort != val || cichar != digest) \
goto bad; \
try.neg = 0; \
try.neg_upap = 0; \
LCPDEBUG((LOG_INFO,"lcp_rejci rejected chap opt %d", opt)); \
}
#define REJCILONG(opt, neg, val) \
@ -920,7 +1044,7 @@ lcp_rejci(f, p, len)
GETSHORT(cishort, p); \
GETLONG(cilong, p); \
/* Check rejected value. */ \
if (cishort != LQR || cilong != val) \
if (cishort != PPP_LQR || cilong != val) \
goto bad; \
try.neg = 0; \
LCPDEBUG((LOG_INFO,"lcp_rejci rejected LQR opt %d", opt)); \
@ -928,9 +1052,9 @@ lcp_rejci(f, p, len)
REJCISHORT(CI_MRU, neg_mru, go->mru);
REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap);
REJCICHAP(CI_AUTHTYPE, neg_chap, CHAP, go->chap_mdtype);
REJCICHAP(CI_AUTHTYPE, neg_chap, PPP_CHAP, go->chap_mdtype);
if (!go->neg_chap) {
REJCISHORT(CI_AUTHTYPE, neg_upap, UPAP);
REJCISHORT(CI_AUTHTYPE, neg_upap, PPP_PAP);
}
REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period);
REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber);
@ -977,11 +1101,12 @@ lcp_reqci(f, inp, lenp, reject_if_disagree)
u_char *cip, *next; /* Pointer to current and next CIs */
u_char cilen, citype, cichar;/* Parsed len, type, char value */
u_short cishort; /* Parsed short value */
u_long cilong; /* Parse long value */
u_int32_t cilong; /* Parse long value */
int rc = CONFACK; /* Final packet return code */
int orc; /* Individual option return code */
u_char *p; /* Pointer to next char to parse */
u_char *ucp = inp; /* Pointer to current output char */
u_char *rejp; /* Pointer to next char in reject frame */
u_char *nakp; /* Pointer to next char in Nak frame */
int l = *lenp; /* Length left */
/*
@ -993,6 +1118,8 @@ lcp_reqci(f, inp, lenp, reject_if_disagree)
* Process all his options.
*/
next = inp;
nakp = nak_buffer;
rejp = inp;
while (l) {
orc = CONFACK; /* Assume success */
cip = p = next; /* Remember begining of CI */
@ -1028,10 +1155,9 @@ lcp_reqci(f, inp, lenp, reject_if_disagree)
*/
if (cishort < MINMRU) {
orc = CONFNAK; /* Nak CI */
if( !reject_if_disagree ){
DECPTR(sizeof (short), p); /* Backup */
PUTSHORT(MINMRU, p); /* Give him a hint */
}
PUTCHAR(CI_MRU, nakp);
PUTCHAR(CILEN_SHORT, nakp);
PUTSHORT(MINMRU, nakp); /* Give him a hint */
break;
}
ho->neg_mru = 1; /* Remember he sent MRU */
@ -1046,7 +1172,7 @@ lcp_reqci(f, inp, lenp, reject_if_disagree)
break;
}
GETLONG(cilong, p);
LCPDEBUG((LOG_INFO, "(%lx)", cilong));
LCPDEBUG((LOG_INFO, "(%x)", (unsigned int) cilong));
/*
* Asyncmap must have set at least the bits
@ -1054,10 +1180,9 @@ lcp_reqci(f, inp, lenp, reject_if_disagree)
*/
if ((ao->asyncmap & ~cilong) != 0) {
orc = CONFNAK;
if( !reject_if_disagree ){
DECPTR(sizeof (long), p);
PUTLONG(ao->asyncmap | cilong, p);
}
PUTCHAR(CI_ASYNCMAP, nakp);
PUTCHAR(CILEN_LONG, nakp);
PUTLONG(ao->asyncmap | cilong, nakp);
break;
}
ho->neg_asyncmap = 1;
@ -1068,6 +1193,9 @@ lcp_reqci(f, inp, lenp, reject_if_disagree)
LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd AUTHTYPE"));
if (cilen < CILEN_SHORT ||
!(ao->neg_upap || ao->neg_chap)) {
/*
* Reject the option if we're not willing to authenticate.
*/
orc = CONFREJ;
break;
}
@ -1085,34 +1213,47 @@ lcp_reqci(f, inp, lenp, reject_if_disagree)
* the ordering of the CIs in the peer's Configure-Request.
*/
if (cishort == UPAP) {
if (!ao->neg_upap || /* we don't want to do PAP */
ho->neg_chap || /* or we've already accepted CHAP */
if (cishort == PPP_PAP) {
if (ho->neg_chap || /* we've already accepted CHAP */
cilen != CILEN_SHORT) {
LCPDEBUG((LOG_WARNING,
"lcp_reqci: rcvd AUTHTYPE PAP, rejecting..."));
orc = CONFREJ;
break;
}
if (!ao->neg_upap) { /* we don't want to do PAP */
orc = CONFNAK; /* NAK it and suggest CHAP */
PUTCHAR(CI_AUTHTYPE, nakp);
PUTCHAR(CILEN_CHAP, nakp);
PUTSHORT(PPP_CHAP, nakp);
PUTCHAR(ao->chap_mdtype, nakp);
break;
}
ho->neg_upap = 1;
break;
}
if (cishort == CHAP) {
if (!ao->neg_chap || /* we don't want to do CHAP */
ho->neg_upap || /* or we've already accepted UPAP */
if (cishort == PPP_CHAP) {
if (ho->neg_upap || /* we've already accepted PAP */
cilen != CILEN_CHAP) {
LCPDEBUG((LOG_INFO,
"lcp_reqci: rcvd AUTHTYPE CHAP, rejecting..."));
orc = CONFREJ;
break;
}
if (!ao->neg_chap) { /* we don't want to do CHAP */
orc = CONFNAK; /* NAK it and suggest PAP */
PUTCHAR(CI_AUTHTYPE, nakp);
PUTCHAR(CILEN_SHORT, nakp);
PUTSHORT(PPP_PAP, nakp);
break;
}
GETCHAR(cichar, p); /* get digest type*/
if (cichar != ao->chap_mdtype) {
orc = CONFNAK;
if( !reject_if_disagree ){
DECPTR(sizeof (u_char), p);
PUTCHAR(ao->chap_mdtype, p);
}
PUTCHAR(CI_AUTHTYPE, nakp);
PUTCHAR(CILEN_CHAP, nakp);
PUTSHORT(PPP_CHAP, nakp);
PUTCHAR(ao->chap_mdtype, nakp);
break;
}
ho->chap_mdtype = cichar; /* save md type */
@ -1122,9 +1263,19 @@ lcp_reqci(f, inp, lenp, reject_if_disagree)
/*
* We don't recognize the protocol they're asking for.
* Reject it.
* Nak it with something we're willing to do.
* (At this point we know ao->neg_upap || ao->neg_chap.)
*/
orc = CONFREJ;
orc = CONFNAK;
PUTCHAR(CI_AUTHTYPE, nakp);
if (ao->neg_chap) {
PUTCHAR(CILEN_CHAP, nakp);
PUTSHORT(PPP_CHAP, nakp);
PUTCHAR(ao->chap_mdtype, nakp);
} else {
PUTCHAR(CILEN_SHORT, nakp);
PUTSHORT(PPP_PAP, nakp);
}
break;
case CI_QUALITY:
@ -1137,16 +1288,20 @@ lcp_reqci(f, inp, lenp, reject_if_disagree)
GETSHORT(cishort, p);
GETLONG(cilong, p);
LCPDEBUG((LOG_INFO, "(%x %lx)", cishort, cilong));
if (cishort != LQR) {
orc = CONFREJ;
break;
}
LCPDEBUG((LOG_INFO, "(%x %x)", cishort, (unsigned int) cilong));
/*
* Check the reporting period.
* Check the protocol and the reporting period.
* XXX When should we Nak this, and what with?
*/
if (cishort != PPP_LQR) {
orc = CONFNAK;
PUTCHAR(CI_QUALITY, nakp);
PUTCHAR(CILEN_LQR, nakp);
PUTSHORT(PPP_LQR, nakp);
PUTLONG(ao->lqr_period, nakp);
break;
}
break;
case CI_MAGICNUMBER:
@ -1157,17 +1312,18 @@ lcp_reqci(f, inp, lenp, reject_if_disagree)
break;
}
GETLONG(cilong, p);
LCPDEBUG((LOG_INFO, "(%lx)", cilong));
LCPDEBUG((LOG_INFO, "(%x)", (unsigned int) cilong));
/*
* He must have a different magic number.
*/
if (go->neg_magicnumber &&
cilong == go->magicnumber) {
orc = CONFNAK;
DECPTR(sizeof (long), p);
cilong = magic(); /* Don't put magic() inside macro! */
PUTLONG(cilong, p);
orc = CONFNAK;
PUTCHAR(CI_MAGICNUMBER, nakp);
PUTCHAR(CILEN_LONG, nakp);
PUTLONG(cilong, nakp);
break;
}
ho->neg_magicnumber = 1;
@ -1209,35 +1365,46 @@ lcp_reqci(f, inp, lenp, reject_if_disagree)
continue; /* Don't send this one */
if (orc == CONFNAK) { /* Nak this CI? */
if (reject_if_disagree) /* Getting fed up with sending NAKs? */
if (reject_if_disagree /* Getting fed up with sending NAKs? */
&& citype != CI_MAGICNUMBER) {
orc = CONFREJ; /* Get tough if so */
else {
} else {
if (rc == CONFREJ) /* Rejecting prior CI? */
continue; /* Don't send this one */
if (rc == CONFACK) { /* Ack'd all prior CIs? */
rc = CONFNAK; /* Not anymore... */
ucp = inp; /* Backup */
}
rc = CONFNAK;
}
}
if (orc == CONFREJ && /* Reject this CI */
rc != CONFREJ) { /* but no prior ones? */
if (orc == CONFREJ) { /* Reject this CI */
rc = CONFREJ;
ucp = inp; /* Backup */
if (cip != rejp) /* Need to move rejected CI? */
BCOPY(cip, rejp, cilen); /* Move it */
INCPTR(cilen, rejp); /* Update output pointer */
}
if (ucp != cip) /* Need to move CI? */
BCOPY(cip, ucp, cilen); /* Move it */
INCPTR(cilen, ucp); /* Update output pointer */
}
/*
* If we wanted to send additional NAKs (for unsent CIs), the
* code would go here. This must be done with care since it might
* require a longer packet than we received. At present there
* are no cases where we want to ask the peer to negotiate an option.
* code would go here. The extra NAKs would go at *nakp.
* At present there are no cases where we want to ask the
* peer to negotiate an option.
*/
*lenp = ucp - inp; /* Compute output length */
switch (rc) {
case CONFACK:
*lenp = next - inp;
break;
case CONFNAK:
/*
* Copy the Nak'd options from the nak_buffer to the caller's buffer.
*/
*lenp = nakp - nak_buffer;
BCOPY(nak_buffer, inp, *lenp);
break;
case CONFREJ:
*lenp = rejp - inp;
break;
}
LCPDEBUG((LOG_INFO, "lcp_reqci: returning CONF%s.", CODENAME(rc)));
return (rc); /* Return final code */
}
@ -1268,7 +1435,7 @@ lcp_up(f)
* set our MRU to the larger of value we wanted and
* the value we got in the negotiation.
*/
ppp_send_config(f->unit, MIN(ao->mru, (ho->neg_mru? ho->mru: MTU)),
ppp_send_config(f->unit, MIN(ao->mru, (ho->neg_mru? ho->mru: PPP_MRU)),
(ho->neg_asyncmap? ho->asyncmap: 0xffffffff),
ho->neg_pcompression, ho->neg_accompression);
/*
@ -1276,7 +1443,7 @@ lcp_up(f)
* set the receive asyncmap to ffffffff, but we set it to 0
* for backwards contemptibility.
*/
ppp_recv_config(f->unit, (go->neg_mru? MAX(wo->mru, go->mru): MTU),
ppp_recv_config(f->unit, (go->neg_mru? MAX(wo->mru, go->mru): PPP_MRU),
(go->neg_asyncmap? go->asyncmap: 0x00000000),
go->neg_pcompression, go->neg_accompression);
@ -1286,6 +1453,7 @@ lcp_up(f)
ChapLowerUp(f->unit); /* Enable CHAP */
upap_lowerup(f->unit); /* Enable UPAP */
ipcp_lowerup(f->unit); /* Enable IPCP */
ccp_lowerup(f->unit); /* Enable CCP */
lcp_echo_lowerup(f->unit); /* Enable echo messages */
link_established(f->unit);
@ -1302,14 +1470,15 @@ lcp_down(f)
fsm *f;
{
lcp_echo_lowerdown(f->unit);
ccp_lowerdown(f->unit);
ipcp_lowerdown(f->unit);
ChapLowerDown(f->unit);
upap_lowerdown(f->unit);
sifdown(f->unit);
ppp_send_config(f->unit, MTU, 0xffffffff, 0, 0);
ppp_recv_config(f->unit, MTU, 0x00000000, 0, 0);
peer_mru[f->unit] = MTU;
ppp_send_config(f->unit, PPP_MRU, 0xffffffff, 0, 0);
ppp_recv_config(f->unit, PPP_MRU, 0x00000000, 0, 0);
peer_mru[f->unit] = PPP_MRU;
link_down(f->unit);
}
@ -1350,13 +1519,13 @@ int
lcp_printpkt(p, plen, printer, arg)
u_char *p;
int plen;
void (*printer) __ARGS((void *, char *, ...));
void (*printer) __P((void *, char *, ...));
void *arg;
{
int code, id, len, olen;
u_char *pstart, *optend;
u_short cishort;
u_long cilong;
u_int32_t cilong;
if (plen < HEADERLEN)
return 0;
@ -1410,10 +1579,10 @@ lcp_printpkt(p, plen, printer, arg)
printer(arg, "auth ");
GETSHORT(cishort, p);
switch (cishort) {
case UPAP:
case PPP_PAP:
printer(arg, "upap");
break;
case CHAP:
case PPP_CHAP:
printer(arg, "chap");
break;
default:
@ -1427,7 +1596,7 @@ lcp_printpkt(p, plen, printer, arg)
printer(arg, "quality ");
GETSHORT(cishort, p);
switch (cishort) {
case LQR:
case PPP_LQR:
printer(arg, "lqr");
break;
default:
@ -1483,7 +1652,7 @@ void LcpLinkFailure (f)
{
if (f->state == OPENED) {
syslog (LOG_NOTICE, "Excessive lack of response to LCP echo frames.");
lcp_lowerdown(f->unit); /* Reset connection */
lcp_close(f->unit); /* Reset connection */
}
}
@ -1495,43 +1664,36 @@ static void
LcpEchoCheck (f)
fsm *f;
{
u_long delta;
long int delta;
#ifdef __linux__
struct ppp_ddinfo ddinfo;
u_long latest;
struct ppp_idle ddinfo;
/*
* Read the time since the last packet was received.
*/
if (ioctl (fd, PPPIOCGTIME, &ddinfo) < 0) {
syslog (LOG_ERR, "ioctl(PPPIOCGTIME): %m");
if (ioctl (fd, PPPIOCGIDLE, &ddinfo) < 0) {
syslog (LOG_ERR, "ioctl(PPPIOCGIDLE): %m");
die (1);
}
/*
* Choose the most recient frame received. It may be an IP or NON-IP frame.
*/
latest = ddinfo.nip_rjiffies < ddinfo.ip_rjiffies ? ddinfo.nip_rjiffies
: ddinfo.ip_rjiffies;
/*
* Compute the time since the last packet was received. If the timer
* has expired then send the echo request and reset the timer to maximum.
*/
delta = (lcp_echo_interval * HZ) - latest;
if (delta < HZ || latest < 0L) {
delta = (long int) lcp_echo_interval - (long int) ddinfo.recv_idle;
if (delta < 0L) {
LcpSendEchoRequest (f);
delta = lcp_echo_interval * HZ;
delta = (int) lcp_echo_interval;
}
delta /= HZ;
#else /* Other implementations do not have ability to find delta */
LcpSendEchoRequest (f);
delta = lcp_echo_interval;
delta = (int) lcp_echo_interval;
#endif
/*
* Start the timer for the next interval.
*/
assert (lcp_echo_timer_running==0);
TIMEOUT (LcpEchoTimeout, (caddr_t) f, delta);
TIMEOUT (LcpEchoTimeout, (caddr_t) f, (u_int32_t) delta);
lcp_echo_timer_running = 1;
}
@ -1558,15 +1720,19 @@ lcp_received_echo_reply (f, id, inp, len)
fsm *f;
int id; u_char *inp; int len;
{
u_long magic;
u_int32_t magic;
/* Check the magic number - don't count replies from ourselves. */
if (len < CILEN_LONG)
if (len < 4) {
syslog(LOG_DEBUG, "lcp: received short Echo-Reply, length %d", len);
return;
}
GETLONG(magic, inp);
if (lcp_gotoptions[f->unit].neg_magicnumber
&& magic == lcp_gotoptions[f->unit].magicnumber)
&& magic == lcp_gotoptions[f->unit].magicnumber) {
syslog(LOG_WARNING, "appear to have received our own echo-reply!");
return;
}
/* Reset the number of outstanding echo frames */
lcp_echos_pending = 0;
@ -1580,7 +1746,7 @@ static void
LcpSendEchoRequest (f)
fsm *f;
{
u_long lcp_magic;
u_int32_t lcp_magic;
u_char pkt[4], *pktp;
/*
@ -1625,6 +1791,11 @@ lcp_echo_lowerup (unit)
/* If a timeout interval is specified then start the timer */
if (lcp_echo_interval != 0)
LcpEchoCheck (f);
#ifdef _linux_
/* If a idle time limit is given then start it */
if (idle_time_limit != 0)
RestartIdleTimer (f);
#endif
}
/*
@ -1641,4 +1812,11 @@ lcp_echo_lowerdown (unit)
UNTIMEOUT (LcpEchoTimeout, (caddr_t) f);
lcp_echo_timer_running = 0;
}
#ifdef _linux_
/* If a idle time limit is running then stop it */
if (idle_timer_running != 0) {
UNTIMEOUT (IdleTimeCheck, (caddr_t) f);
idle_timer_running = 0;
}
#endif
}

View File

@ -16,7 +16,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* $Id: lcp.h,v 1.4 1994/05/24 11:22:28 paulus Exp $
* $Id: lcp.h,v 1.8 1995/06/12 11:22:47 paulus Exp $
*/
/*
@ -55,10 +55,10 @@ typedef struct lcp_options {
int neg_lqr : 1; /* Negotiate use of Link Quality Reports */
u_short mru; /* Value of MRU */
u_char chap_mdtype; /* which MD type (hashing algorithm) */
u_long asyncmap; /* Value of async map */
u_long magicnumber;
u_int32_t asyncmap; /* Value of async map */
u_int32_t magicnumber;
int numloops; /* Number of loops during magic number neg. */
u_long lqr_period; /* Reporting period for link quality */
u_int32_t lqr_period; /* Reporting period for LQR 1/100ths second */
} lcp_options;
extern fsm lcp_fsm[];
@ -66,22 +66,23 @@ extern lcp_options lcp_wantoptions[];
extern lcp_options lcp_gotoptions[];
extern lcp_options lcp_allowoptions[];
extern lcp_options lcp_hisoptions[];
extern u_long xmit_accm[][8];
extern u_int32_t xmit_accm[][8];
#define DEFMRU 1500 /* Try for this */
#define MINMRU 128 /* No MRUs below this */
#define MAXMRU 16384 /* Normally limit MRU to this */
void lcp_init __ARGS((int));
void lcp_open __ARGS((int));
void lcp_close __ARGS((int));
void lcp_lowerup __ARGS((int));
void lcp_lowerdown __ARGS((int));
void lcp_input __ARGS((int, u_char *, int));
void lcp_protrej __ARGS((int));
void lcp_sprotrej __ARGS((int, u_char *, int));
int lcp_printpkt __ARGS((u_char *, int,
void (*) __ARGS((void *, char *, ...)), void *));
void lcp_init __P((int));
void lcp_open __P((int));
void lcp_close __P((int));
void lcp_lowerup __P((int));
void lcp_lowerdown __P((int));
void lcp_input __P((int, u_char *, int));
void lcp_protrej __P((int));
void lcp_sprotrej __P((int, u_char *, int));
int lcp_printpkt __P((u_char *, int,
void (*) __P((void *, char *, ...)), void *));
extern int lcp_warnloops; /* Warn about a loopback this often */
#define DEFWARNLOOPS 10 /* Default value for above */
/* Default number of times we receive our magic number from the peer
before deciding the link is looped-back. */
#define DEFLOOPBACKFAIL 5

View File

@ -1,122 +0,0 @@
/*
* lock.c - lock/unlock the serial device.
*
* This code is derived from chat.c.
*/
static char rcsid[] = "$Id: lock.c,v 1.1 1994/04/18 23:41:52 paulus Exp $";
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <syslog.h>
#ifdef sun
# if defined(SUNOS) && SUNOS >= 41
# ifndef HDB
# define HDB
# endif
# endif
#endif
#ifndef LOCK_DIR
# ifdef __NetBSD__
# define PIDSTRING
# define LOCK_PREFIX "/var/spool/lock/LCK.."
# else
# ifdef HDB
# define PIDSTRING
# define LOCK_PREFIX "/usr/spool/locks/LCK.."
# else /* HDB */
# define LOCK_PREFIX "/usr/spool/uucp/LCK.."
# endif /* HDB */
# endif
#endif /* LOCK_DIR */
static char *lock_file;
/*
* Create a lock file for the named lock device
*/
int
lock(dev)
char *dev;
{
char hdb_lock_buffer[12];
int fd, pid, n;
char *p;
if ((p = strrchr(dev, '/')) != NULL)
dev = p + 1;
lock_file = malloc(strlen(LOCK_PREFIX) + strlen(dev) + 1);
if (lock_file == NULL)
novm("lock file name");
strcat(strcpy(lock_file, LOCK_PREFIX), dev);
while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
if (errno == EEXIST
&& (fd = open(lock_file, O_RDONLY, 0)) >= 0) {
/* Read the lock file to find out who has the device locked */
#ifdef PIDSTRING
n = read(fd, hdb_lock_buffer, 11);
if (n > 0) {
hdb_lock_buffer[n] = 0;
pid = atoi(hdb_lock_buffer);
}
#else
n = read(fd, &pid, sizeof(pid));
#endif
if (n <= 0) {
syslog(LOG_ERR, "Can't read pid from lock file %s", lock_file);
close(fd);
} else {
if (kill(pid, 0) == -1 && errno == ESRCH) {
/* pid no longer exists - remove the lock file */
if (unlink(lock_file) == 0) {
close(fd);
syslog(LOG_NOTICE, "Removed stale lock on %s (pid %d)",
dev, pid);
continue;
} else
syslog(LOG_WARNING, "Couldn't remove stale lock on %s",
dev);
} else
syslog(LOG_NOTICE, "Device %s is locked by pid %d",
dev, pid);
}
close(fd);
} else
syslog(LOG_ERR, "Can't create lock file %s: %m", lock_file);
free(lock_file);
lock_file = NULL;
return -1;
}
# ifdef PIDSTRING
sprintf(hdb_lock_buffer, "%10d\n", getpid());
write(fd, hdb_lock_buffer, 11);
# else
pid = getpid();
write(fd, &pid, sizeof pid);
# endif
close(fd);
return 0;
}
/*
* Remove our lockfile
*/
unlock()
{
if (lock_file) {
unlink(lock_file);
free(lock_file);
lock_file = NULL;
}
}

View File

@ -18,53 +18,73 @@
*/
#ifndef lint
static char rcsid[] = "$Id: magic.c,v 1.1 1993/11/11 03:54:25 paulus Exp $";
static char rcsid[] = "$Id: magic.c,v 1.5 1995/06/06 01:52:25 paulus Exp $";
#endif
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include "pppd.h"
#include "magic.h"
static u_int32_t next; /* Next value to return */
static u_long next; /* Next value to return */
extern u_long gethostid __ARGS((void));
extern long random __ARGS((void));
extern void srandom __ARGS((int));
extern int gethostid __P((void));
extern long mrand48 __P((void));
extern void srand48 __P((long));
/*
* magic_init - Initialize the magic number generator.
*
* Computes first magic number and seed for random number generator.
* Attempts to compute a random number seed which will not repeat.
* The current method uses the current hostid and current time.
* The current method uses the current hostid, current process ID
* and current time, currently.
*/
void magic_init()
void
magic_init()
{
struct timeval tv;
long seed;
struct timeval t;
next = gethostid();
if (gettimeofday(&tv, NULL)) {
perror("gettimeofday");
exit(1);
}
next ^= (u_long) tv.tv_sec ^ (u_long) tv.tv_usec;
srandom((int) next);
gettimeofday(&t, NULL);
seed = gethostid() ^ t.tv_sec ^ t.tv_usec ^ getpid();
srand48(seed);
}
/*
* magic - Returns the next magic number.
*/
u_long magic()
u_int32_t
magic()
{
u_long m;
m = next;
next = (u_long) random();
return (m);
return (u_int32_t) mrand48();
}
#ifdef NO_DRAND48
/*
* Substitute procedures for those systems which don't have
* drand48 et al.
*/
double
drand48()
{
return (double)random() / (double)0x7fffffffL; /* 2**31-1 */
}
long
mrand48()
{
return random();
}
void
srand48(seedval)
long seedval;
{
srandom((int)seedval);
}
#endif

View File

@ -16,9 +16,8 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* $Id: magic.h,v 1.1 1993/11/11 03:54:25 paulus Exp $
* $Id: magic.h,v 1.3 1994/09/21 06:47:37 paulus Exp $
*/
#include "args.h"
void magic_init __ARGS((void)); /* Initialize the magic number generator */
u_long magic __ARGS((void)); /* Returns the next magic number */
void magic_init __P((void)); /* Initialize the magic number generator */
u_int32_t magic __P((void)); /* Returns the next magic number */

File diff suppressed because it is too large Load Diff

View File

@ -40,7 +40,7 @@
#ifndef __MD5_INCLUDE__
/* typedef a 32-bit type */
typedef unsigned long int UINT4;
typedef unsigned int UINT4;
/* Data structure for MD5 (Message-Digest) computation */
typedef struct {

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
/* $Id: patchlevel.h,v 1.10 1994/06/09 01:51:10 paulus Exp $ */
#define PATCHLEVEL 2
/* $Id: patchlevel.h,v 1.16 1995/07/11 06:41:07 paulus Exp $ */
#define PATCHLEVEL 0
#define VERSION "2.1"
#define DATE "9 June 94"
#define VERSION "2.2"
#define IMPLEMENTATION "beta3"
#define DATE "11 July 95"

View File

@ -1,13 +1,15 @@
/*
* define path names
*
* $Id: pathnames.h,v 1.4 1994/05/18 06:34:46 paulus Exp $
* $Id: pathnames.h,v 1.6 1995/06/12 11:22:53 paulus Exp $
*/
#if defined(STREAMS) || defined(ultrix)
#define _PATH_PIDFILE "/etc/ppp"
#ifdef HAVE_PATHS_H
#include <paths.h>
#else
#define _PATH_PIDFILE "/var/run"
#define _PATH_VARRUN "/etc/ppp/"
#define _PATH_DEVNULL "/dev/null"
#endif
#define _PATH_UPAPFILE "/etc/ppp/pap-secrets"
@ -16,4 +18,5 @@
#define _PATH_IPUP "/etc/ppp/ip-up"
#define _PATH_IPDOWN "/etc/ppp/ip-down"
#define _PATH_TTYOPT "/etc/ppp/options."
#define _PATH_CONNERRS "/etc/ppp/connect-errors"
#define _PATH_USEROPT ".ppprc"

View File

@ -1,5 +1,5 @@
.\" manual page [] for pppd 2.0
.\" $Id: pppd.8,v 1.7 1994/06/09 01:50:48 paulus Exp $
.\" $Id: pppd.8,v 1.14 1995/08/16 01:39:53 paulus Exp $
.\" SH section heading
.\" SS subsection heading
.\" LP paragraph
@ -36,6 +36,7 @@ NCP for establishing and configuring the Internet Protocol (IP)
.I <tty_name>
Communicate over the named device. The string "/dev/"
is prepended if necessary. If no device name is given,
or if the name of the controlling terminal is given,
.I pppd
will use the controlling terminal, and will not fork to put itself in
the background.
@ -58,7 +59,7 @@ bit 31 (80000000) represents the character 0x1f or ^_.
If multiple \fBasyncmap\fR options are
given, the values are ORed together.
If no \fBasyncmap\fR option is given, no async character map will be
negotiated for the receive direction; the peer will then escape
negotiated for the receive direction; the peer should then escape
\fIall\fR control characters.
.TP
.B auth
@ -74,14 +75,17 @@ dial the modem and start the remote ppp session.
Use hardware flow control (i.e. RTS/CTS) to control the flow of data on
the serial port.
.TP
.B -crtscts
Disable hardware flow control (i.e. RTS/CTS) on the serial port. If
neither the \fBcrtscts\fR nor the \fB\-crtscts\fR option is given,
the hardware flow control setting for the serial port is left
unchanged.
.TP
.B xonxoff
Use software flow control (i.e. XON/XOFF) to control the flow of data on
the serial port. This option is not implemented on BSD or Ultrix systems
the serial port. This option is only implemented on Linux systems
at present.
.TP
.B -crtscts
A synonym for \fBxonxoff\fR.
.TP
.B defaultroute
Add a default route to the system routing tables, using the peer as
the gateway, when IPCP negotiation is successfully completed.
@ -135,7 +139,7 @@ will then just wait passively for a valid LCP packet from the peer
With this option,
.I pppd
will not transmit LCP packets to initiate a connection until a valid
LCP packet is received from the peer (as for the "passive" option with
LCP packet is received from the peer (as for the `passive' option with
old versions of \fIpppd\fR).
.SH OPTIONS
.TP
@ -228,6 +232,21 @@ Don't agree to authenticate using CHAP.
Disable negotiation of Van Jacobson style IP header compression (use
default, i.e. no compression).
.TP
.B bsdcomp \fInr,nt
Request that the peer compress packets that it sends, using the
BSD-Compress scheme, with a maximum code size of \fInr\fR bits, and
agree to compress packets sent to the peer with a maximum code size of
\fInt\fR bits. If \fInt\fR is not specified, it defaults to the value
given for \fInr\fR. Values in the range 9 to 15 may be used for
\fInr\fR and \fInt\fR; larger values give better compression but
consume more kernel memory for compression dictionaries.
Alternatively, a value of 0 for \fInr\fR or \fInt\fR disables
compression in the corresponding direction.
.TP
.B \-bsdcomp
Disables compression; \fBpppd\fR will not request or agree to compress
packets using the BSD-Compress scheme.
.TP
.B debug
Increase debugging level (same as \fB\-d\fR).
If this
@ -235,9 +254,12 @@ option is given, \fIpppd\fR will log the contents of all control
packets sent or received in a readable form. The packets are logged
through syslog with facility \fIdaemon\fR and level \fIdebug\fR. This
information can be directed to a file by setting up /etc/syslog.conf
appropriately (see syslog.conf(5)). (If \fIpppd\fR is compiled with
extra debugging enabled, it will log messages using facility
\fIlocal2\fR instead of \fIdaemon\fR).
appropriately (see syslog.conf(5)).
.TP
.B \-defaultroute
Disable the \fBdefaultroute\fR option. The system administrator who
wishes to prevent users from creating default routes with \fIpppd\fR
can do so by placing this option in the /etc/ppp/options file.
.TP
.B domain \fI<d>
Append the domain name <d> to the local host name for authentication
@ -245,10 +267,22 @@ purposes. For example, if gethostname() returns the name porsche, but the
fully qualified domain name is porsche.Quotron.COM, you would use the
domain option to set the domain name to Quotron.COM.
.TP
.B ipparam \fIstring
Provides an extra parameter to the ip-up and ip-down scripts. If this
option is given, the \fIstring\fR supplied is given as the 6th
parameter to those scripts.
.TP
.B modem
Use the modem control lines. On Ultrix, this option implies hardware
flow control, as for the \fBcrtscts\fR option. (This option is not fully
implemented.)
Use the modem control lines. This option is the default. With this
option,
.B pppd
will wait for the CD (Carrier Detect) signal from the modem to be asserted
when opening the serial device
(unless a connect script is specified), and it will drop the DTR (Data
Terminal Ready) signal briefly when the connection is terminated and before
executing the connect script.
On Ultrix, this option implies hardware
flow control, as for the \fBcrtscts\fR option.
.TP
.B kdebug \fIn
Enable debugging code in the kernel-level PPP driver. The argument
@ -258,7 +292,10 @@ received packets be printed, and 4 to request that the contents of
transmitted packets be printed.
.TP
.B local
Don't use the modem control lines.
Don't use the modem control lines. With this option,
.B pppd
will ignore the state of the CD (Carrier Detect) signal from the modem and
will not change the state of the DTR (Data Terminal Ready) signal.
.TP
.B mtu \fI<n>
Set the MTU [Maximum Transmit Unit] value to \fI<n>\fR. Unless the
@ -283,11 +320,27 @@ option).
Set the assumed name of the remote system for authentication purposes
to <n>.
.TP
.B papcrypt
Indicates that all secrets in the /etc/ppp/pap-secrets file which
are used for checking the identity of the peer are encrypted, and thus
pppd should not accept a password which (before encryption) is
identical to the secret from the /etc/ppp/pap-secrets file.
.TP
.B proxyarp
Add an entry to this system's ARP [Address Resolution Protocol] table
with the IP address of the peer and the Ethernet address of this
system.
.TP
.B \-proxyarp
Disable the \fBproxyarp\fR option. The system administrator who
wishes to prevent users from creating proxy ARP entries with
\fIpppd\fR can do so by placing this option in the /etc/ppp/options
file.
.TP
.B persist
Do not exit after a connection is terminated; instead try to reopen
the connection.
.TP
.B login
Use the system password database for authenticating the peer using
PAP.
@ -358,6 +411,12 @@ Set the PAP restart interval (retransmission timeout) to <n> seconds
Set the maximum number of PAP authenticate-request transmissions to
<n> (default 10).
.TP
.B pap-timeout \fI<n>
Set the maximum time that
.I pppd
will wait for the peer to authenticate itself with PAP to
<n> seconds (0 means no limit).
.TP
.B chap-restart \fI<n>
Set the CHAP restart interval (retransmission timeout for challenges)
to <n> seconds (default 3).
@ -424,7 +483,7 @@ directions if desired.
.LP
A secrets file is parsed into words as for a options file. A secret
is specified by a line containing at least 3 words, in the order
client, server, secret. Any following words on the same line are
client name, server name, secret. Any following words on the same line are
taken to be a list of acceptable IP addresses for that client. If
there are only 3 words on the line, it is assumed that any IP address
is OK; to disallow all IP addresses, use "-". If the secret starts
@ -480,11 +539,16 @@ When authenticating the peer with PAP, a secret of "" matches any
password supplied by the peer. If the password doesn't match the
secret, the password is encrypted using crypt() and checked against
the secret again; thus secrets for authenticating the peer can be
stored in encrypted form. If the \fBlogin\fR option was specified, the
stored in encrypted form. If the \fBpapcrypt\fR option is given, the
first (unencrypted) comparison is omitted, for better security.
.LP
If the \fBlogin\fR option was specified, the
username and password are also checked against the system password
database. Thus, the system administrator can set up the pap-secrets
file to allow PPP access only to certain users, and to restrict the
set of IP addresses that each user can use.
set of IP addresses that each user can use. Typically, when using the
\fBlogin\fR option, the secret in /etc/ppp/pap-secrets would be "", to
avoid the need to have the same secret in two places.
.LP
Secrets are selected from the CHAP secrets file as follows:
.TP 2
@ -590,27 +654,28 @@ to direct the messages to the desired output device or file.
The \fBdebug\fR option causes the contents of all control packets sent
or received to be logged, that is, all LCP, PAP, CHAP or IPCP packets.
This can be useful if the PPP negotiation does not succeed.
If debugging is enabled at compile time, \fIpppd\fR uses facility
LOG_LOCAL2 instead of LOG_DAEMON, and the \fBdebug\fR option
causes additional debugging messages to be logged.
If debugging is enabled at compile time, the \fBdebug\fR option also
causes other debugging messages to be logged.
.LP
Debugging can also be enabled by sending a
Debugging can also be enabled or disabled by sending a
SIGUSR1 to the
.I pppd
process.
Debugging may be disabled by sending a SIGUSR2 to the
.I pppd
process.
process. This signal acts as a toggle.
.SH FILES
.TP
.B /var/run/ppp\fIn\fB.pid \fR(BSD), \fB/etc/ppp/ppp\fIn\fB.pid \fR(SunOS)
.B /var/run/ppp\fIn\fB.pid \fR(BSD or Linux), \fB/etc/ppp/ppp\fIn\fB.pid \fR(others)
Process-ID for \fIpppd\fR process on ppp interface unit \fIn\fR.
.TP
.B /etc/ppp/ip-up
A program or script which is executed when the link is available for
sending and receiving IP packets (that is, IPCP has come up). It is
executed with the parameters \fIinterface-name tty-device speed
local-IP-address remote-IP-address\fR.
executed with the parameters
.IP
\fIinterface-name tty-device speed local-IP-address
remote-IP-address\fR
.IP
and with its standard input,
output and error streams redirected to \fB/dev/null\fR.
.IP
This program or script is executed with the same real and effective
user-ID as \fIpppd\fR, that is, at least the effective user-ID and
@ -682,20 +747,29 @@ The following signals have the specified effect when sent to the
process.
.TP
.B SIGINT, SIGTERM
These signals cause \fIpppd\fR to terminate the link (by closing LCP),
These signals cause \fBpppd\fR to terminate the link (by closing LCP),
restore the serial device settings, and exit.
.TP
.B SIGHUP
Indicates that the physical layer has been disconnected. \fIpppd\fR
will attempt to restore the serial device settings (this may produce
error messages on Suns), and then exit.
.SH BUGS
The use of the modem control lines and the effects of the \fBmodem\fR
and \fBlocal\fR options are not well defined.
This signal causes \fBpppd\fR to terminate the link, restore the
serial device settings, and close the serial device. If the
\fBpersist\fR option has been specified, \fBpppd\fR will try to reopen
the serial device and start another connection. Otherwise \fBpppd\fR
will exit.
.TP
.B SIGUSR2
This signal causes
.B pppd
to renegotiate compression. This can be useful to re-enable
compression after it has been disabled as a result of a fatal
decompression error. With the BSD Compress scheme, fatal
decompression errors generally indicate a bug in one or other
implementation.
.SH AUTHORS
Drew Perkins,
Brad Clements,
Karl Fox,
Greg Christy,
Brad Parker (brad@fcr.com),
Paul Mackerras (paulus@cs.anu.edu.au)
Brad Parker,
Paul Mackerras (paulus@cs.anu.edu.au).

View File

@ -16,7 +16,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* $Id: pppd.h,v 1.3 1994/05/26 06:43:42 paulus Exp $
* $Id: pppd.h,v 1.8 1995/04/26 06:46:31 paulus Exp $
*/
/*
@ -25,15 +25,17 @@
#ifndef __PPPD_H__
#define __PPPD_H__
#include "args.h"
#include <sys/param.h> /* for MAXPATHLEN and BSD4_4, if defined */
#include <sys/types.h> /* for u_int32_t, if defined */
#include <net/ppp_defs.h>
#define NPPP 1 /* One PPP interface supported (per process) */
#define NUM_PPP 1 /* One PPP interface supported (per process) */
/*
* Limits.
*/
#define MAXWORDLEN 1024 /* max length of word in file (incl null) */
#define MAXARGS 1 /* max # args to a command */
#define MAXNAMELEN 256 /* max length of hostname or name for auth */
@ -42,14 +44,47 @@
/*
* Global variables.
*/
extern int debug; /* Debug flag */
extern int ifunit; /* Interface unit number */
extern char ifname[]; /* Interface name */
extern int fd; /* Device file descriptor */
extern int s; /* socket descriptor */
extern char hostname[]; /* hostname */
extern u_char outpacket_buf[]; /* buffer for outgoing packets */
extern int phase; /* See values below */
extern int hungup; /* Physical layer has disconnected */
extern int ifunit; /* Interface unit number */
extern char ifname[]; /* Interface name */
extern int fd; /* Serial device file descriptor */
extern char hostname[]; /* Our hostname */
extern u_char outpacket_buf[]; /* Buffer for outgoing packets */
extern int phase; /* Current state of link - see values below */
extern int baud_rate; /* Current link speed in bits/sec */
extern char *progname; /* Name of this program */
/*
* Variables set by command-line options.
*/
extern int debug; /* Debug flag */
extern int kdebugflag; /* Tell kernel to print debug messages */
extern int default_device; /* Using /dev/tty or equivalent */
extern char devnam[]; /* Device name */
extern int crtscts; /* Use hardware flow control */
extern int modem; /* Use modem control lines */
extern int inspeed; /* Input/Output speed requested */
extern u_int32_t netmask; /* IP netmask to set on interface */
extern int lockflag; /* Create lock file to lock the serial dev */
extern int nodetach; /* Don't detach from controlling tty */
extern char *connector; /* Script to establish physical link */
extern char *disconnector; /* Script to disestablish physical link */
extern char user[]; /* Username for PAP */
extern char passwd[]; /* Password for PAP */
extern int auth_required; /* Peer is required to authenticate */
extern int proxyarp; /* Set up proxy ARP entry for peer */
extern int persist; /* Reopen link after it goes down */
extern int uselogin; /* Use /etc/passwd for checking PAP */
extern int lcp_echo_interval; /* Interval between LCP echo-requests */
extern int lcp_echo_fails; /* Tolerance to unanswered echo-requests */
extern char our_name[]; /* Our name for authentication purposes */
extern char remote_name[]; /* Peer's name for authentication */
extern int usehostname; /* Use hostname for our_name */
extern int disable_defaultip; /* Don't use hostname for default IP adrs */
extern char *ipparam; /* Extra parameter for ip up/down scripts */
extern int cryptpap; /* Others' PAP passwords are encrypted */
/*
* Values for phase.
@ -63,21 +98,21 @@ extern int phase; /* See values below */
/*
* Prototypes.
*/
void quit __ARGS((void)); /* Cleanup and exit */
void timeout __ARGS((void (*)(), caddr_t, int));
void quit __P((void)); /* Cleanup and exit */
void timeout __P((void (*)(), caddr_t, int));
/* Look-alike of kernel's timeout() */
void untimeout __ARGS((void (*)(), caddr_t));
void untimeout __P((void (*)(), caddr_t));
/* Look-alike of kernel's untimeout() */
void output __ARGS((int, u_char *, int));
void output __P((int, u_char *, int));
/* Output a PPP packet */
void demuxprotrej __ARGS((int, int));
void demuxprotrej __P((int, int));
/* Demultiplex a Protocol-Reject */
int check_passwd __ARGS((int, char *, int, char *, int, char **, int *));
int check_passwd __P((int, char *, int, char *, int, char **, int *));
/* Check peer-supplied username/password */
int get_secret __ARGS((int, char *, char *, char *, int *, int));
int get_secret __P((int, char *, char *, char *, int *, int));
/* get "secret" for chap */
u_long GetMask __ARGS((u_long)); /* get netmask for address */
u_int32_t GetMask __P((u_int32_t)); /* get netmask for address */
void die __P((int));
/*
* Inline versions of get/put char/short/long.
@ -118,6 +153,11 @@ u_long GetMask __ARGS((u_long)); /* get netmask for address */
#define INCPTR(n, cp) ((cp) += (n))
#define DECPTR(n, cp) ((cp) -= (n))
#undef FALSE
#define FALSE 0
#undef TRUE
#define TRUE 1
/*
* System dependent definitions for user-level 4.3BSD UNIX implementation.
*/
@ -137,8 +177,8 @@ u_long GetMask __ARGS((u_long)); /* get netmask for address */
* MAKEHEADER - Add Header fields to a packet.
*/
#define MAKEHEADER(p, t) { \
PUTCHAR(ALLSTATIONS, p); \
PUTCHAR(UI, p); \
PUTCHAR(PPP_ALLSTATIONS, p); \
PUTCHAR(PPP_UI, p); \
PUTSHORT(t, p); }

View File

@ -19,21 +19,28 @@
*/
#ifndef lint
static char rcsid[] = "$Id: sys-bsd.c,v 1.7 1994/05/30 06:10:07 paulus Exp $";
static char rcsid[] = "$Id: sys-bsd.c,v 1.21 1995/08/16 01:40:23 paulus Exp $";
#endif
/*
* TODO:
*/
#include <stdio.h>
#include <syslog.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/errno.h>
#include <sys/stat.h>
#include <net/if.h>
#include <net/ppp_defs.h>
#include <net/if_ppp.h>
#include <net/route.h>
#include <net/if_dl.h>
@ -44,12 +51,75 @@ static char rcsid[] = "$Id: sys-bsd.c,v 1.7 1994/05/30 06:10:07 paulus Exp $";
#endif
#include "pppd.h"
#include "ppp.h"
static int initdisc = -1; /* Initial TTY discipline */
extern int kdebugflag;
static int initdisc = -1; /* Initial TTY discipline */
static int rtm_seq;
static int restore_term; /* 1 => we've munged the terminal */
static struct termios inittermios; /* Initial TTY termios */
static struct winsize wsinfo; /* Initial window size info */
static char *lock_file; /* name of lock file created */
int sockfd; /* socket for doing interface ioctls */
/*
* sys_init - System-dependent initialization.
*/
void
sys_init()
{
openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP);
setlogmask(LOG_UPTO(LOG_INFO));
if (debug)
setlogmask(LOG_UPTO(LOG_DEBUG));
/* Get an internet socket for doing socket ioctl's on. */
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
syslog(LOG_ERR, "Couldn't create IP socket: %m");
die(1);
}
}
/*
* note_debug_level - note a change in the debug level.
*/
void
note_debug_level()
{
if (debug) {
syslog(LOG_INFO, "Debug turned ON, Level %d", debug);
setlogmask(LOG_UPTO(LOG_DEBUG));
} else {
setlogmask(LOG_UPTO(LOG_WARNING));
}
}
/*
* ppp_available - check whether the system has any ppp interfaces
* (in fact we check whether we can do an ioctl on ppp0).
*/
int
ppp_available()
{
int s, ok;
struct ifreq ifr;
extern char *no_ppp_msg;
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
return 1; /* can't tell */
strncpy(ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
close(s);
no_ppp_msg = "\
This system lacks kernel support for PPP. To include PPP support\n\
in the kernel, please follow the steps detailed in the README.bsd\n\
file in the ppp-2.2 distribution.\n";
return ok;
}
/*
* establish_ppp - Turn the serial port into a ppp interface.
*/
@ -132,6 +202,111 @@ disestablish_ppp()
}
/*
* set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
* at the requested speed, etc. If `local' is true, set CLOCAL
* regardless of whether the modem option was specified.
*
* For *BSD, we assume that speed_t values numerically equal bits/second.
*/
set_up_tty(fd, local)
int fd, local;
{
struct termios tios;
if (tcgetattr(fd, &tios) < 0) {
syslog(LOG_ERR, "tcgetattr: %m");
die(1);
}
if (!restore_term) {
inittermios = tios;
ioctl(fd, TIOCGWINSZ, &wsinfo);
}
tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
if (crtscts > 0)
tios.c_cflag |= CRTSCTS;
else if (crtscts < 0)
tios.c_cflag &= ~CRTSCTS;
tios.c_cflag |= CS8 | CREAD | HUPCL;
if (local || !modem)
tios.c_cflag |= CLOCAL;
tios.c_iflag = IGNBRK | IGNPAR;
tios.c_oflag = 0;
tios.c_lflag = 0;
tios.c_cc[VMIN] = 1;
tios.c_cc[VTIME] = 0;
if (crtscts == 2) {
tios.c_iflag |= IXOFF;
tios.c_cc[VSTOP] = 0x13; /* DC3 = XOFF = ^S */
tios.c_cc[VSTART] = 0x11; /* DC1 = XON = ^Q */
}
if (inspeed) {
cfsetospeed(&tios, inspeed);
cfsetispeed(&tios, inspeed);
} else {
inspeed = cfgetospeed(&tios);
/*
* We can't proceed if the serial port speed is 0,
* since that implies that the serial port is disabled.
*/
if (inspeed == 0) {
syslog(LOG_ERR, "Baud rate for %s is 0; need explicit baud rate",
devnam);
die(1);
}
}
baud_rate = inspeed;
if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
syslog(LOG_ERR, "tcsetattr: %m");
die(1);
}
restore_term = 1;
}
/*
* restore_tty - restore the terminal to the saved settings.
*/
void
restore_tty()
{
if (restore_term) {
if (!default_device) {
/*
* Turn off echoing, because otherwise we can get into
* a loop with the tty and the modem echoing to each other.
* We presume we are the sole user of this tty device, so
* when we close it, it will revert to its defaults anyway.
*/
inittermios.c_lflag &= ~(ECHO | ECHONL);
}
if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
if (errno != ENXIO)
syslog(LOG_WARNING, "tcsetattr: %m");
ioctl(fd, TIOCSWINSZ, &wsinfo);
restore_term = 0;
}
}
/*
* setdtr - control the DTR line on the serial port.
* This is called from die(), so it shouldn't call die().
*/
setdtr(fd, on)
int fd, on;
{
int modembits = TIOCM_DTR;
ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);
}
/*
* output - Output PPP packet.
*/
@ -153,6 +328,27 @@ output(unit, p, len)
}
/*
* wait_input - wait until there is data available on fd,
* for the length of time specified by *timo (indefinite
* if timo is NULL).
*/
wait_input(timo)
struct timeval *timo;
{
fd_set ready;
int n;
FD_ZERO(&ready);
FD_SET(fd, &ready);
n = select(fd+1, &ready, NULL, &ready, timo);
if (n < 0 && errno != EINTR) {
syslog(LOG_ERR, "select: %m");
die(1);
}
}
/*
* read_packet - get a PPP packet from the serial device.
*/
@ -162,11 +358,9 @@ read_packet(buf)
{
int len;
if ((len = read(fd, buf, MTU + DLLHEADERLEN)) < 0) {
if (errno == EWOULDBLOCK) {
MAINDEBUG((LOG_DEBUG, "read(fd): EWOULDBLOCK"));
if ((len = read(fd, buf, PPP_MTU + PPP_HDRLEN)) < 0) {
if (errno == EWOULDBLOCK || errno == EINTR)
return -1;
}
syslog(LOG_ERR, "read(fd): %m");
die(1);
}
@ -181,7 +375,7 @@ read_packet(buf)
void
ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
int unit, mtu;
u_long asyncmap;
u_int32_t asyncmap;
int pcomp, accomp;
{
u_int x;
@ -189,7 +383,7 @@ ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
ifr.ifr_mtu = mtu;
if (ioctl(s, SIOCSIFMTU, (caddr_t) &ifr) < 0) {
if (ioctl(sockfd, SIOCSIFMTU, (caddr_t) &ifr) < 0) {
syslog(LOG_ERR, "ioctl(SIOCSIFMTU): %m");
quit();
}
@ -232,7 +426,7 @@ ppp_set_xaccm(unit, accm)
void
ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
int unit, mru;
u_long asyncmap;
u_int32_t asyncmap;
int pcomp, accomp;
{
int x;
@ -256,6 +450,59 @@ ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
}
}
/*
* 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;
data.ptr = opt_ptr;
data.length = opt_len;
data.transmit = for_transmit;
return ioctl(fd, PPPIOCSCOMPRESS, (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;
if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
return;
}
x = isopen? x | SC_CCP_OPEN: x &~ SC_CCP_OPEN;
x = isup? x | SC_CCP_UP: x &~ SC_CCP_UP;
if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
}
/*
* ccp_fatal_error - returns 1 if decompression was disabled as a
* result of an error detected after decompression of a packet,
* 0 otherwise. This is necessary because of patent nonsense.
*/
int
ccp_fatal_error(unit)
int unit;
{
int x;
if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
syslog(LOG_ERR, "ioctl(PPPIOCGFLAGS): %m");
return 0;
}
return x & SC_DC_FERROR;
}
/*
* sifvjcomp - config tcp header compression
*/
@ -285,31 +532,45 @@ sifvjcomp(u, vjcomp, cidcomp, maxcid)
/*
* sifup - Config the interface up and enable IP packets to pass.
*/
#ifndef SC_ENABLE_IP
#define SC_ENABLE_IP 0x100 /* compat for old versions of kernel code */
#endif
int
sifup(u)
int u;
{
struct ifreq ifr;
u_int x;
struct npioctl npi;
strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
return 0;
}
ifr.ifr_flags |= IFF_UP;
if (ioctl(s, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
return 0;
}
if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
return 0;
}
x |= SC_ENABLE_IP;
if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
return 0;
npi.protocol = PPP_IP;
npi.mode = NPMODE_PASS;
if (ioctl(fd, PPPIOCSNPMODE, &npi) < 0) {
if (errno != ENOTTY) {
syslog(LOG_ERR, "ioctl(PPPIOCSNPMODE): %m");
return 0;
}
/* for backwards compatibility */
if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
return 0;
}
x |= SC_ENABLE_IP;
if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
return 0;
}
}
return 1;
}
@ -324,25 +585,37 @@ sifdown(u)
struct ifreq ifr;
u_int x;
int rv;
struct npioctl npi;
rv = 1;
if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
rv = 0;
} else {
x &= ~SC_ENABLE_IP;
if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
npi.protocol = PPP_IP;
npi.mode = NPMODE_ERROR;
if (ioctl(fd, PPPIOCSNPMODE, (caddr_t) &npi) < 0) {
if (errno != ENOTTY) {
syslog(LOG_ERR, "ioctl(PPPIOCSNPMODE): %m");
rv = 0;
} else {
/* backwards compatibility */
if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
rv = 0;
} else {
x &= ~SC_ENABLE_IP;
if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
rv = 0;
}
}
}
}
strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
rv = 0;
} else {
ifr.ifr_flags &= ~IFF_UP;
if (ioctl(s, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
rv = 0;
}
@ -365,7 +638,7 @@ sifdown(u)
int
sifaddr(u, o, h, m)
int u;
u_long o, h, m;
u_int32_t o, h, m;
{
struct ifaliasreq ifra;
@ -379,7 +652,7 @@ sifaddr(u, o, h, m)
((struct sockaddr_in *) &ifra.ifra_mask)->sin_addr.s_addr = m;
} else
BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask));
if (ioctl(s, SIOCAIFADDR, (caddr_t) &ifra) < 0) {
if (ioctl(sockfd, SIOCAIFADDR, (caddr_t) &ifra) < 0) {
if (errno != EEXIST) {
syslog(LOG_ERR, "ioctl(SIOCAIFADDR): %m");
return 0;
@ -396,7 +669,7 @@ sifaddr(u, o, h, m)
int
cifaddr(u, o, h)
int u;
u_long o, h;
u_int32_t o, h;
{
struct ifaliasreq ifra;
@ -406,21 +679,20 @@ cifaddr(u, o, h)
SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET);
((struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h;
BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask));
if (ioctl(s, SIOCDIFADDR, (caddr_t) &ifra) < 0) {
if (ioctl(sockfd, SIOCDIFADDR, (caddr_t) &ifra) < 0) {
syslog(LOG_WARNING, "ioctl(SIOCDIFADDR): %m");
return 0;
}
return 1;
}
/*
* sifdefaultroute - assign a default route through the address given.
*/
int
sifdefaultroute(u, g)
int u;
u_long g;
u_int32_t g;
{
return dodefaultroute(g, 's');
}
@ -431,7 +703,7 @@ sifdefaultroute(u, g)
int
cifdefaultroute(u, g)
int u;
u_long g;
u_int32_t g;
{
return dodefaultroute(g, 'c');
}
@ -441,7 +713,7 @@ cifdefaultroute(u, g)
*/
int
dodefaultroute(g, cmd)
u_long g;
u_int32_t g;
int cmd;
{
int routes;
@ -499,7 +771,7 @@ static int arpmsg_valid;
int
sifproxyarp(unit, hisaddr)
int unit;
u_long hisaddr;
u_int32_t hisaddr;
{
int routes;
int l;
@ -549,7 +821,7 @@ sifproxyarp(unit, hisaddr)
int
cifproxyarp(unit, hisaddr)
int unit;
u_long hisaddr;
u_int32_t hisaddr;
{
int routes;
@ -583,7 +855,7 @@ cifproxyarp(unit, hisaddr)
int
sifproxyarp(unit, hisaddr)
int unit;
u_long hisaddr;
u_int32_t hisaddr;
{
struct arpreq arpreq;
struct {
@ -608,7 +880,7 @@ sifproxyarp(unit, hisaddr)
SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
arpreq.arp_flags = ATF_PERM | ATF_PUBL;
if (ioctl(s, SIOCSARP, (caddr_t)&arpreq) < 0) {
if (ioctl(sockfd, SIOCSARP, (caddr_t)&arpreq) < 0) {
syslog(LOG_ERR, "ioctl(SIOCSARP): %m");
return 0;
}
@ -622,14 +894,14 @@ sifproxyarp(unit, hisaddr)
int
cifproxyarp(unit, hisaddr)
int unit;
u_long hisaddr;
u_int32_t hisaddr;
{
struct arpreq arpreq;
BZERO(&arpreq, sizeof(arpreq));
SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
if (ioctl(s, SIOCDARP, (caddr_t)&arpreq) < 0) {
if (ioctl(sockfd, SIOCDARP, (caddr_t)&arpreq) < 0) {
syslog(LOG_WARNING, "ioctl(SIOCDARP): %m");
return 0;
}
@ -646,11 +918,11 @@ cifproxyarp(unit, hisaddr)
int
get_ether_addr(ipaddr, hwaddr)
u_long ipaddr;
u_int32_t ipaddr;
struct sockaddr_dl *hwaddr;
{
struct ifreq *ifr, *ifend, *ifp;
u_long ina, mask;
u_int32_t ina, mask;
struct sockaddr_dl *dla;
struct ifreq ifreq;
struct ifconf ifc;
@ -658,7 +930,7 @@ get_ether_addr(ipaddr, hwaddr)
ifc.ifc_len = sizeof(ifs);
ifc.ifc_req = ifs;
if (ioctl(s, SIOCGIFCONF, &ifc) < 0) {
if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
syslog(LOG_ERR, "ioctl(SIOCGIFCONF): %m");
return 0;
}
@ -668,7 +940,8 @@ get_ether_addr(ipaddr, hwaddr)
* address on the same subnet as `ipaddr'.
*/
ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
for (ifr = ifc.ifc_req; ifr < ifend; ) {
for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *)
((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len)) {
if (ifr->ifr_addr.sa_family == AF_INET) {
ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
@ -676,7 +949,7 @@ get_ether_addr(ipaddr, hwaddr)
* Check that the interface is up, and not point-to-point
* or loopback.
*/
if (ioctl(s, SIOCGIFFLAGS, &ifreq) < 0)
if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
continue;
if ((ifreq.ifr_flags &
(IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
@ -685,15 +958,14 @@ get_ether_addr(ipaddr, hwaddr)
/*
* Get its netmask and check that it's on the right subnet.
*/
if (ioctl(s, SIOCGIFNETMASK, &ifreq) < 0)
if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
continue;
mask = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr;
if ((ipaddr & mask) != (ina & mask))
continue;
break;
}
ifr = (struct ifreq *) ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len);
}
if (ifr >= ifend)
@ -721,23 +993,143 @@ get_ether_addr(ipaddr, hwaddr)
return 0;
}
/*
* Return user specified netmask, modified by any mask we might determine
* for address `addr' (in network byte order).
* Here we scan through the system's list of interfaces, looking for
* any non-point-to-point interfaces which might appear to be on the same
* network as `addr'. If we find any, we OR in their netmask to the
* user-specified netmask.
*/
u_int32_t
GetMask(addr)
u_int32_t addr;
{
u_int32_t mask, nmask, ina;
struct ifreq *ifr, *ifend, ifreq;
struct ifconf ifc;
struct ifreq ifs[MAX_IFS];
addr = ntohl(addr);
if (IN_CLASSA(addr)) /* determine network mask for address class */
nmask = IN_CLASSA_NET;
else if (IN_CLASSB(addr))
nmask = IN_CLASSB_NET;
else
nmask = IN_CLASSC_NET;
/* class D nets are disallowed by bad_ip_adrs */
mask = netmask | htonl(nmask);
/*
* Scan through the system's network interfaces.
*/
ifc.ifc_len = sizeof(ifs);
ifc.ifc_req = ifs;
if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
syslog(LOG_WARNING, "ioctl(SIOCGIFCONF): %m");
return mask;
}
ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *)
((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len)) {
/*
* Check the interface's internet address.
*/
if (ifr->ifr_addr.sa_family != AF_INET)
continue;
ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
if ((ntohl(ina) & nmask) != (addr & nmask))
continue;
/*
* Check that the interface is up, and not point-to-point or loopback.
*/
strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0)
continue;
if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK))
!= IFF_UP)
continue;
/*
* Get its netmask and OR it into our mask.
*/
if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0)
continue;
mask |= ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr;
}
return mask;
}
/*
* ppp_available - check whether the system has any ppp interfaces
* (in fact we check whether we can do an ioctl on ppp0).
* lock - create a lock file for the named lock device
*/
#define LOCK_PREFIX "/var/spool/lock/LCK.."
int
ppp_available()
lock(dev)
char *dev;
{
int s, ok;
struct ifreq ifr;
char hdb_lock_buffer[12];
int fd, pid, n;
char *p;
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
return 1; /* can't tell - maybe we're not root */
if ((p = strrchr(dev, '/')) != NULL)
dev = p + 1;
lock_file = malloc(strlen(LOCK_PREFIX) + strlen(dev) + 1);
if (lock_file == NULL)
novm("lock file name");
strcat(strcpy(lock_file, LOCK_PREFIX), dev);
strncpy(ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
close(s);
while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
if (errno == EEXIST
&& (fd = open(lock_file, O_RDONLY, 0)) >= 0) {
/* Read the lock file to find out who has the device locked */
n = read(fd, hdb_lock_buffer, 11);
if (n > 0) {
hdb_lock_buffer[n] = 0;
pid = atoi(hdb_lock_buffer);
}
if (n <= 0) {
syslog(LOG_ERR, "Can't read pid from lock file %s", lock_file);
close(fd);
} else {
if (kill(pid, 0) == -1 && errno == ESRCH) {
/* pid no longer exists - remove the lock file */
if (unlink(lock_file) == 0) {
close(fd);
syslog(LOG_NOTICE, "Removed stale lock on %s (pid %d)",
dev, pid);
continue;
} else
syslog(LOG_WARNING, "Couldn't remove stale lock on %s",
dev);
} else
syslog(LOG_NOTICE, "Device %s is locked by pid %d",
dev, pid);
}
close(fd);
} else
syslog(LOG_ERR, "Can't create lock file %s: %m", lock_file);
free(lock_file);
lock_file = NULL;
return -1;
}
return ok;
sprintf(hdb_lock_buffer, "%10d\n", getpid());
write(fd, hdb_lock_buffer, 11);
close(fd);
return 0;
}
/*
* unlock - remove our lockfile
*/
unlock()
{
if (lock_file) {
unlink(lock_file);
free(lock_file);
lock_file = NULL;
}
}

View File

@ -1,830 +0,0 @@
/*
* sys-linux.c - System-dependent procedures for setting up
* PPP interfaces on Linux systems
*
* 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:
*/
#include <stdio.h>
#include <syslog.h>
#include <string.h>
#include <time.h>
#include <memory.h>
#include <utmp.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/errno.h>
#include <mntent.h>
#include <net/if.h>
#include <linux/ppp.h>
#include <linux/route.h>
#include <linux/if_ether.h>
#include <netinet/in.h>
#include <signal.h>
#include "pppd.h"
#include "ppp.h"
#include "fsm.h"
#include "ipcp.h"
static int initdisc = -1; /* Initial TTY discipline */
static int prev_kdebugflag = 0;
extern int kdebugflag;
extern u_long netmask;
#define MAX_IFS 32
/* prototypes */
void die __ARGS((int));
/*
* SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
* if it exists.
*/
#define SET_SA_FAMILY(addr, family) \
memset ((char *) &(addr), '\0', sizeof(addr)); \
addr.sa_family = (family);
/*
* set_kdebugflag - Define the debugging level for the kernel
*/
int set_kdebugflag (int requested_level)
{
if (ioctl(fd, PPPIOCGDEBUG, &prev_kdebugflag) < 0) {
syslog(LOG_ERR, "ioctl(PPPIOCGDEBUG): %m");
return (0);
}
if (prev_kdebugflag != requested_level) {
if (ioctl(fd, PPPIOCSDEBUG, &requested_level) < 0) {
syslog (LOG_ERR, "ioctl(PPPIOCSDEBUG): %m");
return (0);
}
syslog(LOG_INFO, "set kernel debugging level to %d", requested_level);
}
return (1);
}
/*
* establish_ppp - Turn the serial port into a ppp interface.
*/
void establish_ppp (void)
{
int pppdisc = N_PPP;
int sig = SIGIO;
if (ioctl(fd, PPPIOCSINPSIG, &sig) == -1) {
syslog(LOG_ERR, "ioctl(PPPIOCSINPSIG): %m");
die(1);
}
if (ioctl(fd, TIOCEXCL, 0) < 0) {
syslog (LOG_WARNING, "ioctl(TIOCEXCL): %m");
}
if (ioctl(fd, TIOCGETD, &initdisc) < 0) {
syslog(LOG_ERR, "ioctl(TIOCGETD): %m");
die (1);
}
if (ioctl(fd, TIOCSETD, &pppdisc) < 0) {
syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
die (1);
}
if (ioctl(fd, PPPIOCGUNIT, &ifunit) < 0) {
syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
die (1);
}
set_kdebugflag (kdebugflag);
}
/*
* disestablish_ppp - Restore the serial port to normal operation.
* This shouldn't call die() because it's called from die().
*/
void disestablish_ppp(void)
{
int x;
char *s;
if (initdisc >= 0) {
set_kdebugflag (prev_kdebugflag);
/*
* Check whether the link seems not to be 8-bit clean.
*/
if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) == 0) {
s = NULL;
switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) {
case SC_RCV_B7_0:
s = "bit 7 set to 1";
break;
case SC_RCV_B7_1:
s = "bit 7 set to 0";
break;
case SC_RCV_EVNP:
s = "odd parity";
break;
case SC_RCV_ODDP:
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);
}
}
if (ioctl(fd, TIOCSETD, &initdisc) < 0)
syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
if (ioctl(fd, TIOCNXCL, 0) < 0)
syslog (LOG_WARNING, "ioctl(TIOCNXCL): %m");
initdisc = -1;
}
}
/*
* output - Output PPP packet.
*/
void output (int unit, unsigned char *p, int len)
{
if (unit != 0)
MAINDEBUG((LOG_WARNING, "output: unit != 0!"));
if (debug)
log_packet(p, len, "sent ");
if (write(fd, p, len) < 0) {
syslog(LOG_ERR, "write: %m");
die(1);
}
}
/*
* read_packet - get a PPP packet from the serial device.
*/
int read_packet (unsigned char *buf)
{
int len;
len = read(fd, buf, MTU + DLLHEADERLEN);
if (len < 0) {
if (errno == EWOULDBLOCK) {
#if 0
MAINDEBUG((LOG_DEBUG, "read(fd): EWOULDBLOCK"));
#endif
return -1;
}
syslog(LOG_ERR, "read(fd): %m");
die(1);
}
return len;
}
/*
* ppp_send_config - configure the transmit characteristics of
* the ppp interface.
*/
void ppp_send_config (int unit,int mtu,u_long asyncmap,int pcomp,int accomp)
{
u_int x;
struct ifreq ifr;
MAINDEBUG ((LOG_DEBUG, "send_config: mtu = %d\n", mtu));
strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
ifr.ifr_mtu = mtu;
if (ioctl(s, SIOCSIFMTU, (caddr_t) &ifr) < 0) {
syslog(LOG_ERR, "ioctl(SIOCSIFMTU): %m");
quit();
}
MAINDEBUG ((LOG_DEBUG, "send_config: asyncmap = %lx\n", asyncmap));
if (ioctl(fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) {
syslog(LOG_ERR, "ioctl(PPPIOCSASYNCMAP): %m");
quit();
}
if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
quit();
}
x = pcomp ? x | SC_COMP_PROT : x & ~SC_COMP_PROT;
x = accomp ? x | SC_COMP_AC : x & ~SC_COMP_AC;
MAINDEBUG ((LOG_DEBUG, "send_config: flags = %x\n", x));
if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
quit();
}
}
/*
* ppp_set_xaccm - set the extended transmit ACCM for the interface.
*/
void
ppp_set_xaccm(unit, accm)
int unit;
ext_accm accm;
{
MAINDEBUG ((LOG_DEBUG, "set_xaccm: %08lx %08lx %08lx %08lx\n",
accm[0], accm[1], accm[2], accm[3]));
if (ioctl(fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY)
syslog(LOG_WARNING, "ioctl(set extended ACCM): %m");
}
/*
* ppp_recv_config - configure the receive-side characteristics of
* the ppp interface.
*/
void ppp_recv_config (int unit,int mru,u_long asyncmap,int pcomp,int accomp)
{
u_int x;
MAINDEBUG ((LOG_DEBUG, "recv_config: mru = %d\n", mru));
if (ioctl(fd, PPPIOCSMRU, (caddr_t) &mru) < 0)
syslog(LOG_ERR, "ioctl(PPPIOCSMRU): %m");
MAINDEBUG ((LOG_DEBUG, "recv_config: asyncmap = %lx\n", asyncmap));
if (ioctl(fd, PPPIOCRASYNCMAP, (caddr_t) &asyncmap) < 0) {
syslog(LOG_ERR, "ioctl(PPPIOCRASYNCMAP): %m");
quit();
}
if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
quit();
}
x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC;
MAINDEBUG ((LOG_DEBUG, "recv_config: flags = %x\n", x));
if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
quit();
}
}
/*
* sifvjcomp - config tcp header compression
*/
int sifvjcomp (int u, int vjcomp, int cidcomp, int maxcid)
{
u_int x;
if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
return 0;
}
x = vjcomp ? x | SC_COMP_TCP : x &~ SC_COMP_TCP;
x = cidcomp ? x & ~SC_NO_TCP_CCID : x | SC_NO_TCP_CCID;
if(ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
return 0;
}
if (vjcomp) {
if (ioctl (fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) {
syslog (LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
return 0;
}
}
return 1;
}
/*
* sifup - Config the interface up and enable IP packets to pass.
*/
int sifup (int u)
{
struct ifreq ifr;
strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
return 0;
}
ifr.ifr_flags |= (IFF_UP | IFF_POINTOPOINT);
if (ioctl(s, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
return 0;
}
return 1;
}
/*
* sifdown - Config the interface down and disable IP.
*/
int sifdown (int u)
{
struct ifreq ifr;
strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
return 0;
}
ifr.ifr_flags &= ~IFF_UP;
ifr.ifr_flags |= IFF_POINTOPOINT;
if (ioctl(s, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
return 0;
}
return 1;
}
/*
* sifaddr - Config the interface IP addresses and netmask.
*/
int sifaddr (int unit, int our_adr, int his_adr, int net_mask)
{
struct ifreq ifr;
struct rtentry rt;
SET_SA_FAMILY (ifr.ifr_addr, AF_INET);
SET_SA_FAMILY (ifr.ifr_dstaddr, AF_INET);
SET_SA_FAMILY (ifr.ifr_netmask, AF_INET);
strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
/*
* Set our IP address
*/
((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = our_adr;
if (ioctl(s, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
if (errno != EEXIST)
syslog (LOG_ERR, "ioctl(SIOCAIFADDR): %m");
else
syslog (LOG_WARNING, "ioctl(SIOCAIFADDR): Address already exists");
return (0);
}
/*
* Set the gateway address
*/
((struct sockaddr_in *) &ifr.ifr_dstaddr)->sin_addr.s_addr = his_adr;
if (ioctl(s, SIOCSIFDSTADDR, (caddr_t) &ifr) < 0) {
syslog (LOG_ERR, "ioctl(SIOCSIFDSTADDR): %m");
return (0);
}
/*
* Set the netmask
*/
if (net_mask != 0) {
((struct sockaddr_in *) &ifr.ifr_netmask)->sin_addr.s_addr = net_mask;
if (ioctl(s, SIOCSIFNETMASK, (caddr_t) &ifr) < 0) {
syslog (LOG_ERR, "ioctl(SIOCSIFNETMASK): %m");
return (0);
}
}
/*
* Add the device route
*/
memset (&rt, '\0', sizeof (rt));
SET_SA_FAMILY (rt.rt_dst, AF_INET);
SET_SA_FAMILY (rt.rt_gateway, AF_INET);
rt.rt_dev = ifname; /* MJC */
((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = 0;
((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr = his_adr;
rt.rt_flags = RTF_UP | RTF_HOST;
if (ioctl(s, SIOCADDRT, &rt) < 0) {
syslog (LOG_ERR, "ioctl(SIOCADDRT) device route: %m");
return (0);
}
return 1;
}
/*
* cifaddr - Clear the interface IP addresses, and delete routes
* through the interface if possible.
*/
int cifaddr (int unit, int our_adr, int his_adr)
{
struct rtentry rt;
/*
* Delete the route through the device
*/
memset (&rt, '\0', sizeof (rt));
SET_SA_FAMILY (rt.rt_dst, AF_INET);
SET_SA_FAMILY (rt.rt_gateway, AF_INET);
rt.rt_dev = ifname; /* MJC */
((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = 0;
((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr = his_adr;
rt.rt_flags = RTF_UP | RTF_HOST;
if (ioctl(s, SIOCDELRT, &rt) < 0) {
syslog (LOG_ERR, "ioctl(SIOCDELRT) device route: %m");
return (0);
}
return 1;
}
/*
* path_to_route - determine the path to the proc file system data
*/
FILE *route_fd = (FILE *) 0;
static char route_buffer [100];
static char *path_to_route (void);
static int open_route_table (void);
static void close_route_table (void);
static int read_route_table (struct rtentry *rt);
static int defaultroute_exists (void);
/*
* path_to_route - find the path to the route tables in the proc file system
*/
static char *path_to_route (void)
{
struct mntent *mntent;
FILE *fp;
fp = fopen (MOUNTED, "r");
if (fp != 0) {
while ((mntent = getmntent (fp)) != 0) {
if (strcmp (mntent->mnt_type, MNTTYPE_IGNORE) == 0)
continue;
if (strcmp (mntent->mnt_type, "proc") == 0) {
strncpy (route_buffer, mntent->mnt_dir,
sizeof (route_buffer)-10);
route_buffer [sizeof (route_buffer)-10] = '\0';
strcat (route_buffer, "/net/route");
fclose (fp);
return (route_buffer);
}
}
fclose (fp);
}
syslog (LOG_ERR, "proc file system not mounted");
return 0;
}
/*
* open_route_table - open the interface to the route table
*/
static int open_route_table (void)
{
char *path;
if (route_fd != (FILE *) 0)
close_route_table();
path = path_to_route();
if (path == NULL)
return 0;
route_fd = fopen (path, "r");
if (route_fd == (FILE *) 0) {
syslog (LOG_ERR, "can not open %s: %m", path);
return 0;
}
/* read and discard the header line. */
if (fgets (route_buffer, sizeof (route_buffer), route_fd) == (char *) 0) {
close_route_table();
return 0;
}
return 1;
}
/*
* close_route_table - close the interface to the route table
*/
static void close_route_table (void)
{
if (route_fd != (FILE *) 0) {
fclose (route_fd);
route_fd = (FILE *) 0;
}
}
/*
* read_route_table - read the next entry from the route table
*/
static int read_route_table (struct rtentry *rt)
{
static char delims[] = " \t\n";
char *dev_ptr, *ptr, *dst_ptr, *gw_ptr, *flag_ptr;
if (fgets (route_buffer, sizeof (route_buffer), route_fd) == (char *) 0)
return 0;
memset (rt, '\0', sizeof (struct rtentry));
dev_ptr = strtok (route_buffer, delims); /* interface name */
dst_ptr = strtok (NULL, delims); /* destination address */
gw_ptr = strtok (NULL, delims); /* gateway */
flag_ptr = strtok (NULL, delims); /* flags */
#if 0
ptr = strtok (NULL, delims); /* reference count */
ptr = strtok (NULL, delims); /* useage count */
ptr = strtok (NULL, delims); /* metric */
ptr = strtok (NULL, delims); /* mask */
#endif
((struct sockaddr_in *) &rt->rt_dst)->sin_addr.s_addr =
strtoul (dst_ptr, NULL, 16);
((struct sockaddr_in *) &rt->rt_gateway)->sin_addr.s_addr =
strtoul (gw_ptr, NULL, 16);
rt->rt_flags = (short) strtoul (flag_ptr, NULL, 16);
rt->rt_dev = dev_ptr;
return 1;
}
/*
* defaultroute_exists - determine if there is a default route
*/
static int defaultroute_exists (void)
{
struct rtentry rt;
int result = 0;
if (!open_route_table())
return 0;
while (read_route_table(&rt) != 0) {
if (rt.rt_flags & RTF_UP == 0)
continue;
if (((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr == 0L) {
syslog (LOG_ERR,
"ppp not replacing existing default route to %s[%s]",
rt.rt_dev,
inet_ntoa (((struct sockaddr_in *) &rt.rt_gateway)->
sin_addr.s_addr));
result = 1;
break;
}
}
close_route_table();
return result;
}
/*
* sifdefaultroute - assign a default route through the address given.
*/
int sifdefaultroute (int unit, int gateway)
{
struct rtentry rt;
if (defaultroute_exists())
return 0;
memset (&rt, '\0', sizeof (rt));
SET_SA_FAMILY (rt.rt_dst, AF_INET);
SET_SA_FAMILY (rt.rt_gateway, AF_INET);
((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = gateway;
rt.rt_flags = RTF_UP | RTF_GATEWAY;
if (ioctl(s, SIOCADDRT, &rt) < 0) {
syslog (LOG_ERR, "default route ioctl(SIOCADDRT): %m");
return 0;
}
return 1;
}
/*
* cifdefaultroute - delete a default route through the address given.
*/
int cifdefaultroute (int unit, int gateway)
{
struct rtentry rt;
SET_SA_FAMILY (rt.rt_dst, AF_INET);
SET_SA_FAMILY (rt.rt_gateway, AF_INET);
((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = gateway;
rt.rt_flags = RTF_UP | RTF_GATEWAY;
if (ioctl(s, SIOCDELRT, &rt) < 0) {
syslog (LOG_ERR, "default route ioctl(SIOCDELRT): %m");
return 0;
}
return 1;
}
/*
* sifproxyarp - Make a proxy ARP entry for the peer.
*/
int sifproxyarp (int unit, u_long his_adr)
{
struct arpreq arpreq;
memset (&arpreq, '\0', sizeof(arpreq));
/*
* Get the hardware address of an interface on the same subnet
* as our local address.
*/
if (!get_ether_addr(his_adr, &arpreq.arp_ha)) {
syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP");
return 0;
}
SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = his_adr;
arpreq.arp_flags = ATF_PERM | ATF_PUBL;
if (ioctl(s, SIOCSARP, (caddr_t)&arpreq) < 0) {
syslog(LOG_ERR, "ioctl(SIOCSARP): %m");
return 0;
}
return 1;
}
/*
* cifproxyarp - Delete the proxy ARP entry for the peer.
*/
int cifproxyarp (int unit, u_long his_adr)
{
struct arpreq arpreq;
memset (&arpreq, '\0', sizeof(arpreq));
SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = his_adr;
if (ioctl(s, SIOCDARP, (caddr_t)&arpreq) < 0) {
syslog(LOG_WARNING, "ioctl(SIOCDARP): %m");
return 0;
}
return 1;
}
/*
* get_ether_addr - get the hardware address of an interface on the
* the same subnet as ipaddr.
*/
int get_ether_addr (u_long ipaddr, struct sockaddr *hwaddr)
{
struct ifreq *ifr, *ifend, *ifp;
int i;
u_long ina, mask;
struct sockaddr_dl *dla;
struct ifreq ifreq;
struct ifconf ifc;
struct ifreq ifs[MAX_IFS];
ifc.ifc_len = sizeof(ifs);
ifc.ifc_req = ifs;
if (ioctl(s, SIOCGIFCONF, &ifc) < 0) {
syslog(LOG_ERR, "ioctl(SIOCGIFCONF): %m");
return 0;
}
MAINDEBUG ((LOG_DEBUG, "proxy arp: scanning %d interfaces for IP %s",
ifc.ifc_len / sizeof(struct ifreq), ip_ntoa(ipaddr)));
/*
* Scan through looking for an interface with an Internet
* address on the same subnet as `ipaddr'.
*/
ifend = ifs + (ifc.ifc_len / sizeof(struct ifreq));
for (ifr = ifc.ifc_req; ifr < ifend; ifr++) {
if (ifr->ifr_addr.sa_family == AF_INET) {
ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
MAINDEBUG ((LOG_DEBUG, "proxy arp: examining interface %s",
ifreq.ifr_name));
/*
* Check that the interface is up, and not point-to-point
* or loopback.
*/
if (ioctl(s, SIOCGIFFLAGS, &ifreq) < 0)
continue;
if ((ifreq.ifr_flags &
(IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
!= (IFF_UP|IFF_BROADCAST))
continue;
/*
* Get its netmask and check that it's on the right subnet.
*/
if (ioctl(s, SIOCGIFNETMASK, &ifreq) < 0)
continue;
mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr;
MAINDEBUG ((LOG_DEBUG, "proxy arp: interface addr %s mask %lx",
ip_ntoa(ina), ntohl(mask)));
if (((ipaddr ^ ina) & mask) != 0)
continue;
break;
}
}
if (ifr >= ifend)
return 0;
syslog(LOG_INFO, "found interface %s for proxy arp", ifreq.ifr_name);
/*
* Now get the hardware address.
*/
if (ioctl (s, SIOCGIFHWADDR, &ifreq) < 0) {
syslog(LOG_ERR, "SIOCGIFHWADDR(%s): %m", ifreq.ifr_name);
return 0;
}
hwaddr->sa_family = ARPHRD_ETHER;
#ifndef old_ifr_hwaddr
memcpy (&hwaddr->sa_data, &ifreq.ifr_hwaddr, ETH_ALEN);
#else
memcpy (&hwaddr->sa_data, &ifreq.ifr_hwaddr.sa_data, ETH_ALEN);
#endif
MAINDEBUG ((LOG_DEBUG,
"proxy arp: found hwaddr %02x:%02x:%02x:%02x:%02x:%02x",
(int) ((unsigned char *) &hwaddr->sa_data)[0],
(int) ((unsigned char *) &hwaddr->sa_data)[1],
(int) ((unsigned char *) &hwaddr->sa_data)[2],
(int) ((unsigned char *) &hwaddr->sa_data)[3],
(int) ((unsigned char *) &hwaddr->sa_data)[4],
(int) ((unsigned char *) &hwaddr->sa_data)[5]));
return 1;
}
/*
* ppp_available - check whether the system has any ppp interfaces
* (in fact we check whether we can do an ioctl on ppp0).
*/
int ppp_available(void)
{
int s, ok;
struct ifreq ifr;
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0)
return 1; /* can't tell - maybe we're not root */
strncpy(ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
close(s);
return ok;
}
int
logwtmp(line, name, host)
char *line, *name, *host;
{
struct utmp ut;
memset (&ut, 0, sizeof (ut));
(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);
pututline (&ut); /* Write the line to the proper place */
endutent(); /* Indicate operation is complete */
}

View File

@ -1,730 +0,0 @@
/*
* sys-str.c - System-dependent procedures for setting up
* PPP interfaces on systems which use the STREAMS ppp interface.
*
* 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:
*/
#include <stdio.h>
#include <errno.h>
#include <syslog.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <utmp.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/stream.h>
#include <sys/stropts.h>
#include <net/if.h>
#include <net/route.h>
#include <net/if_arp.h>
#include <netinet/in.h>
#include "pppd.h"
#include "ppp.h"
#include <net/ppp_str.h>
#ifndef ifr_mtu
#define ifr_mtu ifr_metric
#endif
#define MAXMODULES 10 /* max number of module names to save */
static struct modlist {
char modname[FMNAMESZ+1];
} str_modules[MAXMODULES];
static int str_module_count = 0;
static int pushed_ppp;
extern int hungup; /* has the physical layer been disconnected? */
extern int kdebugflag;
#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
/*
* 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;
}
/*
* establish_ppp - Turn the serial port into a ppp interface.
*/
void
establish_ppp()
{
/* go through and save the name of all the modules, then pop em */
for (;;) {
if (ioctl(fd, I_LOOK, str_modules[str_module_count].modname) < 0 ||
ioctl(fd, I_POP, 0) < 0)
break;
MAINDEBUG((LOG_DEBUG, "popped stream module : %s",
str_modules[str_module_count].modname));
str_module_count++;
}
/* now push the async/fcs module */
if (ioctl(fd, I_PUSH, "pppasync") < 0) {
syslog(LOG_ERR, "ioctl(I_PUSH, ppp_async): %m");
die(1);
}
/* 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);
}
pushed_ppp = 1;
if (ioctl(fd, I_SETSIG, S_INPUT) < 0) {
syslog(LOG_ERR, "ioctl(I_SETSIG, S_INPUT): %m");
die(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)
*/
if (ioctl(fd, SIOCGETU, &ifunit) < 0) {
syslog(LOG_ERR, "ioctl(SIOCGETU): %m");
die(1);
}
/* Set debug flags in driver */
if (ioctl(fd, SIOCSIFDEBUG, &kdebugflag) < 0) {
syslog(LOG_ERR, "ioctl(SIOCSIFDEBUG): %m");
}
}
/*
* disestablish_ppp - Restore the serial port to normal operation.
* It attempts to reconstruct the stream with the previously popped
* modules. This shouldn't call die() because it's called from die().
*/
void
disestablish_ppp()
{
int flags;
char *s;
if (hungup) {
/* we can't push or pop modules after the stream has hung up */
str_module_count = 0;
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_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));
}
}
}
/*
* output - Output PPP packet.
*/
void
output(unit, p, len)
int unit;
u_char *p;
int len;
{
struct strbuf str;
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);
}
}
/*
* read_packet - get a PPP packet from the serial device.
*/
int
read_packet(buf)
u_char *buf;
{
struct strbuf str;
int len, i;
str.maxlen = MTU+DLLHEADERLEN;
str.buf = (caddr_t) buf;
i = 0;
len = getmsg(fd, NULL, &str, &i);
if (len < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
return -1;
}
syslog(LOG_ERR, "getmsg(fd) %m");
die(1);
}
if (len)
MAINDEBUG((LOG_DEBUG, "getmsg returned 0x%x",len));
if (str.len < 0) {
MAINDEBUG((LOG_DEBUG, "getmsg short return length %d", str.len));
return -1;
}
return str.len;
}
/*
* ppp_send_config - configure the transmit characteristics of
* the ppp interface.
*/
void
ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
int unit, mtu;
u_long asyncmap;
int pcomp, accomp;
{
char c;
struct ifreq ifr;
strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
ifr.ifr_mtu = mtu;
if (ioctl(s, SIOCSIFMTU, (caddr_t) &ifr) < 0) {
syslog(LOG_ERR, "ioctl(SIOCSIFMTU): %m");
quit();
}
if(ioctl(fd, SIOCSIFASYNCMAP, (caddr_t) &asyncmap) < 0) {
syslog(LOG_ERR, "ioctl(SIOCSIFASYNCMAP): %m");
quit();
}
c = (pcomp? 1: 0);
if(ioctl(fd, SIOCSIFCOMPPROT, &c) < 0) {
syslog(LOG_ERR, "ioctl(SIOCSIFCOMPPROT): %m");
quit();
}
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.
*/
void
ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
int unit, mru;
u_long asyncmap;
int pcomp, accomp;
{
char c;
if (ioctl(fd, SIOCSIFMRU, &mru) < 0) {
syslog(LOG_ERR, "ioctl(SIOCSIFMRU): %m");
}
if (ioctl(fd, SIOCSIFRASYNCMAP, (caddr_t) &asyncmap) < 0) {
syslog(LOG_ERR, "ioctl(SIOCSIFRASYNCMAP): %m");
}
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");
}
}
/*
* sifvjcomp - config tcp header compression
*/
int
sifvjcomp(u, vjcomp, cidcomp, maxcid)
int u, vjcomp, cidcomp, maxcid;
{
char x;
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;
}
return 1;
}
/*
* sifup - Config the interface up.
*/
int
sifup(u)
int u;
{
struct ifreq ifr;
strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
return 0;
}
ifr.ifr_flags |= IFF_UP;
if (ioctl(s, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
return 0;
}
return 1;
}
/*
* sifdown - Config the interface down.
*/
int
sifdown(u)
int u;
{
struct ifreq ifr;
strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
return 0;
}
ifr.ifr_flags &= ~IFF_UP;
if (ioctl(s, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
return 0;
}
return 1;
}
/*
* SET_SA_FAMILY - initialize a struct sockaddr, setting the sa_family field.
*/
#define SET_SA_FAMILY(addr, family) \
BZERO((char *) &(addr), sizeof(addr)); \
addr.sa_family = (family);
/*
* sifaddr - Config the interface IP addresses and netmask.
*/
int
sifaddr(u, o, h, m)
int u;
u_long o, h, m;
{
int ret;
struct ifreq ifr;
ret = 1;
strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
SET_SA_FAMILY(ifr.ifr_addr, AF_INET);
((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = o;
if (ioctl(s, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
syslog(LOG_ERR, "ioctl(SIOCSIFADDR): %m");
ret = 0;
}
((struct sockaddr_in *) &ifr.ifr_dstaddr)->sin_addr.s_addr = h;
if (ioctl(s, SIOCSIFDSTADDR, (caddr_t) &ifr) < 0) {
syslog(LOG_ERR, "ioctl(SIOCSIFDSTADDR): %m");
ret = 0;
}
if (m != 0) {
((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = m;
syslog(LOG_INFO, "Setting interface mask to %s\n", ip_ntoa(m));
if (ioctl(s, SIOCSIFNETMASK, (caddr_t) &ifr) < 0) {
syslog(LOG_ERR, "ioctl(SIOCSIFNETMASK): %m");
ret = 0;
}
}
return ret;
}
/*
* cifaddr - Clear the interface IP addresses, and delete routes
* through the interface if possible.
*/
int
cifaddr(u, o, h)
int u;
u_long o, h;
{
struct rtentry rt;
SET_SA_FAMILY(rt.rt_dst, AF_INET);
((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr = h;
SET_SA_FAMILY(rt.rt_gateway, AF_INET);
((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = o;
rt.rt_flags = RTF_HOST;
if (ioctl(s, SIOCDELRT, (caddr_t) &rt) < 0) {
syslog(LOG_ERR, "ioctl(SIOCDELRT): %m");
return 0;
}
return 1;
}
/*
* sifdefaultroute - assign a default route through the address given.
*/
int
sifdefaultroute(u, g)
int u;
u_long g;
{
struct rtentry rt;
SET_SA_FAMILY(rt.rt_dst, AF_INET);
SET_SA_FAMILY(rt.rt_gateway, AF_INET);
((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = g;
rt.rt_flags = RTF_GATEWAY;
if (ioctl(s, SIOCADDRT, &rt) < 0) {
syslog(LOG_ERR, "default route ioctl(SIOCADDRT): %m");
return 0;
}
return 1;
}
/*
* cifdefaultroute - delete a default route through the address given.
*/
int
cifdefaultroute(u, g)
int u;
u_long g;
{
struct rtentry rt;
SET_SA_FAMILY(rt.rt_dst, AF_INET);
SET_SA_FAMILY(rt.rt_gateway, AF_INET);
((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = g;
rt.rt_flags = RTF_GATEWAY;
if (ioctl(s, SIOCDELRT, &rt) < 0) {
syslog(LOG_ERR, "default route ioctl(SIOCDELRT): %m");
return 0;
}
return 1;
}
/*
* sifproxyarp - Make a proxy ARP entry for the peer.
*/
int
sifproxyarp(unit, hisaddr)
int unit;
u_long hisaddr;
{
struct arpreq arpreq;
BZERO(&arpreq, sizeof(arpreq));
/*
* Get the hardware address of an interface on the same subnet
* as our local address.
*/
if (!get_ether_addr(hisaddr, &arpreq.arp_ha)) {
syslog(LOG_WARNING, "Cannot determine ethernet address for proxy ARP");
return 0;
}
SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
arpreq.arp_flags = ATF_PERM | ATF_PUBL;
if (ioctl(s, SIOCSARP, (caddr_t)&arpreq) < 0) {
syslog(LOG_ERR, "ioctl(SIOCSARP): %m");
return 0;
}
return 1;
}
/*
* cifproxyarp - Delete the proxy ARP entry for the peer.
*/
int
cifproxyarp(unit, hisaddr)
int unit;
u_long hisaddr;
{
struct arpreq arpreq;
BZERO(&arpreq, sizeof(arpreq));
SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
if (ioctl(s, SIOCDARP, (caddr_t)&arpreq) < 0) {
syslog(LOG_ERR, "ioctl(SIOCDARP): %m");
return 0;
}
return 1;
}
/*
* 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 (which also applies to logwtmp below):
*
* Copyright (c) 1990, 1992 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the University of California,
* Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
* the University nor the names of its contributors may 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
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include <fcntl.h>
#include <nlist.h>
#include <kvm.h>
#include <arpa/inet.h>
/* XXX SunOS 4.1 defines this and 3.5 doesn't... */
#ifdef _nlist_h
#define SUNOS4
#endif
#ifdef SUNOS4
#include <netinet/in_var.h>
#endif
#include <netinet/if_ether.h>
/* Cast a struct sockaddr to a structaddr_in */
#define SATOSIN(sa) ((struct sockaddr_in *)(sa))
/* Determine if "bits" is set in "flag" */
#define ALLSET(flag, bits) (((flag) & (bits)) == (bits))
static struct nlist nl[] = {
#define N_IFNET 0
{ "_ifnet" },
{ 0 }
};
static void kread();
int
get_ether_addr(ipaddr, hwaddr)
u_long ipaddr;
struct sockaddr *hwaddr;
{
register kvm_t *kd;
register struct ifnet *ifp;
register struct arpcom *ac;
struct arpcom arpcom;
struct in_addr *inp;
#ifdef SUNOS4
register struct ifaddr *ifa;
register struct in_ifaddr *in;
union {
struct ifaddr ifa;
struct in_ifaddr in;
} ifaddr;
#endif
u_long addr, mask;
/* Open kernel memory for reading */
kd = kvm_open(0, 0, 0, O_RDONLY, NULL);
if (kd == 0) {
syslog(LOG_ERR, "kvm_open: %m");
return 0;
}
/* Fetch namelist */
if (kvm_nlist(kd, nl) != 0) {
syslog(LOG_ERR, "kvm_nlist failed");
return 0;
}
ac = &arpcom;
ifp = &arpcom.ac_if;
#ifdef SUNOS4
ifa = &ifaddr.ifa;
in = &ifaddr.in;
#endif
if (kvm_read(kd, nl[N_IFNET].n_value, (char *)&addr, sizeof(addr))
!= sizeof(addr)) {
syslog(LOG_ERR, "error reading ifnet addr");
return 0;
}
for ( ; addr; addr = (u_long)ifp->if_next) {
if (kvm_read(kd, addr, (char *)ac, sizeof(*ac)) != sizeof(*ac)) {
syslog(LOG_ERR, "error reading ifnet");
return 0;
}
/* Only look at configured, broadcast interfaces */
if (!ALLSET(ifp->if_flags, IFF_UP | IFF_BROADCAST))
continue;
#ifdef SUNOS4
/* This probably can't happen... */
if (ifp->if_addrlist == 0)
continue;
#endif
/* Get interface ip address */
#ifdef SUNOS4
if (kvm_read(kd, (u_long)ifp->if_addrlist, (char *)&ifaddr,
sizeof(ifaddr)) != sizeof(ifaddr)) {
syslog(LOG_ERR, "error reading ifaddr");
return 0;
}
inp = &SATOSIN(&ifa->ifa_addr)->sin_addr;
#else
inp = &SATOSIN(&ifp->if_addr)->sin_addr;
#endif
/* Check if this interface on the right subnet */
#ifdef SUNOS4
mask = in->ia_subnetmask;
#else
mask = ifp->if_subnetmask;
#endif
if ((ipaddr & mask) != (inp->s_addr & mask))
continue;
/* Copy out the local ethernet address */
hwaddr->sa_family = AF_UNSPEC;
BCOPY((caddr_t) &arpcom.ac_enaddr, hwaddr->sa_data,
sizeof(arpcom.ac_enaddr));
return 1; /* success! */
}
/* 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);
}

View File

@ -1,663 +0,0 @@
/*
* sys-ultrix.c - System-dependent procedures for setting up
* PPP interfaces on Ultrix systems.
*
* 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.
*/
#ifndef lint
static char rcsid[] = "$Id: sys-ultrix.c,v 1.4 1994/05/25 06:30:49 paulus Exp $";
#endif
/*
* TODO:
*/
#include <syslog.h>
#include <utmp.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/errno.h>
#include <sys/stat.h>
#include <net/if.h>
#include <net/if_ppp.h>
#include <net/route.h>
#include <netinet/in.h>
#include "pppd.h"
#include "ppp.h"
static int initdisc = -1; /* Initial TTY discipline */
extern int kdebugflag;
/*
* establish_ppp - Turn the serial port into a ppp interface.
*/
void
establish_ppp()
{
int pppdisc = PPPDISC;
int x;
if (ioctl(fd, TIOCGETD, &initdisc) < 0) {
syslog(LOG_ERR, "ioctl(TIOCGETD): %m");
die(1);
}
if (ioctl(fd, TIOCSETD, &pppdisc) < 0) {
syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
die(1);
}
/*
* Find out which interface we were given.
*/
if (ioctl(fd, PPPIOCGUNIT, &ifunit) < 0) {
syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
die(1);
}
/*
* Enable debug in the driver if requested.
*/
if (kdebugflag) {
if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
syslog(LOG_WARNING, "ioctl (PPPIOCGFLAGS): %m");
} else {
x |= (kdebugflag & 0xFF) * SC_DEBUG;
if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
syslog(LOG_WARNING, "ioctl(PPPIOCSFLAGS): %m");
}
}
}
/*
* disestablish_ppp - Restore the serial port to normal operation.
* This shouldn't call die() because it's called from die().
*/
void
disestablish_ppp()
{
int x;
char *s;
if (initdisc >= 0) {
/*
* Check whether the link seems not to be 8-bit clean.
*/
if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) == 0) {
s = NULL;
switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) {
case SC_RCV_B7_0:
s = "bit 7 set to 1";
break;
case SC_RCV_B7_1:
s = "bit 7 set to 0";
break;
case SC_RCV_EVNP:
s = "odd parity";
break;
case SC_RCV_ODDP:
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);
}
}
if (ioctl(fd, TIOCSETD, &initdisc) < 0)
syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
}
}
/*
* output - Output PPP packet.
*/
void
output(unit, p, len)
int unit;
u_char *p;
int len;
{
if (unit != 0)
MAINDEBUG((LOG_WARNING, "output: unit != 0!"));
if (debug)
log_packet(p, len, "sent ");
if (write(fd, p, len) < 0) {
syslog(LOG_ERR, "write: %m");
die(1);
}
}
/*
* read_packet - get a PPP packet from the serial device.
*/
int
read_packet(buf)
u_char *buf;
{
int len;
if ((len = read(fd, buf, MTU + DLLHEADERLEN)) < 0) {
if (errno == EWOULDBLOCK) {
MAINDEBUG((LOG_DEBUG, "read(fd): EWOULDBLOCK"));
return -1;
}
syslog(LOG_ERR, "read(fd): %m");
die(1);
}
return len;
}
/*
* ppp_send_config - configure the transmit characteristics of
* the ppp interface.
*/
void
ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
int unit, mtu;
u_long asyncmap;
int pcomp, accomp;
{
u_int x;
struct ifreq ifr;
strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
ifr.ifr_mtu = mtu;
if (ioctl(s, SIOCSIFMTU, (caddr_t) &ifr) < 0) {
syslog(LOG_ERR, "ioctl(SIOCSIFMTU): %m");
quit();
}
if (ioctl(fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) {
syslog(LOG_ERR, "ioctl(PPPIOCSASYNCMAP): %m");
quit();
}
if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
quit();
}
x = pcomp? x | SC_COMP_PROT: x &~ SC_COMP_PROT;
x = accomp? x | SC_COMP_AC: x &~ SC_COMP_AC;
if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %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, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY)
syslog(LOG_WARNING, "ioctl(set extended ACCM): %m");
}
/*
* ppp_recv_config - configure the receive-side characteristics of
* the ppp interface.
*/
void
ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
int unit, mru;
u_long asyncmap;
int pcomp, accomp;
{
int x;
if (ioctl(fd, PPPIOCSMRU, (caddr_t) &mru) < 0) {
syslog(LOG_ERR, "ioctl(PPPIOCSMRU): %m");
quit();
}
if (ioctl(fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) {
syslog(LOG_ERR, "ioctl(PPPIOCSRASYNCMAP): %m");
quit();
}
if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
quit();
}
x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC;
if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
quit();
}
}
/*
* sifvjcomp - config tcp header compression
*/
int
sifvjcomp(u, vjcomp, cidcomp, maxcid)
int u, vjcomp, cidcomp, maxcid;
{
u_int x;
if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
return 0;
}
x = vjcomp ? x | SC_COMP_TCP: x &~ SC_COMP_TCP;
x = cidcomp? x & ~SC_NO_TCP_CCID: x | SC_NO_TCP_CCID;
if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
return 0;
}
if (ioctl(fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) {
syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
return 0;
}
return 1;
}
/*
* sifup - Config the interface up and enable IP packets to pass.
*/
int
sifup(u)
{
struct ifreq ifr;
u_int x;
strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
return 0;
}
ifr.ifr_flags |= IFF_UP;
if (ioctl(s, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
return 0;
}
if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
return 0;
}
x |= SC_ENABLE_IP;
if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
return 0;
}
return 1;
}
/*
* sifdown - Config the interface down and disable IP.
*/
int
sifdown(u)
{
struct ifreq ifr;
u_int x;
int rv;
rv = 1;
if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
rv = 0;
} else {
x &= ~SC_ENABLE_IP;
if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
rv = 0;
}
}
strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
rv = 0;
} else {
ifr.ifr_flags &= ~IFF_UP;
if (ioctl(s, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
rv = 0;
}
}
return rv;
}
/*
* SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
* if it exists.
*/
#define SET_SA_FAMILY(addr, family) \
BZERO((char *) &(addr), sizeof(addr)); \
addr.sa_family = (family);
/*
* sifaddr - Config the interface IP addresses and netmask.
*/
int
sifaddr(u, o, h, m)
{
int ret;
struct ifreq ifr;
ret = 1;
strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
SET_SA_FAMILY(ifr.ifr_addr, AF_INET);
((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = o;
if (ioctl(s, SIOCSIFADDR, (caddr_t) &ifr) < 0) {
syslog(LOG_ERR, "ioctl(SIOCSIFADDR): %m");
ret = 0;
}
((struct sockaddr_in *) &ifr.ifr_dstaddr)->sin_addr.s_addr = h;
if (ioctl(s, SIOCSIFDSTADDR, (caddr_t) &ifr) < 0) {
syslog(LOG_ERR, "ioctl(SIOCSIFDSTADDR): %m");
ret = 0;
}
if (m != 0) {
((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr.s_addr = m;
syslog(LOG_INFO, "Setting interface mask to %s\n", ip_ntoa(m));
if (ioctl(s, SIOCSIFNETMASK, (caddr_t) &ifr) < 0) {
syslog(LOG_ERR, "ioctl(SIOCSIFNETMASK): %m");
ret = 0;
}
}
return ret;
}
/*
* cifaddr - Clear the interface IP addresses, and delete routes
* through the interface if possible.
*/
int
cifaddr(u, o, h)
{
struct rtentry rt;
SET_SA_FAMILY(rt.rt_dst, AF_INET);
((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr = h;
SET_SA_FAMILY(rt.rt_gateway, AF_INET);
((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = o;
rt.rt_flags = RTF_HOST;
if (ioctl(s, SIOCDELRT, (caddr_t) &rt) < 0) {
syslog(LOG_ERR, "ioctl(SIOCDELRT): %m");
return 0;
}
return 1;
}
/*
* sifdefaultroute - assign a default route through the address given.
*/
int
sifdefaultroute(u, g)
{
struct rtentry rt;
SET_SA_FAMILY(rt.rt_dst, AF_INET);
SET_SA_FAMILY(rt.rt_gateway, AF_INET);
((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = g;
rt.rt_flags = RTF_GATEWAY;
if (ioctl(s, SIOCADDRT, &rt) < 0) {
syslog(LOG_ERR, "default route ioctl(SIOCADDRT): %m");
return 0;
}
return 1;
}
/*
* cifdefaultroute - delete a default route through the address given.
*/
int
cifdefaultroute(u, g)
{
struct rtentry rt;
SET_SA_FAMILY(rt.rt_dst, AF_INET);
SET_SA_FAMILY(rt.rt_gateway, AF_INET);
((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = g;
rt.rt_flags = RTF_GATEWAY;
if (ioctl(s, SIOCDELRT, &rt) < 0)
syslog(LOG_WARNING, "default route ioctl(SIOCDELRT): %m");
}
/*
* sifproxyarp - Make a proxy ARP entry for the peer.
*/
int
sifproxyarp(unit, hisaddr)
int unit;
u_long hisaddr;
{
struct arpreq arpreq;
BZERO(&arpreq, sizeof(arpreq));
/*
* Get the hardware address of an interface on the same subnet
* as our local address.
*/
if (!get_ether_addr(hisaddr, &arpreq.arp_ha)) {
syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP");
return 0;
}
SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
arpreq.arp_flags = ATF_PERM | ATF_PUBL;
if (ioctl(s, SIOCSARP, (caddr_t)&arpreq) < 0) {
syslog(LOG_ERR, "ioctl(SIOCSARP): %m");
return 0;
}
return 1;
}
/*
* cifproxyarp - Delete the proxy ARP entry for the peer.
*/
int
cifproxyarp(unit, hisaddr)
int unit;
u_long hisaddr;
{
struct arpreq arpreq;
BZERO(&arpreq, sizeof(arpreq));
SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
if (ioctl(s, SIOCDARP, (caddr_t)&arpreq) < 0) {
syslog(LOG_WARNING, "ioctl(SIOCDARP): %m");
return 0;
}
return 1;
}
/*
* get_ether_addr - get the hardware address of an interface on the
* the same subnet as ipaddr.
*/
#define MAX_IFS 32
int
get_ether_addr(ipaddr, hwaddr)
u_long ipaddr;
struct sockaddr *hwaddr;
{
struct ifreq *ifr, *ifend, *ifp;
u_long ina, mask;
struct sockaddr_dl *dla;
struct ifreq ifreq;
struct ifconf ifc;
struct ifreq ifs[MAX_IFS];
ifc.ifc_len = sizeof(ifs);
ifc.ifc_req = ifs;
if (ioctl(s, SIOCGIFCONF, &ifc) < 0) {
syslog(LOG_ERR, "ioctl(SIOCGIFCONF): %m");
return 0;
}
/*
* Scan through looking for an interface with an Internet
* address on the same subnet as `ipaddr'.
*/
ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
for (ifr = ifc.ifc_req; ifr < ifend; ) {
if (ifr->ifr_addr.sa_family == AF_INET) {
ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
/*
* Check that the interface is up, and not point-to-point
* or loopback.
*/
if (ioctl(s, SIOCGIFFLAGS, &ifreq) < 0)
continue;
if ((ifreq.ifr_flags &
(IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
!= (IFF_UP|IFF_BROADCAST))
continue;
/*
* Get its netmask and check that it's on the right subnet.
*/
if (ioctl(s, SIOCGIFNETMASK, &ifreq) < 0)
continue;
mask = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
if ((ipaddr & mask) != (ina & mask))
continue;
break;
}
ifr = (struct ifreq *) ((char *)&ifr->ifr_addr + sizeof(struct sockaddr)
);
}
if (ifr >= ifend)
return 0;
syslog(LOG_DEBUG, "found interface %s for proxy arp", ifr->ifr_name);
/*
* Now scan through again looking for a link-level address
* for this interface.
*/
ifp = ifr;
for (ifr = ifc.ifc_req; ifr < ifend; ) {
if (strcmp(ifp->ifr_name, ifr->ifr_name) == 0
&& ifr->ifr_addr.sa_family == AF_DLI) {
/* && ifr->ifr_addr.sa_family == AF_LINK) { Per! Kolla !!! ROHACK */
/*
* Found the link-level address - copy it out
*/
dla = (struct sockaddr_dl *)&ifr->ifr_addr;
hwaddr->sa_family = AF_UNSPEC;
BCOPY(dla, hwaddr->sa_data, sizeof(hwaddr->sa_data));
return 1;
}
ifr = (struct ifreq *) ((char *)&ifr->ifr_addr + sizeof(struct sockaddr)
);
}
return 0;
}
/*
* ppp_available - check whether the system has any ppp interfaces
* (in fact we check whether we can do an ioctl on ppp0).
*/
int
ppp_available()
{
int s, ok;
struct ifreq ifr;
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
return 1; /* can't tell - maybe we're not root */
strncpy(ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
close(s);
return ok;
}
/*
Seems like strdup() is not part of string package in Ultrix.
If I understood the man-page on the sun this should work.
Robert Olsson
*/
char *strdup( in ) char *in;
{
char* dup;
if(! (dup = (char *) malloc( strlen( in ) +1 ))) return NULL;
(void) strcpy( dup, in );
return dup;
}
/*
* This logwtmp() implementation is subject to the following copyright:
*
* Copyright (c) 1988 The Regents of the University of California.
* 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 the University of California, Berkeley. 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.
*/
#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);
}

View File

@ -18,7 +18,7 @@
*/
#ifndef lint
static char rcsid[] = "$Id: upap.c,v 1.2 1994/04/11 07:13:44 paulus Exp $";
static char rcsid[] = "$Id: upap.c,v 1.6 1995/06/12 12:02:24 paulus Exp $";
#endif
/*
@ -26,24 +26,25 @@ static char rcsid[] = "$Id: upap.c,v 1.2 1994/04/11 07:13:44 paulus Exp $";
*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <syslog.h>
#include "ppp.h"
#include "pppd.h"
#include "upap.h"
upap_state upap[NPPP]; /* UPAP state; one for each unit */
upap_state upap[NUM_PPP]; /* UPAP state; one for each unit */
static void upap_timeout __ARGS((caddr_t));
static void upap_rauthreq __ARGS((upap_state *, u_char *, int, int));
static void upap_rauthack __ARGS((upap_state *, u_char *, int, int));
static void upap_rauthnak __ARGS((upap_state *, u_char *, int, int));
static void upap_sauthreq __ARGS((upap_state *));
static void upap_sresp __ARGS((upap_state *, int, int, char *, int));
static void upap_timeout __P((caddr_t));
static void upap_reqtimeout __P((caddr_t));
static void upap_rauthreq __P((upap_state *, u_char *, int, int));
static void upap_rauthack __P((upap_state *, u_char *, int, int));
static void upap_rauthnak __P((upap_state *, u_char *, int, int));
static void upap_sauthreq __P((upap_state *));
static void upap_sresp __P((upap_state *, int, int, char *, int));
/*
@ -65,6 +66,7 @@ upap_init(unit)
u->us_id = 0;
u->us_timeouttime = UPAP_DEFTIMEOUT;
u->us_maxtransmits = 10;
u->us_reqtimeout = UPAP_DEFREQTIME;
}
@ -117,11 +119,13 @@ upap_authpeer(unit)
}
u->us_serverstate = UPAPSS_LISTEN;
if (u->us_reqtimeout > 0)
TIMEOUT(upap_reqtimeout, (caddr_t) u, u->us_reqtimeout);
}
/*
* upap_timeout - Timeout expired.
* upap_timeout - Retransmission timer for sending auth-reqs expired.
*/
static void
upap_timeout(arg)
@ -136,7 +140,7 @@ upap_timeout(arg)
/* give up in disgust */
syslog(LOG_ERR, "No response to PAP authenticate-requests");
u->us_clientstate = UPAPCS_BADAUTH;
auth_withpeer_fail(u->us_unit, UPAP);
auth_withpeer_fail(u->us_unit, PPP_PAP);
return;
}
@ -144,6 +148,23 @@ upap_timeout(arg)
}
/*
* upap_reqtimeout - Give up waiting for the peer to send an auth-req.
*/
static void
upap_reqtimeout(arg)
caddr_t arg;
{
upap_state *u = (upap_state *) arg;
if (u->us_serverstate != UPAPSS_LISTEN)
return; /* huh?? */
auth_peer_fail(u->us_unit, PPP_PAP);
u->us_serverstate = UPAPSS_BADAUTH;
}
/*
* upap_lowerup - The lower layer is up.
*
@ -163,8 +184,11 @@ upap_lowerup(unit)
if (u->us_serverstate == UPAPSS_INITIAL)
u->us_serverstate = UPAPSS_CLOSED;
else if (u->us_serverstate == UPAPSS_PENDING)
else if (u->us_serverstate == UPAPSS_PENDING) {
u->us_serverstate = UPAPSS_LISTEN;
if (u->us_reqtimeout > 0)
TIMEOUT(upap_reqtimeout, (caddr_t) u, u->us_reqtimeout);
}
}
@ -179,8 +203,10 @@ upap_lowerdown(unit)
{
upap_state *u = &upap[unit];
if (u->us_clientstate == UPAPCS_AUTHREQ) /* Timeout pending? */
if (u->us_clientstate == UPAPCS_AUTHREQ) /* Timeout pending? */
UNTIMEOUT(upap_timeout, (caddr_t) u); /* Cancel timeout */
if (u->us_serverstate == UPAPSS_LISTEN && u->us_reqtimeout > 0)
UNTIMEOUT(upap_reqtimeout, (caddr_t) u);
u->us_clientstate = UPAPCS_INITIAL;
u->us_serverstate = UPAPSS_INITIAL;
@ -200,11 +226,11 @@ upap_protrej(unit)
if (u->us_clientstate == UPAPCS_AUTHREQ) {
syslog(LOG_ERR, "PAP authentication failed due to protocol-reject");
auth_withpeer_fail(unit, UPAP);
auth_withpeer_fail(unit, PPP_PAP);
}
if (u->us_serverstate == UPAPSS_LISTEN) {
syslog(LOG_ERR, "PAP authentication of peer failed (protocol-reject)");
auth_peer_fail(unit, UPAP);
auth_peer_fail(unit, PPP_PAP);
}
upap_lowerdown(unit);
}
@ -334,11 +360,14 @@ upap_rauthreq(u, inp, id, len)
if (retcode == UPAP_AUTHACK) {
u->us_serverstate = UPAPSS_OPEN;
auth_peer_success(u->us_unit, UPAP);
auth_peer_success(u->us_unit, PPP_PAP);
} else {
u->us_serverstate = UPAPSS_BADAUTH;
auth_peer_fail(u->us_unit, UPAP);
auth_peer_fail(u->us_unit, PPP_PAP);
}
if (u->us_reqtimeout > 0)
UNTIMEOUT(upap_reqtimeout, (caddr_t) u);
}
@ -377,7 +406,7 @@ upap_rauthack(u, inp, id, len)
u->us_clientstate = UPAPCS_OPEN;
auth_withpeer_success(u->us_unit, UPAP);
auth_withpeer_success(u->us_unit, PPP_PAP);
}
@ -417,7 +446,7 @@ upap_rauthnak(u, inp, id, len)
u->us_clientstate = UPAPCS_BADAUTH;
syslog(LOG_ERR, "PAP authentication failed");
auth_withpeer_fail(u->us_unit, UPAP);
auth_withpeer_fail(u->us_unit, PPP_PAP);
}
@ -435,7 +464,7 @@ upap_sauthreq(u)
u->us_userlen + u->us_passwdlen;
outp = outpacket_buf;
MAKEHEADER(outp, UPAP);
MAKEHEADER(outp, PPP_PAP);
PUTCHAR(UPAP_AUTHREQ, outp);
PUTCHAR(++u->us_id, outp);
@ -446,7 +475,7 @@ upap_sauthreq(u)
PUTCHAR(u->us_passwdlen, outp);
BCOPY(u->us_passwd, outp, u->us_passwdlen);
output(u->us_unit, outpacket_buf, outlen + DLLHEADERLEN);
output(u->us_unit, outpacket_buf, outlen + PPP_HDRLEN);
UPAPDEBUG((LOG_INFO, "upap_sauth: Sent id %d.", u->us_id));
@ -471,14 +500,14 @@ upap_sresp(u, code, id, msg, msglen)
outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen;
outp = outpacket_buf;
MAKEHEADER(outp, UPAP);
MAKEHEADER(outp, PPP_PAP);
PUTCHAR(code, outp);
PUTCHAR(id, outp);
PUTSHORT(outlen, outp);
PUTCHAR(msglen, outp);
BCOPY(msg, outp, msglen);
output(u->us_unit, outpacket_buf, outlen + DLLHEADERLEN);
output(u->us_unit, outpacket_buf, outlen + PPP_HDRLEN);
UPAPDEBUG((LOG_INFO, "upap_sresp: Sent code %d, id %d.", code, id));
}
@ -494,7 +523,7 @@ int
upap_printpkt(p, plen, printer, arg)
u_char *p;
int plen;
void (*printer) __ARGS((void *, char *, ...));
void (*printer) __P((void *, char *, ...));
void *arg;
{
int code, id, len;

View File

@ -16,7 +16,7 @@
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* $Id: upap.h,v 1.2 1994/04/11 07:13:44 paulus Exp $
* $Id: upap.h,v 1.4 1995/06/12 12:02:25 paulus Exp $
*/
/*
@ -45,9 +45,10 @@ typedef struct upap_state {
int us_clientstate; /* Client state */
int us_serverstate; /* Server state */
u_char us_id; /* Current id */
int us_timeouttime; /* Timeout time in milliseconds */
int us_timeouttime; /* Timeout (seconds) for auth-req retrans. */
int us_transmits; /* Number of auth-reqs sent */
int us_maxtransmits; /* Maximum number of auth-reqs to send */
int us_reqtimeout; /* Time to wait for auth-req from peer */
} upap_state;
@ -75,17 +76,18 @@ typedef struct upap_state {
/*
* Timeouts.
*/
#define UPAP_DEFTIMEOUT 3 /* Timeout time in seconds */
#define UPAP_DEFTIMEOUT 3 /* Timeout (seconds) for retransmitting req */
#define UPAP_DEFREQTIME 30 /* Time to wait for auth-req from peer */
extern upap_state upap[];
void upap_init __ARGS((int));
void upap_authwithpeer __ARGS((int, char *, char *));
void upap_authpeer __ARGS((int));
void upap_lowerup __ARGS((int));
void upap_lowerdown __ARGS((int));
void upap_input __ARGS((int, u_char *, int));
void upap_protrej __ARGS((int));
int upap_printpkt __ARGS((u_char *, int,
void (*) __ARGS((void *, char *, ...)), void *));
void upap_init __P((int));
void upap_authwithpeer __P((int, char *, char *));
void upap_authpeer __P((int));
void upap_lowerup __P((int));
void upap_lowerdown __P((int));
void upap_input __P((int, u_char *, int));
void upap_protrej __P((int));
int upap_printpkt __P((u_char *, int,
void (*) __P((void *, char *, ...)), void *));