From d47a7a8e1a57bb7b4c4f588baa5a95bd44a26cec Mon Sep 17 00:00:00 2001 From: phk Date: Sun, 27 Dec 1998 21:30:44 +0000 Subject: [PATCH] Update sppp support to i4b level. This includes the new spppcontrol program to set PPP options like authentication with. --- sys/net/if_sppp.h | 13 +++- sys/net/if_spppsubr.c | 148 ++++++++++++++++++++++++++++++++---------- usr.sbin/Makefile | 3 +- 3 files changed, 128 insertions(+), 36 deletions(-) diff --git a/sys/net/if_sppp.h b/sys/net/if_sppp.h index 058e6676846f..67a63ae0472f 100644 --- a/sys/net/if_sppp.h +++ b/sys/net/if_sppp.h @@ -16,7 +16,7 @@ * * From: Version 2.0, Fri Oct 6 20:39:21 MSK 1995 * - * $Id: if_sppp.h,v 1.11 1998/12/11 21:42:57 phk Exp $ + * $Id: if_sppp.h,v 1.12 1998/12/20 19:06:22 phk Exp $ */ #ifndef _NET_IF_SPPP_H_ @@ -45,6 +45,7 @@ struct sipcp { u_int flags; #define IPCP_HISADDR_SEEN 1 /* have seen his address already */ #define IPCP_MYADDR_DYN 2 /* my address is dynamically assigned */ +#define IPCP_MYADDR_SEEN 4 /* have seen his address already */ }; #define AUTHNAMELEN 32 @@ -116,7 +117,15 @@ struct sppp { */ void (*pp_tls)(struct sppp *sp); void (*pp_tlf)(struct sppp *sp); - + /* + * These (optional) functions may be filled by the hardware + * driver if any notification of established connections + * (currently: IPCP up) is desired (pp_con) or any internal + * state change of the interface state machine should be + * signaled for monitoring purposes (pp_chg). + */ + void (*pp_con)(struct sppp *sp); + void (*pp_chg)(struct sppp *sp, int new_state); /* These two fields are for use by the lower layer */ void *pp_lowerp; int pp_loweri; diff --git a/sys/net/if_spppsubr.c b/sys/net/if_spppsubr.c index b9b4bfa2250d..4f3e17afdecb 100644 --- a/sys/net/if_spppsubr.c +++ b/sys/net/if_spppsubr.c @@ -17,7 +17,7 @@ * * From: Version 2.4, Thu Apr 30 17:17:21 MSD 1997 * - * $Id: if_spppsubr.c,v 1.50 1998/12/26 12:43:26 phk Exp $ + * $Id: if_spppsubr.c,v 1.51 1998/12/26 13:14:45 phk Exp $ */ #include @@ -39,6 +39,9 @@ #include #include #include +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include +#endif #include #include @@ -51,6 +54,7 @@ #include #include #include +#include #if defined(__FreeBSD__) && __FreeBSD__ >= 3 #include @@ -58,6 +62,7 @@ #if defined (__NetBSD__) || defined (__OpenBSD__) #include /* XXX for softnet */ #endif + #include #ifdef INET @@ -97,10 +102,13 @@ #if defined(__FreeBSD__) && __FreeBSD__ >= 3 # define UNTIMEOUT(fun, arg, handle) untimeout(fun, arg, handle) # define TIMEOUT(fun, arg1, arg2, handle) handle = timeout(fun, arg1, arg2) +# define IOCTL_CMD_T u_long #else # define UNTIMEOUT(fun, arg, handle) untimeout(fun, arg) # define TIMEOUT(fun, arg1, arg2, handle) timeout(fun, arg1, arg2) +# define IOCTL_CMD_T int #endif + #define MAXALIVECNT 3 /* max. alive packets */ /* @@ -291,13 +299,11 @@ static void sppp_cp_input(const struct cp *cp, struct sppp *sp, struct mbuf *m); static void sppp_cp_send(struct sppp *sp, u_short proto, u_char type, u_char ident, u_short len, void *data); -#ifdef notyet -static void sppp_cp_timeout(void *arg); -#endif +/* static void sppp_cp_timeout(void *arg); */ static void sppp_cp_change_state(const struct cp *cp, struct sppp *sp, int newstate); static void sppp_auth_send(const struct cp *cp, - struct sppp *sp, u_char type, u_char id, + struct sppp *sp, unsigned int type, unsigned int id, ...); static void sppp_up_event(const struct cp *cp, struct sppp *sp); @@ -643,15 +649,36 @@ sppp_output(struct ifnet *ifp, struct mbuf *m, ifq = &ifp->if_snd; #ifdef INET - /* - * Put low delay, telnet, rlogin and ftp control packets - * in front of the queue. - */ if (dst->sa_family == AF_INET) { /* XXX Check mbuf length here? */ struct ip *ip = mtod (m, struct ip*); struct tcphdr *tcp = (struct tcphdr*) ((long*)ip + ip->ip_hl); + /* + * When using dynamic local IP address assignment by using + * 0.0.0.0 as a local address, the first TCP session will + * not connect because the local TCP checksum is computed + * using 0.0.0.0 which will later become our real IP address + * so the TCP checksum computed at the remote end will + * become invalid. So we + * - don't let packets with src ip addr 0 thru + * - we flag TCP packets with src ip 0 as an error + */ + + if(ip->ip_src.s_addr == INADDR_ANY) /* -hm */ + { + m_freem(m); + splx(s); + if(ip->ip_p == IPPROTO_TCP) + return(EADDRNOTAVAIL); + else + return(0); + } + + /* + * Put low delay, telnet, rlogin and ftp control packets + * in front of the queue. + */ if (IF_QFULL (&sp->pp_fastq)) ; else if (ip->ip_tos & IPTOS_LOWDELAY) @@ -782,7 +809,9 @@ sppp_attach(struct ifnet *ifp) sp->pp_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST; sp->pp_if.if_type = IFT_PPP; sp->pp_if.if_output = sppp_output; +#if 0 sp->pp_flags = PP_KEEPALIVE; +#endif sp->pp_fastq.ifq_maxlen = 32; sp->pp_cpq.ifq_maxlen = 20; sp->pp_loopcnt = 0; @@ -904,7 +933,7 @@ sppp_pick(struct ifnet *ifp) * Process an ioctl request. Called on low priority level. */ int -sppp_ioctl(struct ifnet *ifp, u_long cmd, void *data) +sppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, void *data) { struct ifreq *ifr = (struct ifreq*) data; struct sppp *sp = (struct sppp*) ifp; @@ -2290,6 +2319,10 @@ sppp_lcp_tlu(struct sppp *sp) if (sp->lcp.protos & mask && ((cps[i])->flags & CP_LCP) == 0) (cps[i])->Up(sp); + /* notify low-level driver of state change */ + if (sp->pp_chg) + sp->pp_chg(sp, (int)sp->pp_phase); + if (sp->pp_phase == PHASE_NETWORK) /* if no NCP is starting, close down */ sppp_lcp_check_and_close(sp); @@ -2468,6 +2501,8 @@ sppp_ipcp_open(struct sppp *sp) STDDCL; u_long myaddr, hisaddr; + sp->ipcp.flags &= ~(IPCP_HISADDR_SEEN|IPCP_MYADDR_SEEN|IPCP_MYADDR_DYN); + sppp_get_ip_addrs(sp, &myaddr, &hisaddr, 0); /* * If we don't have his address, this probably means our @@ -2490,7 +2525,8 @@ sppp_ipcp_open(struct sppp *sp) */ sp->ipcp.flags |= IPCP_MYADDR_DYN; sp->ipcp.opts |= (1 << IPCP_OPT_ADDRESS); - } + } else + sp->ipcp.flags |= IPCP_MYADDR_SEEN; sppp_open_event(&ipcp, sp); } @@ -2524,6 +2560,7 @@ sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) struct ifnet *ifp = &sp->pp_if; int rlen, origlen, debug = ifp->if_flags & IFF_DEBUG; u_long hisaddr, desiredaddr; + int gotmyaddr = 0; len -= 4; origlen = len; @@ -2597,10 +2634,11 @@ sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) continue; #endif case IPCP_OPT_ADDRESS: + /* This is the address he wants in his end */ desiredaddr = p[2] << 24 | p[3] << 16 | p[4] << 8 | p[5]; if (desiredaddr == hisaddr || - hisaddr == 1 && desiredaddr != 0) { + (hisaddr == 1 && desiredaddr != 0)) { /* * Peer's address is same as our value, * or we have set it to 0.0.0.1 to @@ -2610,7 +2648,7 @@ sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) */ if (debug) addlog("%s [ack] ", - sppp_dotted_quad(desiredaddr)); + sppp_dotted_quad(hisaddr)); /* record that we've seen it already */ sp->ipcp.flags |= IPCP_HISADDR_SEEN; continue; @@ -2621,13 +2659,14 @@ sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) * address, or he send us another address not * matching our value. Either case, we gonna * conf-nak it with our value. + * XXX: we should "rej" if hisaddr == 0 */ if (debug) { if (desiredaddr == 0) addlog("[addr requested] "); else addlog("%s [not agreed] ", - sppp_dotted_quad(desiredaddr)); + sppp_dotted_quad(desiredaddr)); p[2] = hisaddr >> 24; p[3] = hisaddr >> 16; @@ -2652,7 +2691,7 @@ sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) * doesn't want to send us his address. Q: What should we do * about it? XXX A: implement the max-failure counter. */ - if (rlen == 0 && !(sp->ipcp.flags & IPCP_HISADDR_SEEN)) { + if (rlen == 0 && !(sp->ipcp.flags & IPCP_HISADDR_SEEN) && !gotmyaddr) { buf[0] = IPCP_OPT_ADDRESS; buf[1] = 6; buf[2] = hisaddr >> 24; @@ -2708,6 +2747,7 @@ sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) /* * Peer doesn't grok address option. This is * bad. XXX Should we better give up here? + * XXX We could try old "addresses" option... */ sp->ipcp.opts &= ~(1 << IPCP_OPT_ADDRESS); break; @@ -2768,11 +2808,14 @@ sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) * we accept his offer. Otherwise, we * ignore it and thus continue to negotiate * our already existing value. + * XXX: Bogus, if he said no once, he'll + * just say no again, might as well die. */ if (sp->ipcp.flags & IPCP_MYADDR_DYN) { sppp_set_ip_addr(sp, wantaddr); if (debug) addlog("[agree] "); + sp->ipcp.flags |= IPCP_MYADDR_SEEN; } } break; @@ -2794,6 +2837,9 @@ sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) static void sppp_ipcp_tlu(struct sppp *sp) { + /* we are up - notify isdn daemon */ + if (sp->pp_con) + sp->pp_con(sp); } static void @@ -3307,17 +3353,17 @@ sppp_chap_scr(struct sppp *sp) { u_long *ch, seed; u_char clen; -#if defined (__NetBSD__) || defined (__OpenBSD__) - struct timeval tv; -#endif /* Compute random challenge. */ ch = (u_long *)sp->myauth.challenge; #if defined(__FreeBSD__) && __FreeBSD__ >= 3 read_random(&seed, sizeof seed); #else + { + struct timeval tv; microtime(&tv); seed = tv.tv_sec ^ tv.tv_usec; + } #endif ch[0] = seed ^ random(); ch[1] = seed ^ random(); @@ -3654,10 +3700,14 @@ sppp_pap_scr(struct sppp *sp) * Varadic function, each of the elements for the ellipsis is of type * ``size_t mlen, const u_char *msg''. Processing will stop iff * mlen == 0. + * NOTE: never declare variadic functions with types subject to type + * promotion (i.e. u_char). This is asking for big trouble depending + * on the architecture you are on... */ static void -sppp_auth_send(const struct cp *cp, struct sppp *sp, u_char type, u_char id, +sppp_auth_send(const struct cp *cp, struct sppp *sp, + unsigned int type, unsigned int id, ...) { STDDCL; @@ -3666,7 +3716,7 @@ sppp_auth_send(const struct cp *cp, struct sppp *sp, u_char type, u_char id, struct mbuf *m; u_char *p; int len; - size_t mlen; + unsigned int mlen; const char *msg; va_list ap; @@ -3688,7 +3738,7 @@ sppp_auth_send(const struct cp *cp, struct sppp *sp, u_char type, u_char id, va_start(ap, id); len = 0; - while ((mlen = va_arg(ap, size_t)) != 0) { + while ((mlen = (unsigned int)va_arg(ap, size_t)) != 0) { msg = va_arg(ap, const char *); len += mlen; if (len > MHLEN - PPP_HEADER_LEN - LCP_HEADER_LEN) { @@ -3816,10 +3866,14 @@ sppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, u_long *srcmask) si = 0; #if defined(__FreeBSD__) && __FreeBSD__ >= 3 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) -#else +#elif defined(__NetBSD__) || defined (__OpenBSD__) for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next) +#else + for (ifa = ifp->if_addrlist; + ifa; + ifa = ifa->ifa_next) #endif if (ifa->ifa_addr->sa_family == AF_INET) { si = (struct sockaddr_in *)ifa->ifa_addr; @@ -3849,7 +3903,7 @@ sppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, u_long *srcmask) static void sppp_set_ip_addr(struct sppp *sp, u_long src) { - struct ifnet *ifp = &sp->pp_if; + STDDCL; struct ifaddr *ifa; struct sockaddr_in *si; @@ -3857,14 +3911,17 @@ sppp_set_ip_addr(struct sppp *sp, u_long src) * Pick the first AF_INET address from the list, * aliases don't make any sense on a p2p link anyway. */ - si = 0; #if defined(__FreeBSD__) && __FreeBSD__ >= 3 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) -#else +#elif defined(__NetBSD__) || defined (__OpenBSD__) for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next) +#else + for (ifa = ifp->if_addrlist; + ifa; + ifa = ifa->ifa_next) #endif { if (ifa->ifa_addr->sa_family == AF_INET) @@ -3876,8 +3933,40 @@ sppp_set_ip_addr(struct sppp *sp, u_long src) } if (ifa && si) + { + int error; +#if __NetBSD_Version__ >= 103080000 + struct sockaddr_in new_sin = *si; + + new_sin.sin_addr.s_addr = htonl(src); + error = in_ifinit(ifp, ifatoia(ifa), &new_sin, 1); + if(debug && error) + { + log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: in_ifinit " + " failed, error=%d\n", SPP_ARGS(ifp), error); + } +#else + /* delete old route */ + error = rtinit(ifa, (int)RTM_DELETE, RTF_HOST); + if(debug && error) + { + log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit DEL failed, error=%d\n", + SPP_ARGS(ifp), error); + } + + /* set new address */ si->sin_addr.s_addr = htonl(src); -} + + /* add new route */ + error = rtinit(ifa, (int)RTM_ADD, RTF_HOST); + if (debug && error) + { + log(LOG_DEBUG, SPP_FMT "sppp_set_ip_addr: rtinit ADD failed, error=%d", + SPP_ARGS(ifp), error); + } +#endif + } +} static int sppp_params(struct sppp *sp, u_long cmd, void *data) @@ -4183,10 +4272,3 @@ sppp_null(struct sppp *unused) { /* do just nothing */ } -/* - * This file is large. Tell emacs to highlight it nevertheless. - * - * Local Variables: - * hilit-auto-highlight-maxout: 120000 - * End: - */ diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index 55d8e7db46bb..60a7a5f36f7e 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -1,5 +1,5 @@ # From: @(#)Makefile 5.20 (Berkeley) 6/12/93 -# $Id: Makefile,v 1.138 1998/12/13 14:56:19 n_hibma Exp $ +# $Id: Makefile,v 1.139 1998/12/27 16:43:15 phk Exp $ # XXX MISSING: mkproto SUBDIR= IPXrouted \ @@ -80,6 +80,7 @@ SUBDIR= IPXrouted \ sliplogin \ slstat \ spray \ + spppcontrol \ sysctl \ syslogd \ tcpdump \