diff options
author | brian <brian@FreeBSD.org> | 2002-03-30 12:30:09 +0000 |
---|---|---|
committer | brian <brian@FreeBSD.org> | 2002-03-30 12:30:09 +0000 |
commit | ee9763124d8cbeceba9f2194f3ea61c1f2c1d362 (patch) | |
tree | b285f7b912098d74c02bd2a8b542e1472a52003a | |
parent | ef538de24ea069ff6846f7363f8a329a92cf1aa1 (diff) | |
download | FreeBSD-src-ee9763124d8cbeceba9f2194f3ea61c1f2c1d362.zip FreeBSD-src-ee9763124d8cbeceba9f2194f3ea61c1f2c1d362.tar.gz |
Merge the NETGRAPH branch into HEAD. tty devices now use netgraph's line
discipline to do the async escaping, but no other benefits are available yet.
Change ``ifdef HAVE_DES'' to ``ifndef NODES'' for consistency.
Make the Makefile a little more sane WRT RELEASE_CRUNCH.
-rw-r--r-- | usr.sbin/ppp/Makefile | 33 | ||||
-rw-r--r-- | usr.sbin/ppp/async.c | 6 | ||||
-rw-r--r-- | usr.sbin/ppp/async.h | 2 | ||||
-rw-r--r-- | usr.sbin/ppp/atm.c | 1 | ||||
-rw-r--r-- | usr.sbin/ppp/bundle.c | 30 | ||||
-rw-r--r-- | usr.sbin/ppp/ccp.c | 10 | ||||
-rw-r--r-- | usr.sbin/ppp/ccp.h | 6 | ||||
-rw-r--r-- | usr.sbin/ppp/chap.c | 62 | ||||
-rw-r--r-- | usr.sbin/ppp/chap.h | 2 | ||||
-rw-r--r-- | usr.sbin/ppp/chat.c | 8 | ||||
-rw-r--r-- | usr.sbin/ppp/command.c | 8 | ||||
-rw-r--r-- | usr.sbin/ppp/datalink.c | 23 | ||||
-rw-r--r-- | usr.sbin/ppp/datalink.h | 3 | ||||
-rw-r--r-- | usr.sbin/ppp/defs.c | 28 | ||||
-rw-r--r-- | usr.sbin/ppp/defs.h | 5 | ||||
-rw-r--r-- | usr.sbin/ppp/ether.c | 33 | ||||
-rw-r--r-- | usr.sbin/ppp/exec.c | 1 | ||||
-rw-r--r-- | usr.sbin/ppp/i4b.c | 1 | ||||
-rw-r--r-- | usr.sbin/ppp/lcp.c | 18 | ||||
-rw-r--r-- | usr.sbin/ppp/lcp.h | 2 | ||||
-rw-r--r-- | usr.sbin/ppp/main.c | 4 | ||||
-rw-r--r-- | usr.sbin/ppp/mppe.c | 2 | ||||
-rw-r--r-- | usr.sbin/ppp/netgraph.c | 740 | ||||
-rw-r--r-- | usr.sbin/ppp/netgraph.h | 37 | ||||
-rw-r--r-- | usr.sbin/ppp/physical.c | 14 | ||||
-rw-r--r-- | usr.sbin/ppp/physical.h | 3 | ||||
-rw-r--r-- | usr.sbin/ppp/route.c | 2 | ||||
-rw-r--r-- | usr.sbin/ppp/tcp.c | 1 | ||||
-rw-r--r-- | usr.sbin/ppp/tty.c | 287 | ||||
-rw-r--r-- | usr.sbin/ppp/udp.c | 1 |
30 files changed, 1226 insertions, 147 deletions
diff --git a/usr.sbin/ppp/Makefile b/usr.sbin/ppp/Makefile index 55c605d..edd2d2c 100644 --- a/usr.sbin/ppp/Makefile +++ b/usr.sbin/ppp/Makefile @@ -8,6 +8,17 @@ SRCS= acf.c arp.c async.c auth.c bundle.c cbcp.c ccp.c chap.c chat.c \ mbuf.c mp.c ncp.c ncpaddr.c pap.c physical.c pred.c probe.c prompt.c \ proto.c route.c server.c sig.c slcompress.c sync.c systems.c tcp.c \ tcpmss.c throughput.c timer.c tty.c tun.c udp.c vjcomp.c +.if defined(RELEASE_CRUNCH) +CFLAGS+=-DRELEASE_CRUNCH +NOATM= true +NOI4B= true +NONAT= true +NOKLDLOAD= true +NORADIUS= true +NOSECURE= true +NOSUID= true +.endif + .if defined(NOSUID) || defined(PPP_NOSUID) BINMODE=554 .else @@ -25,9 +36,6 @@ DPADD= ${LIBCRYPT} ${LIBMD} ${LIBUTIL} ${LIBZ} .8.m4.8: m4 ${M4FLAGS} ${.IMPSRC} >${.TARGET} -.if defined(RELEASE_CRUNCH) -CFLAGS+=-DRELEASE_CRUNCH -.endif .if defined(PPP_CONFDIR) && !empty(PPP_CONFDIR) CFLAGS+=-DPPP_CONFDIR=\"${PPP_CONFDIR}\" @@ -44,14 +52,12 @@ CFLAGS+=-DNOINET6 .if defined(NOALIAS) || defined(NONAT) CFLAGS+=-DNONAT .else -.if !defined(RELEASE_CRUNCH) SRCS+= nat_cmd.c LDADD+= -lalias DPADD+= ${LIBALIAS} .endif -.endif -.if defined(NOATM) || defined(RELEASE_CRUNCH) +.if defined(NOATM) CFLAGS+=-DNOATM .else SRCS+= atm.c @@ -60,14 +66,13 @@ SRCS+= atm.c .if defined(NOSUID) || defined(PPP_NOSUID) CFLAGS+=-DNOSUID .else -.if !defined(RELEASE_CRUNCH) SRCS+= id.c .endif -.endif -.if exists(${.CURDIR}/../../secure) && !defined(NOCRYPT) && !defined(NOSECURE) && !defined(NO_OPENSSL) && !defined(RELEASE_CRUNCH) +.if !exists(${.CURDIR}/../../secure) || defined(NOCRYPT) || defined(NOSECURE) || defined(NO_OPENSSL) || defined(NODES) +CFLAGS+=-DNODES +.else DISTRIBUTION=crypto -CFLAGS+=-DHAVE_DES SRCS+= chap_ms.c mppe.c LDADD+= -lcrypto DPADD+= ${LIBCRYPTO} @@ -76,12 +81,10 @@ DPADD+= ${LIBCRYPTO} .if defined(NORADIUS) CFLAGS+=-DNORADIUS .else -.if !defined(RELEASE_CRUNCH) SRCS+= radius.c LDADD+= -lradius DPADD+= ${LIBRADIUS} .endif -.endif .if defined(NOI4B) || ${MACHINE_ARCH} != "i386" CFLAGS+=-DNOI4B @@ -95,10 +98,10 @@ CFLAGS+=-DNONETGRAPH SRCS+= ether.c LDADD+= -lnetgraph DPADD+= ${LIBNETGRAPH} +.if defined(EXPERIMENTAL_NETGRAPH) +CFLAGS+=-DEXPERIMENTAL_NETGRAPH +SRCS+= netgraph.c .endif - -.if defined(RELEASE_CRUNCH) -CFLAGS+=-DNONAT -DNORADIUS -DNOI4B -DNOSUID .endif .include <bsd.prog.mk> diff --git a/usr.sbin/ppp/async.c b/usr.sbin/ppp/async.c index 266c906..f28e2f6 100644 --- a/usr.sbin/ppp/async.c +++ b/usr.sbin/ppp/async.c @@ -69,10 +69,10 @@ async_Setup(struct async *async) } void -async_SetLinkParams(struct async *async, struct lcp *lcp) +async_SetLinkParams(struct async *async, u_int32_t mymap, u_int32_t hismap) { - async->my_accmap = lcp->want_accmap; - async->his_accmap = lcp->his_accmap | lcp->want_accmap; + async->my_accmap = mymap; + async->his_accmap = hismap | mymap; } /* diff --git a/usr.sbin/ppp/async.h b/usr.sbin/ppp/async.h index dd1eea3..309f597 100644 --- a/usr.sbin/ppp/async.h +++ b/usr.sbin/ppp/async.h @@ -48,6 +48,6 @@ struct bundle; extern void async_Init(struct async *); extern void async_Setup(struct async *); -extern void async_SetLinkParams(struct async *, struct lcp *); +extern void async_SetLinkParams(struct async *, u_int32_t, u_int32_t); extern struct layer asynclayer; diff --git a/usr.sbin/ppp/atm.c b/usr.sbin/ppp/atm.c index 6d6aba9..084418f 100644 --- a/usr.sbin/ppp/atm.c +++ b/usr.sbin/ppp/atm.c @@ -130,6 +130,7 @@ static const struct device baseatmdevice = { NULL, NULL, NULL, + NULL, atm_Free, atm_Recvfrom, atm_Sendto, diff --git a/usr.sbin/ppp/bundle.c b/usr.sbin/ppp/bundle.c index 026eb68..5280548 100644 --- a/usr.sbin/ppp/bundle.c +++ b/usr.sbin/ppp/bundle.c @@ -49,12 +49,6 @@ #include <string.h> #include <sys/uio.h> #include <sys/wait.h> -#if defined(__FreeBSD__) && !defined(NOKLDLOAD) -#ifdef NOSUID -#include <sys/linker.h> -#endif -#include <sys/module.h> -#endif #include <termios.h> #include <unistd.h> @@ -100,7 +94,7 @@ #include "iface.h" #include "server.h" #include "probe.h" -#ifdef HAVE_DES +#ifndef NODES #include "mppe.h" #endif @@ -135,7 +129,7 @@ bundle_NewPhase(struct bundle *bundle, u_int new) switch (new) { case PHASE_DEAD: bundle->phase = new; -#ifdef HAVE_DES +#ifndef NODES MPPE_MasterKeyValid = 0; #endif log_DisplayPrompts(); @@ -625,11 +619,18 @@ bundle_DescriptorWrite(struct fdescriptor *d, struct bundle *bundle, /* This is not actually necessary as struct mpserver doesn't Write() */ if (descriptor_IsSet(&bundle->ncp.mp.server.desc, fdset)) - descriptor_Write(&bundle->ncp.mp.server.desc, bundle, fdset); + if (descriptor_Write(&bundle->ncp.mp.server.desc, bundle, fdset) == 1) + result++; for (dl = bundle->links; dl; dl = dl->next) if (descriptor_IsSet(&dl->desc, fdset)) - result += descriptor_Write(&dl->desc, bundle, fdset); + switch (descriptor_Write(&dl->desc, bundle, fdset)) { + case -1: + datalink_ComeDown(dl, CLOSE_NORMAL); + break; + case 1: + result++; + } return result; } @@ -705,13 +706,8 @@ bundle_Create(const char *prefix, int type, int unit) * Attempt to load the tunnel interface KLD if it isn't loaded * already. */ - if (modfind("if_tun") == -1) { - if (ID0kldload("if_tun") != -1) { - bundle.unit--; - continue; - } - log_Printf(LogWARN, "kldload: if_tun: %s\n", strerror(errno)); - } + loadmodules(LOAD_VERBOSLY, "if_tun", NULL); + continue; } #endif if (errno != ENOENT || ++enoentcount > 2) { diff --git a/usr.sbin/ppp/ccp.c b/usr.sbin/ppp/ccp.c index c7cea94..8465c5d 100644 --- a/usr.sbin/ppp/ccp.c +++ b/usr.sbin/ppp/ccp.c @@ -70,7 +70,7 @@ #ifndef NORADIUS #include "radius.h" #endif -#ifdef HAVE_DES +#ifndef NODES #include "mppe.h" #endif #include "ipv6cp.h" @@ -148,7 +148,7 @@ static const struct ccp_algorithm * const algorithm[] = { &DeflateAlgorithm, &Pred1Algorithm, &PppdDeflateAlgorithm -#ifdef HAVE_DES +#ifndef NODES , &MPPEAlgorithm #endif }; @@ -197,7 +197,7 @@ ccp_ReportStatus(struct cmdargs const *arg) prompt_Printf(arg->prompt, " deflate windows: "); prompt_Printf(arg->prompt, "incoming = %d, ", ccp->cfg.deflate.in.winsize); prompt_Printf(arg->prompt, "outgoing = %d\n", ccp->cfg.deflate.out.winsize); -#ifdef HAVE_DES +#ifndef NODES prompt_Printf(arg->prompt, " MPPE: "); if (ccp->cfg.mppe.keybits) prompt_Printf(arg->prompt, "%d bits, ", ccp->cfg.mppe.keybits); @@ -224,7 +224,7 @@ ccp_ReportStatus(struct cmdargs const *arg) command_ShowNegval(ccp->cfg.neg[CCP_NEG_PRED1])); prompt_Printf(arg->prompt, " DEFLATE24: %s\n", command_ShowNegval(ccp->cfg.neg[CCP_NEG_DEFLATE24])); -#ifdef HAVE_DES +#ifndef NODES prompt_Printf(arg->prompt, " MPPE: %s\n", command_ShowNegval(ccp->cfg.neg[CCP_NEG_MPPE])); #endif @@ -257,7 +257,7 @@ ccp_Init(struct ccp *ccp, struct bundle *bundle, struct link *l, ccp->cfg.neg[CCP_NEG_DEFLATE] = NEG_ENABLED|NEG_ACCEPTED; ccp->cfg.neg[CCP_NEG_PRED1] = NEG_ENABLED|NEG_ACCEPTED; ccp->cfg.neg[CCP_NEG_DEFLATE24] = 0; -#ifdef HAVE_DES +#ifndef NODES ccp->cfg.mppe.keybits = 0; ccp->cfg.mppe.state = MPPE_ANYSTATE; ccp->cfg.mppe.required = 0; diff --git a/usr.sbin/ppp/ccp.h b/usr.sbin/ppp/ccp.h index bb4f08b..d768e75 100644 --- a/usr.sbin/ppp/ccp.h +++ b/usr.sbin/ppp/ccp.h @@ -47,14 +47,14 @@ #define CCP_NEG_DEFLATE 0 #define CCP_NEG_PRED1 1 #define CCP_NEG_DEFLATE24 2 -#ifdef HAVE_DES +#ifndef NODES #define CCP_NEG_MPPE 3 #define CCP_NEG_TOTAL 4 #else #define CCP_NEG_TOTAL 3 #endif -#ifdef HAVE_DES +#ifndef NODES enum mppe_negstate { MPPE_ANYSTATE, MPPE_STATELESS, @@ -71,7 +71,7 @@ struct ccp_config { int winsize; } in, out; } deflate; -#ifdef HAVE_DES +#ifndef NODES struct { int keybits; enum mppe_negstate state; diff --git a/usr.sbin/ppp/chap.c b/usr.sbin/ppp/chap.c index c76b61f..ac6a6af 100644 --- a/usr.sbin/ppp/chap.c +++ b/usr.sbin/ppp/chap.c @@ -37,7 +37,7 @@ #include <errno.h> #include <fcntl.h> -#ifdef HAVE_DES +#ifndef NODES #include <md4.h> #endif #include <md5.h> @@ -85,7 +85,7 @@ #include "cbcp.h" #include "command.h" #include "datalink.h" -#ifdef HAVE_DES +#ifndef NODES #include "chap_ms.h" #include "mppe.h" #endif @@ -123,7 +123,7 @@ ChapOutput(struct physical *physical, u_int code, u_int id, static char * chap_BuildAnswer(char *name, char *key, u_char id, char *challenge, u_char type -#ifdef HAVE_DES +#ifndef NODES , char *peerchallenge, char *authresponse, int lanman #endif ) @@ -134,7 +134,7 @@ chap_BuildAnswer(char *name, char *key, u_char id, char *challenge, u_char type nlen = strlen(name); klen = strlen(key); -#ifdef HAVE_DES +#ifndef NODES if (type == 0x80) { char expkey[AUTHLEN << 2]; MD4_CTX MD4context; @@ -358,14 +358,14 @@ chap_Cleanup(struct chap *chap, int sig) log_Printf(LogERROR, "Chap: Child exited %d\n", WEXITSTATUS(status)); } *chap->challenge.local = *chap->challenge.peer = '\0'; -#ifdef HAVE_DES +#ifndef NODES chap->peertries = 0; #endif } static void chap_Respond(struct chap *chap, char *name, char *key, u_char type -#ifdef HAVE_DES +#ifndef NODES , int lm #endif ) @@ -373,7 +373,7 @@ chap_Respond(struct chap *chap, char *name, char *key, u_char type u_char *ans; ans = chap_BuildAnswer(name, key, chap->auth.id, chap->challenge.peer, type -#ifdef HAVE_DES +#ifndef NODES , chap->challenge.local, chap->authresponse, lm #endif ); @@ -381,7 +381,7 @@ chap_Respond(struct chap *chap, char *name, char *key, u_char type if (ans) { ChapOutput(chap->auth.physical, CHAP_RESPONSE, chap->auth.id, ans, *ans + 1 + strlen(name), name); -#ifdef HAVE_DES +#ifndef NODES chap->NTRespSent = !lm; MPPE_IsServer = 0; /* XXX Global ! */ #endif @@ -447,7 +447,7 @@ chap_Read(struct fdescriptor *d, struct bundle *bundle, const fd_set *fdset) chap_Cleanup(chap, SIGTERM); } } else { -#ifdef HAVE_DES +#ifndef NODES int lanman = chap->auth.physical->link.lcp.his_authtype == 0x80 && ((chap->NTRespSent && IsAccepted(chap->auth.physical->link.lcp.cfg.chap80lm)) || @@ -462,7 +462,7 @@ chap_Read(struct fdescriptor *d, struct bundle *bundle, const fd_set *fdset) key += strspn(key, " \t"); chap_Respond(chap, name, key, chap->auth.physical->link.lcp.his_authtype -#ifdef HAVE_DES +#ifndef NODES , lanman #endif ); @@ -501,7 +501,7 @@ chap_ChallengeInit(struct authinfo *authp) } else #endif { -#ifdef HAVE_DES +#ifndef NODES if (authp->physical->link.lcp.want_authtype == 0x80) *cp++ = 8; /* MS does 8 byte callenges :-/ */ else if (authp->physical->link.lcp.want_authtype == 0x81) @@ -531,7 +531,7 @@ chap_Challenge(struct authinfo *authp) if (!*chap->challenge.local) chap_ChallengeInit(authp); -#ifdef HAVE_DES +#ifndef NODES if (authp->physical->link.lcp.want_authtype == 0x81) ChapOutput(authp->physical, CHAP_CHALLENGE, authp->id, chap->challenge.local, 1 + *chap->challenge.local, NULL); @@ -546,7 +546,7 @@ chap_Success(struct authinfo *authp) { const char *msg; datalink_GotAuthname(authp->physical->dl, authp->in.name); -#ifdef HAVE_DES +#ifndef NODES if (authp->physical->link.lcp.want_authtype == 0x81) { msg = auth2chap(authp)->authresponse; MPPE_MasterKeyValid = 1; /* XXX Global ! */ @@ -572,12 +572,12 @@ chap_Success(struct authinfo *authp) static void chap_Failure(struct authinfo *authp) { -#ifdef HAVE_DES +#ifndef NODES char buf[1024]; #endif const char *msg; -#ifdef HAVE_DES +#ifndef NODES if (authp->physical->link.lcp.want_authtype == 0x81) { char *ptr; int i; @@ -600,14 +600,14 @@ chap_Failure(struct authinfo *authp) static int chap_Cmp(u_char type, char *myans, int mylen, char *hisans, int hislen -#ifdef HAVE_DES +#ifndef NODES , int lm #endif ) { if (mylen != hislen) return 0; -#ifdef HAVE_DES +#ifndef NODES else if (type == 0x80) { int off = lm ? 0 : 24; @@ -621,7 +621,7 @@ chap_Cmp(u_char type, char *myans, int mylen, char *hisans, int hislen return 1; } -#ifdef HAVE_DES +#ifndef NODES static int chap_HaveAnotherGo(struct chap *chap) { @@ -648,7 +648,7 @@ chap_Init(struct chap *chap, struct physical *p) chap->child.fd = -1; auth_Init(&chap->auth, p, chap_Challenge, chap_Success, chap_Failure); *chap->challenge.local = *chap->challenge.peer = '\0'; -#ifdef HAVE_DES +#ifndef NODES chap->NTRespSent = 0; chap->peertries = 0; #endif @@ -668,7 +668,7 @@ chap_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) char *name, *key, *ans; int len, nlen; u_char alen; -#ifdef HAVE_DES +#ifndef NODES int lanman; #endif @@ -708,7 +708,7 @@ chap_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) } chap->auth.id = chap->auth.in.hdr.id; /* We respond with this id */ -#ifdef HAVE_DES +#ifndef NODES lanman = 0; #endif switch (chap->auth.in.hdr.code) { @@ -723,7 +723,7 @@ chap_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) *chap->challenge.peer = alen; bp = mbuf_Read(bp, chap->challenge.peer + 1, alen); bp = auth_ReadName(&chap->auth, bp, len); -#ifdef HAVE_DES +#ifndef NODES lanman = p->link.lcp.his_authtype == 0x80 && ((chap->NTRespSent && IsAccepted(p->link.lcp.cfg.chap80lm)) || !IsAccepted(p->link.lcp.cfg.chap80nt)); @@ -756,7 +756,7 @@ chap_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) } ans[alen+1] = '\0'; bp = auth_ReadName(&chap->auth, bp, len); -#ifdef HAVE_DES +#ifndef NODES lanman = p->link.lcp.want_authtype == 0x80 && alen == 49 && ans[alen] == 0; #endif @@ -782,7 +782,7 @@ chap_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) log_Printf(LogPHASE, "Chap Input: %s (%d bytes from %s%s)\n", chapcodes[chap->auth.in.hdr.code], alen, chap->auth.in.name, -#ifdef HAVE_DES +#ifndef NODES lanman && chap->auth.in.hdr.code == CHAP_RESPONSE ? " - lanman" : #endif @@ -790,7 +790,7 @@ chap_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) else log_Printf(LogPHASE, "Chap Input: %s (%d bytes%s)\n", chapcodes[chap->auth.in.hdr.code], alen, -#ifdef HAVE_DES +#ifndef NODES lanman && chap->auth.in.hdr.code == CHAP_RESPONSE ? " - lanman" : #endif @@ -817,7 +817,7 @@ chap_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) chap_Respond(chap, bundle->cfg.auth.name, bundle->cfg.auth.key + (*bundle->cfg.auth.key == '!' ? 1 : 0), p->link.lcp.his_authtype -#ifdef HAVE_DES +#ifndef NODES , lanman #endif ); @@ -838,7 +838,7 @@ chap_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) key = auth_GetSecret(bundle, name, nlen, p); if (key) { char *myans; -#ifdef HAVE_DES +#ifndef NODES if (p->link.lcp.want_authtype == 0x80 && lanman && !IsEnabled(p->link.lcp.cfg.chap80lm)) { log_Printf(LogPHASE, "Auth failure: LANMan not enabled\n"); @@ -858,7 +858,7 @@ chap_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) } else #endif { -#ifdef HAVE_DES +#ifndef NODES /* Get peer's challenge */ if (p->link.lcp.want_authtype == 0x81) { chap->challenge.peer[0] = CHAP81_CHALLENGE_LEN; @@ -869,7 +869,7 @@ chap_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) myans = chap_BuildAnswer(name, key, chap->auth.id, chap->challenge.local, p->link.lcp.want_authtype -#ifdef HAVE_DES +#ifndef NODES , chap->challenge.peer, chap->authresponse, lanman); MPPE_IsServer = 1; /* XXX Global ! */ @@ -881,7 +881,7 @@ chap_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) else { if (!chap_Cmp(p->link.lcp.want_authtype, myans + 1, *myans, ans + 1, alen -#ifdef HAVE_DES +#ifndef NODES , lanman #endif )) @@ -903,7 +903,7 @@ chap_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) if (p->link.lcp.auth_iwait == PROTO_CHAP) { p->link.lcp.auth_iwait = 0; if (p->link.lcp.auth_ineed == 0) { -#ifdef HAVE_DES +#ifndef NODES if (p->link.lcp.his_authtype == 0x81) { if (strncmp(ans, chap->authresponse, 42)) { datalink_AuthNotOk(p->dl); diff --git a/usr.sbin/ppp/chap.h b/usr.sbin/ppp/chap.h index f3ab946..33a5b99 100644 --- a/usr.sbin/ppp/chap.h +++ b/usr.sbin/ppp/chap.h @@ -51,7 +51,7 @@ struct chap { u_char local[CHAPCHALLENGELEN + AUTHLEN]; /* I invented this one */ u_char peer[CHAPCHALLENGELEN + AUTHLEN]; /* Peer gave us this one */ } challenge; -#ifdef HAVE_DES +#ifndef NODES unsigned NTRespSent : 1; /* Our last response */ int peertries; u_char authresponse[CHAPAUTHRESPONSELEN]; /* CHAP 81 response */ diff --git a/usr.sbin/ppp/chat.c b/usr.sbin/ppp/chat.c index a81ab0e..3bd3bae 100644 --- a/usr.sbin/ppp/chat.c +++ b/usr.sbin/ppp/chat.c @@ -516,10 +516,12 @@ chat_Write(struct fdescriptor *d, struct bundle *bundle, const fd_set *fdset) } wrote = physical_Write(c->physical, c->argptr, c->arglen); - result = wrote ? 1 : 0; + result = wrote > 0 ? 1 : 0; if (wrote == -1) { - if (errno != EINTR) - log_Printf(LogERROR, "chat_Write: %s\n", strerror(errno)); + if (errno != EINTR) { + log_Printf(LogWARN, "chat_Write: %s\n", strerror(errno)); + result = -1; + } if (physical_IsSync(c->physical)) { c->argptr += 2; c->arglen -= 2; diff --git a/usr.sbin/ppp/command.c b/usr.sbin/ppp/command.c index 93e9d20..0931684 100644 --- a/usr.sbin/ppp/command.c +++ b/usr.sbin/ppp/command.c @@ -1673,7 +1673,7 @@ SetVariable(struct cmdargs const *arg) } break; -#ifdef HAVE_DES +#ifndef NODES case VAR_MPPE: if (arg->argc > arg->argn + 2) { res = -1; @@ -2210,7 +2210,7 @@ static struct cmdtab const SetCommands[] = { {"deflate", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, "deflate window sizes", "set deflate out-winsize in-winsize", (const void *) VAR_WINSIZE}, -#ifdef HAVE_DES +#ifndef NODES {"mppe", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX_OPT, "MPPE key size and state", "set mppe [40|56|128|* [stateful|stateless|*]]", (const void *) VAR_MPPE}, @@ -2674,7 +2674,7 @@ NegotiateSet(struct cmdargs const *arg) cx->physical->link.lcp.cfg.chap05 &= keep; cx->physical->link.lcp.cfg.chap05 |= add; break; -#ifdef HAVE_DES +#ifndef NODES case NEG_CHAP80: cx->physical->link.lcp.cfg.chap80nt &= keep; cx->physical->link.lcp.cfg.chap80nt |= add; @@ -2799,7 +2799,7 @@ static struct cmdtab const NegotiateCommands[] = { {"chap", "chap05", NegotiateSet, LOCAL_AUTH | LOCAL_CX, "Challenge Handshake Authentication Protocol", "accept|deny|disable|enable", (const void *)NEG_CHAP05}, -#ifdef HAVE_DES +#ifndef NODES {"mschap", "chap80nt", NegotiateSet, LOCAL_AUTH | LOCAL_CX, "Microsoft (NT) CHAP", "accept|deny|disable|enable", (const void *)NEG_CHAP80}, diff --git a/usr.sbin/ppp/datalink.c b/usr.sbin/ppp/datalink.c index 135160b..87cab95 100644 --- a/usr.sbin/ppp/datalink.c +++ b/usr.sbin/ppp/datalink.c @@ -489,7 +489,10 @@ datalink_Write(struct fdescriptor *d, struct bundle *bundle, case DATALINK_DIAL: case DATALINK_LOGOUT: case DATALINK_LOGIN: - result = descriptor_Write(&dl->chat.desc, bundle, fdset); + if ((result = descriptor_Write(&dl->chat.desc, bundle, fdset)) == -1) { + datalink_ComeDown(dl, CLOSE_NORMAL); + result = 0; + } break; case DATALINK_READY: @@ -498,16 +501,28 @@ datalink_Write(struct fdescriptor *d, struct bundle *bundle, case DATALINK_CBCP: case DATALINK_OPEN: if (descriptor_IsSet(&dl->chap.desc, fdset)) - result += descriptor_Write(&dl->chap.desc, bundle, fdset); + switch (descriptor_Write(&dl->chap.desc, bundle, fdset)) { + case -1: + datalink_ComeDown(dl, CLOSE_NORMAL); + break; + case 1: + result++; + } if (descriptor_IsSet(&dl->physical->desc, fdset)) - result += descriptor_Write(&dl->physical->desc, bundle, fdset); + switch (descriptor_Write(&dl->physical->desc, bundle, fdset)) { + case -1: + datalink_ComeDown(dl, CLOSE_NORMAL); + break; + case 1: + result++; + } break; } return result; } -static void +void datalink_ComeDown(struct datalink *dl, int how) { int stayonline; diff --git a/usr.sbin/ppp/datalink.h b/usr.sbin/ppp/datalink.h index dc07651..64b3c16 100644 --- a/usr.sbin/ppp/datalink.h +++ b/usr.sbin/ppp/datalink.h @@ -52,7 +52,7 @@ struct physical; struct bundle; struct datalink { - struct fdescriptor desc; /* We play either a physical or a chat */ + struct fdescriptor desc; /* We play either a physical or a chat */ int state; /* Our DATALINK_* state */ struct physical *physical; /* Our link */ @@ -154,3 +154,4 @@ extern int datalink_RemoveFromSet(struct datalink *, fd_set *, fd_set *, extern int datalink_SetMode(struct datalink *, int); extern int datalink_GetDialTimeout(struct datalink *); extern const char *datalink_ChoosePhoneNumber(struct datalink *); +extern void datalink_ComeDown(struct datalink *, int); diff --git a/usr.sbin/ppp/defs.c b/usr.sbin/ppp/defs.c index 9766802..b61b7de 100644 --- a/usr.sbin/ppp/defs.c +++ b/usr.sbin/ppp/defs.c @@ -27,7 +27,7 @@ */ -#include <sys/types.h> +#include <sys/param.h> #include <netdb.h> #include <netinet/in.h> #include <arpa/inet.h> @@ -35,15 +35,24 @@ #include <ctype.h> #include <errno.h> +#include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#if defined(__FreeBSD__) && !defined(NOKLDLOAD) +#include <sys/linker.h> +#include <sys/module.h> +#endif #include <termios.h> #if !defined(__FreeBSD__) || __FreeBSD__ < 3 #include <time.h> #endif #include <unistd.h> +#if defined(__FreeBSD__) && !defined(NOKLDLOAD) +#include "id.h" +#include "log.h" +#endif #include "defs.h" #define issep(c) ((c) == '\t' || (c) == ' ') @@ -410,3 +419,20 @@ Concatinate(char *buf, size_t sz, int argc, const char *const *argv) break; } } + +void +loadmodules(int how, const char *module, ...) +{ +#if defined(__FreeBSD__) && !defined(NOKLDLOAD) + va_list ap; + + va_start(ap, module); + while (module != NULL) { + if (modfind(module) == -1 && ID0kldload(module) == -1 && + how == LOAD_VERBOSLY) + log_Printf(LogWARN, "%s: Cannot load module\n", module); + module = va_arg(ap, const char *); + } + va_end(ap); +#endif +} diff --git a/usr.sbin/ppp/defs.h b/usr.sbin/ppp/defs.h index 1a62195..31a4011 100644 --- a/usr.sbin/ppp/defs.h +++ b/usr.sbin/ppp/defs.h @@ -111,6 +111,10 @@ #define PARSE_REDUCE 1 #define PARSE_NOHASH 2 +/* flags passed to loadmodules */ +#define LOAD_QUIETLY 1 +#define LOAD_VERBOSLY 2 + #define ROUNDUP(x) ((x) ? (1 + (((x) - 1) | (sizeof(long) - 1))) : sizeof(long)) #if defined(__NetBSD__) || __FreeBSD__ < 3 @@ -135,3 +139,4 @@ extern void SetTitle(const char *); extern fd_set *mkfdset(void); extern void zerofdset(fd_set *); extern void Concatinate(char *, size_t, int, const char *const *); +extern void loadmodules(int, const char *, ...); diff --git a/usr.sbin/ppp/ether.c b/usr.sbin/ppp/ether.c index f8a3534..3f65f1c 100644 --- a/usr.sbin/ppp/ether.c +++ b/usr.sbin/ppp/ether.c @@ -49,10 +49,6 @@ #include <string.h> #include <sysexits.h> #include <sys/fcntl.h> -#if defined(__FreeBSD__) && !defined(NOKLDLOAD) -#include <sys/linker.h> -#include <sys/module.h> -#endif #include <sys/stat.h> #include <sys/uio.h> #include <termios.h> @@ -302,6 +298,7 @@ static const struct device baseetherdevice = { NULL, NULL, NULL, + NULL, ether_Free, ether_Read, ether_Write, @@ -432,29 +429,8 @@ ether_Create(struct physical *p) p->fd--; /* We own the device - change fd */ -#if defined(__FreeBSD__) && !defined(NOKLDLOAD) - if (modfind("netgraph") == -1 && ID0kldload("netgraph") == -1) { - log_Printf(LogWARN, "kldload: netgraph: %s\n", strerror(errno)); - return NULL; - } - - if (modfind("ng_ether") == -1 && ID0kldload("ng_ether") == -1) - /* - * Don't treat this as an error as older kernels have this stuff - * built in as part of the netgraph node itself. - */ - log_Printf(LogWARN, "kldload: ng_ether: %s\n", strerror(errno)); - - if (modfind("ng_pppoe") == -1 && ID0kldload("ng_pppoe") == -1) { - log_Printf(LogWARN, "kldload: ng_pppoe: %s\n", strerror(errno)); - return NULL; - } - - if (modfind("ng_socket") == -1 && ID0kldload("ng_socket") == -1) { - log_Printf(LogWARN, "kldload: ng_socket: %s\n", strerror(errno)); - return NULL; - } -#endif + loadmodules(LOAD_VERBOSLY, "netgraph", "ng_ether", "ng_pppoe", "ng_socket", + NULL); if ((dev = malloc(sizeof *dev)) == NULL) return NULL; @@ -498,6 +474,7 @@ ether_Create(struct physical *p) log_Printf(LogWARN, "Cannot create netgraph socket node: %s\n", strerror(errno)); free(dev); + p->fd = -2; return NULL; } @@ -565,7 +542,7 @@ ether_Create(struct physical *p) if (f == ninfo->hooks) { /* * Create a new ``PPPoE'' node connected to the ``ether'' node using - * the magic ``orphan'' and ``ethernet'' hooks + * the ``orphan'' and ``ethernet'' hooks */ snprintf(mkp.type, sizeof mkp.type, "%s", NG_PPPOE_NODE_TYPE); snprintf(mkp.ourhook, sizeof mkp.ourhook, "%s", NG_ETHER_HOOK_ORPHAN); diff --git a/usr.sbin/ppp/exec.c b/usr.sbin/ppp/exec.c index 2522653..98b1b74 100644 --- a/usr.sbin/ppp/exec.c +++ b/usr.sbin/ppp/exec.c @@ -81,6 +81,7 @@ static struct device execdevice = { NULL, NULL, NULL, + NULL, NULL }; diff --git a/usr.sbin/ppp/i4b.c b/usr.sbin/ppp/i4b.c index a191bb0..cf2032d 100644 --- a/usr.sbin/ppp/i4b.c +++ b/usr.sbin/ppp/i4b.c @@ -305,6 +305,7 @@ static struct device basei4bdevice = { i4b_Raw, i4b_Offline, i4b_Cooked, + NULL, i4b_StopTimer, i4b_Free, NULL, diff --git a/usr.sbin/ppp/lcp.c b/usr.sbin/ppp/lcp.c index 616bf2b..1fdfc50 100644 --- a/usr.sbin/ppp/lcp.c +++ b/usr.sbin/ppp/lcp.c @@ -210,7 +210,7 @@ lcp_ReportStatus(struct cmdargs const *arg) command_ShowNegval(lcp->cfg.acfcomp)); prompt_Printf(arg->prompt, " CHAP = %s\n", command_ShowNegval(lcp->cfg.chap05)); -#ifdef HAVE_DES +#ifndef NODES prompt_Printf(arg->prompt, " CHAP80 = %s\n", command_ShowNegval(lcp->cfg.chap80nt)); prompt_Printf(arg->prompt, " LANMan = %s\n", @@ -268,7 +268,7 @@ lcp_Init(struct lcp *lcp, struct bundle *bundle, struct link *l, lcp->cfg.acfcomp = NEG_ENABLED|NEG_ACCEPTED; lcp->cfg.chap05 = NEG_ACCEPTED; -#ifdef HAVE_DES +#ifndef NODES lcp->cfg.chap80nt = NEG_ACCEPTED; lcp->cfg.chap80lm = 0; lcp->cfg.chap81 = NEG_ACCEPTED; @@ -315,7 +315,7 @@ lcp_Setup(struct lcp *lcp, int openmode) if (IsEnabled(lcp->cfg.chap05)) { lcp->want_auth = PROTO_CHAP; lcp->want_authtype = 0x05; -#ifdef HAVE_DES +#ifndef NODES } else if (IsEnabled(lcp->cfg.chap80nt) || IsEnabled(lcp->cfg.chap80lm)) { lcp->want_auth = PROTO_CHAP; @@ -573,7 +573,7 @@ LcpLayerUp(struct fsm *fp) struct lcp *lcp = fsm2lcp(fp); log_Printf(LogLCP, "%s: LayerUp\n", fp->link->name); - async_SetLinkParams(&p->async, lcp); + physical_SetAsyncParams(p, lcp->want_accmap, lcp->his_accmap); lqr_Start(lcp); hdlc_StartTimer(&p->hdlc); fp->more.reqs = fp->more.naks = fp->more.rejs = lcp->cfg.fsm.maxreq * 3; @@ -795,7 +795,7 @@ LcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, *dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8); *dec->nakend++ = (unsigned char) PROTO_CHAP; *dec->nakend++ = 0x05; -#ifdef HAVE_DES +#ifndef NODES } else if (IsAccepted(lcp->cfg.chap80nt) || IsAccepted(lcp->cfg.chap80lm)) { *dec->nakend++ = *cp; @@ -820,7 +820,7 @@ LcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, goto reqreject; } if ((cp[4] == 0x05 && IsAccepted(lcp->cfg.chap05)) -#ifdef HAVE_DES +#ifndef NODES || (cp[4] == 0x80 && (IsAccepted(lcp->cfg.chap80nt) || (IsAccepted(lcp->cfg.chap80lm)))) || (cp[4] == 0x81 && IsAccepted(lcp->cfg.chap81)) @@ -848,7 +848,7 @@ LcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, *dec->nakend++ = (unsigned char) (PROTO_CHAP >> 8); *dec->nakend++ = (unsigned char) PROTO_CHAP; *dec->nakend++ = 0x05; -#ifdef HAVE_DES +#ifndef NODES } else if (IsAccepted(lcp->cfg.chap80nt) || IsAccepted(lcp->cfg.chap80lm)) { *dec->nakend++ = *cp; @@ -896,7 +896,7 @@ LcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, if (cp[4] == 0x05 && IsEnabled(lcp->cfg.chap05)) { lcp->want_auth = PROTO_CHAP; lcp->want_authtype = 0x05; -#ifdef HAVE_DES +#ifndef NODES } else if (cp[4] == 0x80 && (IsEnabled(lcp->cfg.chap80nt) || IsEnabled(lcp->cfg.chap80lm))) { lcp->want_auth = PROTO_CHAP; @@ -917,7 +917,7 @@ LcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, #endif log_Printf(LogLCP, "Peer will only send %s (not %s)\n", Auth2Nam(PROTO_CHAP, cp[4]), -#ifdef HAVE_DES +#ifndef NODES (cp[4] == 0x80 || cp[4] == 0x81) ? "configured" : #endif "supported"); diff --git a/usr.sbin/ppp/lcp.h b/usr.sbin/ppp/lcp.h index ee931ab..1073c6e 100644 --- a/usr.sbin/ppp/lcp.h +++ b/usr.sbin/ppp/lcp.h @@ -92,7 +92,7 @@ struct lcp { struct fsm_retry fsm; /* How often/frequently to resend requests */ unsigned acfcomp : 2; /* Address & Control Field Compression neg */ unsigned chap05 : 2; /* Challenge Handshake Authentication proto */ -#ifdef HAVE_DES +#ifndef NODES unsigned chap80nt : 2; /* Microsoft (NT) CHAP */ unsigned chap80lm : 2; /* Microsoft (LANMan) CHAP */ unsigned chap81 : 2; /* Microsoft CHAP v2 */ diff --git a/usr.sbin/ppp/main.c b/usr.sbin/ppp/main.c index 387cec7..6cf390c 100644 --- a/usr.sbin/ppp/main.c +++ b/usr.sbin/ppp/main.c @@ -653,9 +653,9 @@ DoLoop(struct bundle *bundle) } if (descriptor_IsSet(&bundle->desc, wfds)) - if (!descriptor_Write(&bundle->desc, bundle, wfds) && nothing_done) { + if (descriptor_Write(&bundle->desc, bundle, wfds) <= 0 && nothing_done) { /* - * This is disasterous. The OS has told us that something is + * This is disastrous. The OS has told us that something is * writable, and all our write()s have failed. Rather than * going back immediately to do our UpdateSet()s and select(), * we sleep for a bit to avoid gobbling up all cpu time. diff --git a/usr.sbin/ppp/mppe.c b/usr.sbin/ppp/mppe.c index 4b75cbf..7b7275b 100644 --- a/usr.sbin/ppp/mppe.c +++ b/usr.sbin/ppp/mppe.c @@ -28,8 +28,6 @@ #include <sys/types.h> -#include <arpa/inet.h> - #include <stdio.h> #include <stdlib.h> #include <string.h> diff --git a/usr.sbin/ppp/netgraph.c b/usr.sbin/ppp/netgraph.c new file mode 100644 index 0000000..748ff0e --- /dev/null +++ b/usr.sbin/ppp/netgraph.c @@ -0,0 +1,740 @@ +/*- + * Copyright (c) 2000 Brian Somers <brian@Awfulhak.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <netgraph.h> +#include <net/ethernet.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netgraph/ng_ether.h> +#include <netgraph/ng_message.h> +#include <netgraph/ng_socket.h> + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sysexits.h> +#include <sys/fcntl.h> +#include <sys/uio.h> +#include <termios.h> +#include <sys/time.h> +#include <unistd.h> + +#include "layer.h" +#include "defs.h" +#include "mbuf.h" +#include "log.h" +#include "timer.h" +#include "lqr.h" +#include "hdlc.h" +#include "throughput.h" +#include "fsm.h" +#include "lcp.h" +#include "ccp.h" +#include "link.h" +#include "async.h" +#include "descriptor.h" +#include "physical.h" +#include "main.h" +#include "mp.h" +#include "chat.h" +#include "auth.h" +#include "chap.h" +#include "cbcp.h" +#include "datalink.h" +#include "slcompress.h" +#include "iplist.h" +#include "ncpaddr.h" +#include "ipcp.h" +#include "ipv6cp.h" +#include "ncp.h" +#include "filter.h" +#ifndef NORADIUS +#include "radius.h" +#endif +#include "bundle.h" +#include "id.h" +#include "netgraph.h" + + +struct ngdevice { + struct device dev; /* What struct physical knows about */ + int cs; /* Control socket */ + char hook[NG_HOOKLEN + 1]; /* Our socket node hook */ +}; + +#define device2ng(d) ((d)->type == NG_DEVICE ? (struct ngdevice *)d : NULL) +#define NG_MSGBUFSZ 4096 +#define NETGRAPH_PREFIX "netgraph:" + +int +ng_DeviceSize(void) +{ + return sizeof(struct ngdevice); +} + +static int +ng_MessageOut(struct ngdevice *dev, struct physical *p, const char *data) +{ + char path[NG_PATHLEN + 1]; + int len, pos, dpos; + char *fmt; + + /* + * We expect a node path, one or more spaces, a command, one or more + * spaces and an ascii netgraph structure. + */ + data += strspn(data, " \t"); + len = strcspn(data, " \t"); + if (len >= sizeof path) { + log_Printf(LogWARN, "%s: %.*s: Node path too long\n", + dev->dev.name, len, data); + return 0; + } + memcpy(path, data, len); + path[len] = '\0'; + data += len; + + data += strspn(data, " \t"); + len = strcspn(data, " \t"); + for (pos = len; pos >= 0; pos--) + if (data[pos] == '%') + len++; + if ((fmt = alloca(len + 4)) == NULL) { + log_Printf(LogWARN, "%s: alloca(%d) failure... %s\n", + dev->dev.name, len + 4, strerror(errno)); + return 0; + } + + /* + * This is probably a waste of time, but we really don't want to end + * up stuffing unexpected % escapes into the kernel.... + */ + for (pos = dpos = 0; pos < len;) { + if (data[dpos] == '%') + fmt[pos++] = '%'; + fmt[pos++] = data[dpos++]; + } + strcpy(fmt + pos, " %s"); + data += dpos; + + data += strspn(data, " \t"); + if (NgSendAsciiMsg(dev->cs, path, fmt, data) < 0) { + log_Printf(LogDEBUG, "%s: NgSendAsciiMsg (to %s): \"%s\", \"%s\": %s\n", + dev->dev.name, path, fmt, data, strerror(errno)); + return 0; + } + + return 1; +} + +/* + * Get a netgraph message + */ +static ssize_t +ng_MessageIn(struct physical *p, char *buf, size_t sz) +{ + char msgbuf[sizeof(struct ng_mesg) * 2 + NG_MSGBUFSZ]; + struct ngdevice *dev = device2ng(p->handler); + struct ng_mesg *rep = (struct ng_mesg *)msgbuf; + char path[NG_PATHLEN + 1]; + int len; + +#ifdef BROKEN_SELECT + struct timeval t; + fd_set *r; + int ret; + + if (dev->cs < 0) + return 0; + + if ((r = mkfdset()) == NULL) { + log_Printf(LogERROR, "DoLoop: Cannot create fd_set\n"); + return -1; + } + zerofdset(r); + FD_SET(dev->cs, r); + t.tv_sec = t.tv_usec = 0; + ret = select(dev->cs + 1, r, NULL, NULL, &t); + free(r); + + if (ret <= 0) + return 0; +#endif + + if (NgRecvAsciiMsg(dev->cs, rep, sizeof msgbuf, path)) { + log_Printf(LogWARN, "%s: NgRecvAsciiMsg: %s\n", + dev->dev.name, strerror(errno)); + return -1; + } + + /* XXX: Should we check rep->header.version ? */ + + if (sz == 0) + log_Printf(LogWARN, "%s: Unexpected message: %s\n", dev->dev.name, + rep->header.cmdstr); + else { + log_Printf(LogDEBUG, "%s: Received message: %s\n", dev->dev.name, + rep->header.cmdstr); + len = strlen(rep->header.cmdstr); + if (sz > len) + sz = len; + memcpy(buf, rep->header.cmdstr, sz); + } + + return sz; +} + +static ssize_t +ng_Write(struct physical *p, const void *v, size_t n) +{ + struct ngdevice *dev = device2ng(p->handler); + + switch (p->dl->state) { + case DATALINK_DIAL: + case DATALINK_LOGIN: + return ng_MessageOut(dev, p, v) ? n : -1; + } + return NgSendData(p->fd, dev->hook, v, n) == -1 ? -1 : n; +} + +static ssize_t +ng_Read(struct physical *p, void *v, size_t n) +{ + char hook[NG_HOOKLEN + 1]; + +log_Printf(LogDEBUG, "ng_Read\n"); + switch (p->dl->state) { + case DATALINK_DIAL: + case DATALINK_LOGIN: + return ng_MessageIn(p, v, n); + } + + return NgRecvData(p->fd, v, n, hook); +} + +static int +ng_RemoveFromSet(struct physical *p, fd_set *r, fd_set *w, fd_set *e) +{ + struct ngdevice *dev = device2ng(p->handler); + int result; + + if (r && dev->cs >= 0 && FD_ISSET(dev->cs, r)) { + FD_CLR(dev->cs, r); + log_Printf(LogTIMER, "%s: fdunset(ctrl) %d\n", p->link.name, dev->cs); + result = 1; + } else + result = 0; + + /* Careful... physical_RemoveFromSet() called us ! */ + + p->handler->removefromset = NULL; + result += physical_RemoveFromSet(p, r, w, e); + p->handler->removefromset = ng_RemoveFromSet; + + return result; +} + +static void +ng_Free(struct physical *p) +{ + struct ngdevice *dev = device2ng(p->handler); + + physical_SetDescriptor(p); + if (dev->cs != -1) + close(dev->cs); + free(dev); +} + +static void +ng_device2iov(struct device *d, struct iovec *iov, int *niov, + int maxiov, int *auxfd, int *nauxfd) +{ + struct ngdevice *dev = device2ng(d); + int sz = physical_MaxDeviceSize(); + + iov[*niov].iov_base = realloc(d, sz); + if (iov[*niov].iov_base == NULL) { + log_Printf(LogALERT, "Failed to allocate memory: %d\n", sz); + AbortProgram(EX_OSERR); + } + iov[*niov].iov_len = sz; + (*niov)++; + + *auxfd = dev->cs; + (*nauxfd)++; +} + +static const struct device basengdevice = { + NG_DEVICE, + "netgraph", + 0, + { CD_REQUIRED, DEF_NGCDDELAY }, + NULL, + ng_RemoveFromSet, + NULL, + NULL, + NULL, + NULL, + NULL, + ng_Free, + ng_Read, + ng_Write, + ng_device2iov, + NULL, + NULL +}; + +struct device * +ng_iov2device(int type, struct physical *p, struct iovec *iov, int *niov, + int maxiov, int *auxfd, int *nauxfd) +{ + if (type == NG_DEVICE) { + struct ngdevice *dev = (struct ngdevice *)iov[(*niov)++].iov_base; + + dev = realloc(dev, sizeof *dev); /* Reduce to the correct size */ + if (dev == NULL) { + log_Printf(LogALERT, "Failed to allocate memory: %d\n", + (int)(sizeof *dev)); + AbortProgram(EX_OSERR); + } + + if (*nauxfd) { + dev->cs = *auxfd; + (*nauxfd)--; + } else + dev->cs = -1; + + /* Refresh function pointers etc */ + memcpy(&dev->dev, &basengdevice, sizeof dev->dev); + + /* XXX: Are netgraph always synchronous ? */ + physical_SetupStack(p, dev->dev.name, PHYSICAL_FORCE_SYNCNOACF); + return &dev->dev; + } + + return NULL; +} + +static int +ng_UpdateSet(struct fdescriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n) +{ + struct physical *p = descriptor2physical(d); + struct ngdevice *dev = device2ng(p->handler); + int result; + + switch (p->dl->state) { + case DATALINK_DIAL: + case DATALINK_LOGIN: + if (r) { + FD_SET(dev->cs, r); + log_Printf(LogTIMER, "%s(ctrl): fdset(r) %d\n", p->link.name, dev->cs); + result = 1; + } else + result = 0; + break; + + default: + result = physical_doUpdateSet(d, r, w, e, n, 0); + break; + } + + return result; +} + +static int +ng_IsSet(struct fdescriptor *d, const fd_set *fdset) +{ + struct physical *p = descriptor2physical(d); + struct ngdevice *dev = device2ng(p->handler); + int result; + + result = dev->cs >= 0 && FD_ISSET(dev->cs, fdset); + result += physical_IsSet(d, fdset); + + return result; +} + +static void +ng_DescriptorRead(struct fdescriptor *d, struct bundle *bundle, + const fd_set *fdset) +{ + struct physical *p = descriptor2physical(d); + struct ngdevice *dev = device2ng(p->handler); + + if (dev->cs >= 0 && FD_ISSET(dev->cs, fdset)) + ng_MessageIn(p, NULL, 0); + + if (physical_IsSet(d, fdset)) + physical_DescriptorRead(d, bundle, fdset); +} + +static struct device * +ng_Abandon(struct ngdevice *dev, struct physical *p) +{ + /* Abandon our node construction */ + close(dev->cs); + close(p->fd); + p->fd = -2; /* Nobody else need try.. */ + free(dev); + + return NULL; +} + + +/* + * Populate the ``word'' (of size ``sz'') named ``what'' from ``from'' + * ending with any character from ``sep''. Point ``endp'' at the next + * word. + */ + +#define GETSEGMENT(what, from, sep, endp) \ + getsegment(#what, (what), sizeof(what), from, sep, endp) + +static int +getsegment(const char *what, char *word, size_t sz, const char *from, + const char *sep, const char **endp) +{ + int len; + + if ((len = strcspn(from, sep)) == 0) { + log_Printf(LogWARN, "%s name should not be empty !\n", what); + return 0; + } + + if (len >= sz) { + log_Printf(LogWARN, "%s name too long, max %d !\n", what, sz - 1); + return 0; + } + + strncpy(word, from, len); + word[len] = '\0'; + + *endp = from + len; + *endp += strspn(*endp, sep); + + return 1; +} + +struct device * +ng_Create(struct physical *p) +{ + struct sockaddr_ng ngsock; + u_char rbuf[2048]; + struct sockaddr *sock = (struct sockaddr *)&ngsock; + const struct hooklist *hlist; + const struct nodeinfo *ninfo; + const struct linkinfo *nlink; + struct ngdevice *dev; + struct ng_mesg *resp; + struct ngm_mkpeer mkp; + struct ngm_connect ngc; + const char *devp, *endp; + char lasthook[NG_HOOKLEN + 1]; + char hook[NG_HOOKLEN + 1]; + char nodetype[NG_TYPELEN + NG_NODELEN + 2]; + char modname[NG_TYPELEN + 4]; + char path[NG_PATHLEN + 1]; + char *nodename; + int len, sz, done, f; + + dev = NULL; + if (p->fd < 0 && !strncasecmp(p->name.full, NETGRAPH_PREFIX, + sizeof NETGRAPH_PREFIX - 1)) { + p->fd--; /* We own the device - change fd */ + + if ((dev = malloc(sizeof *dev)) == NULL) + return NULL; + + loadmodules(LOAD_VERBOSLY, "netgraph", "ng_socket", NULL); + + /* Create a socket node */ + if (ID0NgMkSockNode(NULL, &dev->cs, &p->fd) == -1) { + log_Printf(LogWARN, "Cannot create netgraph socket node: %s\n", + strerror(errno)); + free(dev); + p->fd = -2; + return NULL; + } + + devp = p->name.full + sizeof NETGRAPH_PREFIX - 1; + *lasthook = *path = '\0'; + log_Printf(LogDEBUG, "%s: Opening netgraph device \"%s\"\n", + p->link.name, devp); + done = 0; + + while (*devp != '\0' && !done) { + if (*devp != '[') { + if (*lasthook == '\0') { + log_Printf(LogWARN, "%s: Netgraph devices must start with" + " [nodetype:nodename]\n", p->link.name); + return ng_Abandon(dev, p); + } + + /* Get the hook name of the new node */ + if (!GETSEGMENT(hook, devp, ".[", &endp)) + return ng_Abandon(dev, p); + log_Printf(LogDEBUG, "%s: Got hook \"%s\"\n", p->link.name, hook); + devp = endp; + if (*devp == '\0') { + log_Printf(LogWARN, "%s: Netgraph device must not end with a second" + " hook\n", p->link.name); + return ng_Abandon(dev, p); + } + if (devp[-1] != '[') { + log_Printf(LogWARN, "%s: Expected a [nodetype:nodename] at device" + " pos %d\n", p->link.name, devp - p->link.name - 1); + return ng_Abandon(dev, p); + } + } else { + /* Use lasthook as the hook name */ + strcpy(hook, lasthook); + devp++; + } + + /* We've got ``lasthook'' and ``hook'', get the node type */ + if (!GETSEGMENT(nodetype, devp, "]", &endp)) + return ng_Abandon(dev, p); + log_Printf(LogDEBUG, "%s: Got node \"%s\"\n", p->link.name, nodetype); + + if ((nodename = strchr(nodetype, ':')) != NULL) { + *nodename++ = '\0'; + if (*nodename == '\0' && *nodetype == '\0') { + log_Printf(LogWARN, "%s: Empty [nodetype:nodename] at device" + " pos %d\n", p->link.name, devp - p->link.name - 1); + return ng_Abandon(dev, p); + } + } + + /* Ignore optional colons after nodes */ + devp = *endp == ':' ? endp + 1 : endp; + if (*devp == '.') + devp++; + + if (*lasthook == '\0') { + /* This is the first node in the chain */ + if (nodename == NULL || *nodename == '\0') { + log_Printf(LogWARN, "%s: %s: No initial device nodename\n", + p->link.name, devp); + return ng_Abandon(dev, p); + } + + if (*nodetype != '\0') { + /* Attempt to load the module */ + snprintf(modname, sizeof modname, "ng_%s", nodetype); + log_Printf(LogDEBUG, "%s: Attempting to load %s.ko\n", + p->link.name, modname); + loadmodules(LOAD_QUIETLY, modname, NULL); + } + + snprintf(path, sizeof path, "%s:", nodename); + /* XXX: If we have a node type, ensure it's correct */ + } else { + /* + * Ask for a list of hooks attached to the previous node. If we + * find the one we're interested in, and if it's connected to a + * node of the right type using the correct hook, use that. + * If we find the hook connected to something else, fail. + * If we find no match, mkpeer the new node. + */ + if (*nodetype == '\0') { + log_Printf(LogWARN, "%s: Nodetype missing at device offset %d\n", + p->link.name, + devp - p->name.full + sizeof NETGRAPH_PREFIX - 1); + return ng_Abandon(dev, p); + } + + /* Get a list of node hooks */ + if (NgSendMsg(dev->cs, path, NGM_GENERIC_COOKIE, NGM_LISTHOOKS, + NULL, 0) < 0) { + log_Printf(LogWARN, "%s: %s Cannot send a LISTHOOOKS message: %s\n", + p->link.name, path, strerror(errno)); + return ng_Abandon(dev, p); + } + + /* Get our list back */ + resp = (struct ng_mesg *)rbuf; + if (NgRecvMsg(dev->cs, resp, sizeof rbuf, NULL) <= 0) { + log_Printf(LogWARN, "%s: Cannot get netgraph response: %s\n", + p->link.name, strerror(errno)); + return ng_Abandon(dev, p); + } + + hlist = (const struct hooklist *)resp->data; + ninfo = &hlist->nodeinfo; + + log_Printf(LogDEBUG, "List of netgraph node ``%s'' (id %x) hooks:\n", + path, ninfo->id); + + /* look for a hook already attached. */ + for (f = 0; f < ninfo->hooks; f++) { + nlink = &hlist->link[f]; + + log_Printf(LogDEBUG, " Found %s -> %s (type %s)\n", nlink->ourhook, + nlink->peerhook, nlink->nodeinfo.type); + + if (!strcmp(nlink->ourhook, lasthook)) { + if (strcmp(nlink->peerhook, hook) || + strcmp(nlink->nodeinfo.type, nodetype)) { + log_Printf(LogWARN, "%s: hook %s:%s is already in use\n", + p->link.name, nlink->ourhook, path); + return ng_Abandon(dev, p); + } + /* The node is already hooked up nicely.... reuse it */ + break; + } + } + + if (f == ninfo->hooks) { + /* Attempt to load the module */ + snprintf(modname, sizeof modname, "ng_%s", nodetype); + log_Printf(LogDEBUG, "%s: Attempting to load %s.ko\n", + p->link.name, modname); + loadmodules(LOAD_QUIETLY, modname, NULL); + + /* Create (mkpeer) the new node */ + + snprintf(mkp.type, sizeof mkp.type, "%s", nodetype); + snprintf(mkp.ourhook, sizeof mkp.ourhook, "%s", lasthook); + snprintf(mkp.peerhook, sizeof mkp.peerhook, "%s", hook); + + log_Printf(LogDEBUG, "%s: Doing MKPEER %s%s -> %s (type %s)\n", + p->link.name, path, mkp.ourhook, mkp.peerhook, nodetype); + + if (NgSendMsg(dev->cs, path, NGM_GENERIC_COOKIE, + NGM_MKPEER, &mkp, sizeof mkp) < 0) { + log_Printf(LogWARN, "%s Cannot create %s netgraph node: %s\n", + path, nodetype, strerror(errno)); + return ng_Abandon(dev, p); + } + } + len = strlen(path); + snprintf(path + len, sizeof path - len, "%s%s", + path[len - 1] == ':' ? "" : ".", lasthook); + } + + /* Get a list of node hooks */ + if (NgSendMsg(dev->cs, path, NGM_GENERIC_COOKIE, NGM_LISTHOOKS, + NULL, 0) < 0) { + log_Printf(LogWARN, "%s: %s Cannot send a LISTHOOOKS message: %s\n", + p->link.name, path, strerror(errno)); + return ng_Abandon(dev, p); + } + + /* Get our list back */ + resp = (struct ng_mesg *)rbuf; + if (NgRecvMsg(dev->cs, resp, sizeof rbuf, NULL) <= 0) { + log_Printf(LogWARN, "%s: Cannot get netgraph response: %s\n", + p->link.name, strerror(errno)); + return ng_Abandon(dev, p); + } + + hlist = (const struct hooklist *)resp->data; + ninfo = &hlist->nodeinfo; + + if (*lasthook != '\0' && nodename != NULL && *nodename != '\0' && + strcmp(ninfo->name, nodename) && + NgNameNode(dev->cs, path, "%s", nodename) < 0) { + log_Printf(LogWARN, "%s: %s: Cannot name netgraph node: %s\n", + p->link.name, path, strerror(errno)); + return ng_Abandon(dev, p); + } + + if (!GETSEGMENT(lasthook, devp, " \t.[", &endp)) + return ng_Abandon(dev, p); + log_Printf(LogDEBUG, "%s: Got hook \"%s\"\n", p->link.name, lasthook); + + len = strlen(lasthook); + done = strchr(" \t", devp[len]) ? 1 : 0; + devp = endp; + + if (*devp != '\0') { + if (devp[-1] == '[') + devp--; + } /* else should moan about devp[-1] being '[' ? */ + } + + snprintf(dev->hook, sizeof dev->hook, "%s", lasthook); + + /* Connect the node to our socket node */ + snprintf(ngc.path, sizeof ngc.path, "%s", path); + snprintf(ngc.ourhook, sizeof ngc.ourhook, "%s", dev->hook); + memcpy(ngc.peerhook, ngc.ourhook, sizeof ngc.peerhook); + + log_Printf(LogDEBUG, "Connecting netgraph socket .:%s -> %s.%s\n", + ngc.ourhook, ngc.path, ngc.peerhook); + if (NgSendMsg(dev->cs, ".:", NGM_GENERIC_COOKIE, + NGM_CONNECT, &ngc, sizeof ngc) < 0) { + log_Printf(LogWARN, "Cannot connect %s and socket netgraph " + "nodes: %s\n", path, strerror(errno)); + return ng_Abandon(dev, p); + } + + /* Hook things up so that we monitor dev->cs */ + p->desc.UpdateSet = ng_UpdateSet; + p->desc.IsSet = ng_IsSet; + p->desc.Read = ng_DescriptorRead; + + memcpy(&dev->dev, &basengdevice, sizeof dev->dev); + + } else { + /* See if we're a netgraph socket */ + + sz = sizeof ngsock; + if (getsockname(p->fd, sock, &sz) != -1 && sock->sa_family == AF_NETGRAPH) { + /* + * It's a netgraph node... We can't determine hook names etc, so we + * stay pretty impartial.... + */ + log_Printf(LogPHASE, "%s: Link is a netgraph node\n", p->link.name); + + if ((dev = malloc(sizeof *dev)) == NULL) { + log_Printf(LogWARN, "%s: Cannot allocate an ether device: %s\n", + p->link.name, strerror(errno)); + return NULL; + } + + memcpy(&dev->dev, &basengdevice, sizeof dev->dev); + dev->cs = -1; + *dev->hook = '\0'; + } + } + + if (dev) { + physical_SetupStack(p, dev->dev.name, PHYSICAL_FORCE_SYNCNOACF); + return &dev->dev; + } + + return NULL; +} diff --git a/usr.sbin/ppp/netgraph.h b/usr.sbin/ppp/netgraph.h new file mode 100644 index 0000000..ffa012a --- /dev/null +++ b/usr.sbin/ppp/netgraph.h @@ -0,0 +1,37 @@ +/*- + * Copyright (c) 2000 Brian Somers <brian@Awfulhak.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +struct physical; +struct device; + +#define DEF_NGCDDELAY 5 /* Default ``set cd'' value */ + +extern struct device *ng_Create(struct physical *); +extern struct device *ng_iov2device(int, struct physical *, struct iovec *, + int *, int, int *, int *); +extern int ng_DeviceSize(void); diff --git a/usr.sbin/ppp/physical.c b/usr.sbin/ppp/physical.c index 8ff27c2..9bce72e 100644 --- a/usr.sbin/ppp/physical.c +++ b/usr.sbin/ppp/physical.c @@ -100,6 +100,7 @@ #endif #ifndef NONETGRAPH #include "ether.h" +#include "netgraph.h" #endif #ifndef NOATM #include "atm.h" @@ -137,6 +138,9 @@ struct { * able to identify it as a more specific type of SOCK_DGRAM. */ { ether_Create, ether_iov2device, ether_DeviceSize }, +#ifdef EXPERIMENTAL_NETGRAPH + { ng_Create, ng_iov2device, ng_DeviceSize }, +#endif #endif #ifndef NOATM /* Ditto for ATM devices */ @@ -1100,3 +1104,13 @@ physical_AwaitCarrier(struct physical *p) return CARRIER_OK; } + + +void +physical_SetAsyncParams(struct physical *p, u_int32_t mymap, u_int32_t hismap) +{ + if (p->handler && p->handler->setasyncparams) + return (*p->handler->setasyncparams)(p, mymap, hismap); + + async_SetLinkParams(&p->async, mymap, hismap); +} diff --git a/usr.sbin/ppp/physical.h b/usr.sbin/ppp/physical.h index 988b730..eb7c0d5 100644 --- a/usr.sbin/ppp/physical.h +++ b/usr.sbin/ppp/physical.h @@ -36,6 +36,7 @@ struct cmdargs; #define ETHER_DEVICE 5 #define EXEC_DEVICE 6 #define ATM_DEVICE 7 +#define NG_DEVICE 8 /* Returns from awaitcarrier() */ #define CARRIER_PENDING 1 @@ -64,6 +65,7 @@ struct device { int (*raw)(struct physical *); void (*offline)(struct physical *); void (*cooked)(struct physical *); + void (*setasyncparams)(struct physical *, u_int32_t, u_int32_t); void (*stoptimer)(struct physical *); void (*destroy)(struct physical *); ssize_t (*read)(struct physical *, void *, size_t); @@ -166,3 +168,4 @@ extern void physical_StopDeviceTimer(struct physical *); extern int physical_MaxDeviceSize(void); extern int physical_AwaitCarrier(struct physical *); extern void physical_SetDescriptor(struct physical *); +extern void physical_SetAsyncParams(struct physical *, u_int32_t, u_int32_t); diff --git a/usr.sbin/ppp/route.c b/usr.sbin/ppp/route.c index 5f0f662..de88365 100644 --- a/usr.sbin/ppp/route.c +++ b/usr.sbin/ppp/route.c @@ -317,7 +317,7 @@ route_ParseHdr(struct rt_msghdr *rtm, struct sockaddr *sa[RTAX_MAX]) if (rtm->rtm_addrs & (1 << rtax)) { sa[rtax] = (struct sockaddr *)wp; wp += ROUNDUP(sa[rtax]->sa_len); - if (sa[rtax]->sa_family == 0) + if (sa[rtax]->sa_family == 0) sa[rtax] = NULL; /* ??? */ } else sa[rtax] = NULL; diff --git a/usr.sbin/ppp/tcp.c b/usr.sbin/ppp/tcp.c index 567072a..e7968c0 100644 --- a/usr.sbin/ppp/tcp.c +++ b/usr.sbin/ppp/tcp.c @@ -113,6 +113,7 @@ static struct device tcpdevice = { NULL, NULL, NULL, + NULL, NULL }; diff --git a/usr.sbin/ppp/tty.c b/usr.sbin/ppp/tty.c index 773525c..7703cc3 100644 --- a/usr.sbin/ppp/tty.c +++ b/usr.sbin/ppp/tty.c @@ -34,12 +34,18 @@ #include <errno.h> #include <fcntl.h> +#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sysexits.h> #include <sys/uio.h> #include <termios.h> #include <unistd.h> +#include <netgraph.h> +#include <netgraph/ng_async.h> +#include <netgraph/ng_message.h> +#include <netgraph/ng_ppp.h> +#include <netgraph/ng_tty.h> #include "layer.h" #include "defs.h" @@ -63,6 +69,7 @@ #include "cbcp.h" #include "datalink.h" #include "main.h" +#include "id.h" #include "tty.h" #if defined(__mac68k__) || defined(__macppc__) @@ -79,6 +86,15 @@ struct ttydevice { struct pppTimer Timer; /* CD checks */ int mbits; /* Current DCD status */ int carrier_seconds; /* seconds before CD is *required* */ +#ifndef NONETGRAPH + struct { + int speed; /* Pre-line-discipline speed */ + int fd; /* Pre-line-discipline fd */ + int disc; /* Old line-discipline */ + } real; + char hook[sizeof NG_ASYNC_HOOK_SYNC]; /* our ng_socket hook */ + int cs; /* A netgraph control socket (maybe) */ +#endif struct termios ios; /* To be able to reset from raw mode */ }; @@ -192,6 +208,216 @@ tty_AwaitCarrier(struct physical *p) return Online(dev) ? CARRIER_OK : CARRIER_LOST; } +#ifdef NONETGRAPH +#define tty_SetAsyncParams NULL +#define tty_Write NULL +#define tty_Read NULL +#else + +static int +isngtty(struct ttydevice *dev) +{ + return dev->real.fd != -1; +} + +static void +tty_SetAsyncParams(struct physical *p, u_int32_t mymap, u_int32_t hismap) +{ + struct ttydevice *dev = device2tty(p->handler); + char asyncpath[NG_PATHLEN + 1]; + struct ng_async_cfg cfg; + + if (isngtty(dev)) { + /* Configure the async converter node */ + + snprintf(asyncpath, sizeof asyncpath, ".:%s", dev->hook); + memset(&cfg, 0, sizeof cfg); + cfg.enabled = 1; + cfg.accm = mymap | hismap; + cfg.amru = MAX_MTU; + cfg.smru = MAX_MRU; + log_Printf(LogDEBUG, "Configure async node at %s\n", asyncpath); + if (NgSendMsg(dev->cs, asyncpath, NGM_ASYNC_COOKIE, + NGM_ASYNC_CMD_SET_CONFIG, &cfg, sizeof cfg) < 0) + log_Printf(LogWARN, "%s: Can't configure async node at %s\n", + p->link.name, asyncpath); + } else + /* No netgraph node, just config the async layer */ + async_SetLinkParams(&p->async, mymap, hismap); +} + +static int +LoadLineDiscipline(struct physical *p) +{ + struct ttydevice *dev = device2tty(p->handler); + u_char rbuf[sizeof(struct ng_mesg) + sizeof(struct nodeinfo)]; + struct ng_mesg *reply; + struct nodeinfo *info; + char ttypath[NG_NODELEN + 1]; + struct ngm_mkpeer ngm; + struct ngm_connect ngc; + int ldisc, cs, ds, hot, speed; + + reply = (struct ng_mesg *)rbuf; + info = (struct nodeinfo *)reply->data; + + loadmodules(LOAD_VERBOSLY, "netgraph", "ng_tty", "ng_async", "ng_socket", + NULL); + + /* Get the speed before loading the line discipline */ + speed = physical_GetSpeed(p); + + if (ioctl(p->fd, TIOCGETD, &dev->real.disc) < 0) { + log_Printf(LogDEBUG, "%s: Couldn't get tty line discipline\n", + p->link.name); + return 0; + } + ldisc = NETGRAPHDISC; + if (ID0ioctl(p->fd, TIOCSETD, &ldisc) < 0) { + log_Printf(LogDEBUG, "%s: Couldn't set NETGRAPHDISC line discipline\n", + p->link.name); + return 0; + } + + /* Get the name of the tty node */ + if (ioctl(p->fd, NGIOCGINFO, info) < 0) { + log_Printf(LogWARN, "%s: ioctl(NGIOCGINFO): %s\n", p->link.name, + strerror(errno)); + ID0ioctl(p->fd, TIOCSETD, &dev->real.disc); + return 0; + } + snprintf(ttypath, sizeof ttypath, "%s:", info->name); + + /* Create a socket node for our endpoint (and to send messages via) */ + if (ID0NgMkSockNode(NULL, &cs, &ds) == -1) { + log_Printf(LogWARN, "%s: NgMkSockNode: %s\n", p->link.name, + strerror(errno)); + ID0ioctl(p->fd, TIOCSETD, &dev->real.disc); + return 0; + } + + /* Set the ``hot char'' on the TTY node */ + hot = HDLC_SYN; + log_Printf(LogDEBUG, "%s: Set tty hotchar to 0x%02x\n", p->link.name, hot); + if (NgSendMsg(cs, ttypath, NGM_TTY_COOKIE, + NGM_TTY_SET_HOTCHAR, &hot, sizeof hot) < 0) { + log_Printf(LogWARN, "%s: Can't set hot char\n", p->link.name); + goto failed; + } + + /* Attach an async converter node */ + snprintf(ngm.type, sizeof ngm.type, "%s", NG_ASYNC_NODE_TYPE); + snprintf(ngm.ourhook, sizeof ngm.ourhook, "%s", NG_TTY_HOOK); + snprintf(ngm.peerhook, sizeof ngm.peerhook, "%s", NG_ASYNC_HOOK_ASYNC); + log_Printf(LogDEBUG, "%s: Send mkpeer async:%s to %s:%s\n", p->link.name, + ngm.peerhook, ttypath, ngm.ourhook); + if (NgSendMsg(cs, ttypath, NGM_GENERIC_COOKIE, + NGM_MKPEER, &ngm, sizeof ngm) < 0) { + log_Printf(LogWARN, "%s: Can't create %s node\n", p->link.name, + NG_ASYNC_NODE_TYPE); + goto failed; + } + + /* Connect the async node to our socket */ + snprintf(ngc.path, sizeof ngc.path, "%s%s", ttypath, NG_TTY_HOOK); + snprintf(ngc.peerhook, sizeof ngc.peerhook, "%s", NG_ASYNC_HOOK_SYNC); + memcpy(ngc.ourhook, ngc.peerhook, sizeof ngc.ourhook); + log_Printf(LogDEBUG, "%s: Send connect %s:%s to .:%s\n", p->link.name, + ngc.path, ngc.peerhook, ngc.ourhook); + if (NgSendMsg(cs, ".:", NGM_GENERIC_COOKIE, NGM_CONNECT, + &ngc, sizeof ngc) < 0) { + log_Printf(LogWARN, "%s: Can't connect .:%s -> %s.%s: %s\n", + p->link.name, ngc.ourhook, ngc.path, ngc.peerhook, + strerror(errno)); + goto failed; + } + + /* Get the async node id */ + if (NgSendMsg(cs, ngc.path, NGM_GENERIC_COOKIE, NGM_NODEINFO, NULL, 0) < 0) { + log_Printf(LogWARN, "%s: Can't request async node info at %s: %s\n", + p->link.name, ngc.path, strerror(errno)); + goto failed; + } + if (NgRecvMsg(cs, reply, sizeof rbuf, NULL) < 0) { + log_Printf(LogWARN, "%s: Can't obtain async node info at %s: %s\n", + p->link.name, ngc.path, strerror(errno)); + goto failed; + } + + /* All done, set up our device state */ + snprintf(dev->hook, sizeof dev->hook, "%s", ngc.ourhook); + dev->cs = cs; + dev->real.fd = p->fd; + p->fd = ds; + dev->real.speed = speed; + physical_SetSync(p); + + tty_SetAsyncParams(p, 0xffffffff, 0xffffffff); + physical_SetupStack(p, dev->dev.name, PHYSICAL_NOFORCE); + log_Printf(LogPHASE, "%s: Loaded netgraph tty line discipline\n", + p->link.name); + + return 1; + +failed: + ID0ioctl(p->fd, TIOCSETD, &dev->real.disc); + close(ds); + close(cs); + + return 0; +} + +static void +UnloadLineDiscipline(struct physical *p) +{ + struct ttydevice *dev = device2tty(p->handler); + + if (isngtty(dev)) { +log_Printf(LogPHASE, "back to speed %d\n", dev->real.speed); + if (!physical_SetSpeed(p, dev->real.speed)) + log_Printf(LogWARN, "Couldn't reset tty speed to %d\n", dev->real.speed); + dev->real.speed = 0; + close(p->fd); + p->fd = dev->real.fd; + dev->real.fd = -1; + close(dev->cs); + dev->cs = -1; + *dev->hook = '\0'; + if (ID0ioctl(p->fd, TIOCSETD, &dev->real.disc) == 0) { + physical_SetupStack(p, dev->dev.name, PHYSICAL_NOFORCE); + log_Printf(LogPHASE, "%s: Unloaded netgraph tty line discipline\n", + p->link.name); + } else + log_Printf(LogWARN, "%s: Failed to unload netgraph tty line discipline\n", + p->link.name); + } +} + +static ssize_t +tty_Write(struct physical *p, const void *v, size_t n) +{ + struct ttydevice *dev = device2tty(p->handler); + + if (isngtty(dev)) + return NgSendData(p->fd, dev->hook, v, n) == -1 ? -1 : n; + else + return write(p->fd, v, n); +} + +static ssize_t +tty_Read(struct physical *p, void *v, size_t n) +{ + struct ttydevice *dev = device2tty(p->handler); + char hook[sizeof NG_ASYNC_HOOK_SYNC]; + + if (isngtty(dev)) + return NgRecvData(p->fd, v, n, hook); + else + return read(p->fd, v, n); +} + +#endif /* NETGRAPH */ + static int tty_Raw(struct physical *p) { @@ -206,19 +432,24 @@ tty_Raw(struct physical *p) p->link.name, p->fd, dev->mbits); if (!physical_IsSync(p)) { - tcgetattr(p->fd, &ios); - cfmakeraw(&ios); - if (p->cfg.rts_cts) - ios.c_cflag |= CLOCAL | CCTS_OFLOW | CRTS_IFLOW; - else - ios.c_cflag |= CLOCAL; - - if (p->type != PHYS_DEDICATED) - ios.c_cflag |= HUPCL; - - if (tcsetattr(p->fd, TCSANOW, &ios) == -1) - log_Printf(LogWARN, "%s: tcsetattr: Failed configuring device\n", - p->link.name); +#ifndef NONETGRAPH + if (!LoadLineDiscipline(p)) +#endif + { + tcgetattr(p->fd, &ios); + cfmakeraw(&ios); + if (p->cfg.rts_cts) + ios.c_cflag |= CLOCAL | CCTS_OFLOW | CRTS_IFLOW; + else + ios.c_cflag |= CLOCAL; + + if (p->type != PHYS_DEDICATED) + ios.c_cflag |= HUPCL; + + if (tcsetattr(p->fd, TCSANOW, &ios) == -1) + log_Printf(LogWARN, "%s: tcsetattr: Failed configuring device\n", + p->link.name); + } } oldflag = fcntl(p->fd, F_GETFL, 0); @@ -262,6 +493,10 @@ tty_Cooked(struct physical *p) log_Printf(LogWARN, "%s: tcsetattr: Unable to restore device settings\n", p->link.name); +#ifndef NONETGRAPH + UnloadLineDiscipline(p); +#endif + if ((oldflag = fcntl(p->fd, F_GETFL, 0)) != -1) fcntl(p->fd, F_SETFL, oldflag & ~O_NONBLOCK); } @@ -324,6 +559,13 @@ tty_device2iov(struct device *d, struct iovec *iov, int *niov, iov[*niov].iov_len = sz; (*niov)++; +#ifndef NONETGRAPH + if (dev->cs >= 0) { + *auxfd = dev->cs; + (*nauxfd)++; + } +#endif + if (dev->Timer.state != TIMER_STOPPED) { timer_Stop(&dev->Timer); dev->Timer.state = TIMER_RUNNING; @@ -340,10 +582,11 @@ static struct device basettydevice = { tty_Raw, tty_Offline, tty_Cooked, + tty_SetAsyncParams, tty_StopTimer, tty_Free, - NULL, - NULL, + tty_Read, + tty_Write, tty_device2iov, tty_Speed, tty_OpenInfo @@ -363,6 +606,14 @@ tty_iov2device(int type, struct physical *p, struct iovec *iov, int *niov, AbortProgram(EX_OSERR); } +#ifndef NONETGRAPH + if (*nauxfd) { + dev->cs = *auxfd; + (*nauxfd)--; + } else + dev->cs = -1; +#endif + /* Refresh function pointers etc */ memcpy(&dev->dev, &basettydevice, sizeof dev->dev); @@ -408,6 +659,12 @@ tty_Create(struct physical *p) memcpy(&dev->dev, &basettydevice, sizeof dev->dev); memset(&dev->Timer, '\0', sizeof dev->Timer); dev->mbits = -1; +#ifndef NONETGRAPH + dev->real.speed = 0; + dev->real.fd = -1; + dev->real.disc = -1; + *dev->hook = '\0'; +#endif tcgetattr(p->fd, &ios); dev->ios = ios; diff --git a/usr.sbin/ppp/udp.c b/usr.sbin/ppp/udp.c index 7ffa708..e8f97bb 100644 --- a/usr.sbin/ppp/udp.c +++ b/usr.sbin/ppp/udp.c @@ -162,6 +162,7 @@ static const struct device baseudpdevice = { NULL, NULL, NULL, + NULL, udp_Free, udp_Recvfrom, udp_Sendto, |