[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Tried to compile pppd but no luck



 --- Nathan Hawkins <utsl@quic.net> wrote: 

> 
> > Is there something you can do to ask the FreeBSD developers to switch their
> > PPP to Samba's?
> 
> This shouldn't be necessary. All we have to do is get the patches merged 
> upstream, and then point out to FreeBSD developers that with the native ppp 
> in the base system, it makes sense to move pppd to the ports tree. 
>
I can prepare a port and submit it to the ports tree. The version of pppd
included in FreeBSD is so outdated it is clear it has to be updated to the
"samba" version or replaced with mpd. BTW, I doubt it is useful, but I am
including a patch with the FreeBSD changes to ppp-2.3.5. pppd has changed a lot
so don't expect the patch to apply, or even to be relevant.

> FWIW, I think I can probably get the userspace ppp to build. The only 
> problem with it now is that it needs libutil, which is mostly incompatible 
> with the glibc world, but I think I can probably fix ppp to not need it. 
> 

That would be nice!

cheers,

   Pedro.


________________________________________________________________________
Want to chat instantly with your online friends?  Get the FREE Yahoo!
Messenger http://uk.messenger.yahoo.com/
diff -ruN pppd/auth.c /usr/src/usr.sbin/pppd/auth.c
--- pppd/auth.c	Wed Mar 25 23:46:00 1998
+++ /usr/src/usr.sbin/pppd/auth.c	Mon Jul  7 16:59:27 2003
 #include <stdlib.h>
 #include <unistd.h>
 #include <syslog.h>
+#include <paths.h>
 #include <pwd.h>
 #include <string.h>
 #include <sys/types.h>
@@ -55,6 +56,8 @@
 #include <netdb.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#include <sys/time.h>
+#include <utmp.h>
 
 #ifdef USE_PAM
 #include <security/pam_appl.h>
@@ -102,6 +105,9 @@
 /* Set if we have successfully called plogin() */
 static int logged_in;
 
+/* Set if not wild or blank */
+static int non_wildclient;
+
 /* Set if we have run the /etc/ppp/auth-up script. */
 static int did_authup;
 
@@ -140,6 +146,7 @@
 static int  scan_authfile __P((FILE *, char *, char *, u_int32_t, char *,
 			       struct wordlist **, char *));
 static void free_wordlist __P((struct wordlist *));
+static void auth_set_ip_addr __P((int));
 static void auth_script __P((char *));
 static void set_allowed_addrs __P((int, struct wordlist *));
 
@@ -161,12 +168,18 @@
 link_terminated(unit)
     int unit;
 {
+    extern	time_t	etime, stime;
+    extern	int	minutes;
+
     if (phase == PHASE_DEAD)
 	return;
     if (logged_in)
 	plogout();
     phase = PHASE_DEAD;
-    syslog(LOG_NOTICE, "Connection terminated.");
+    etime = time((time_t *) NULL);
+    minutes = (etime-stime)/60;
+    syslog(LOG_NOTICE, "Connection terminated, connected for %d minutes\n",
+	minutes > 1 ? minutes : 1);
 }
 
 /*
@@ -352,6 +365,13 @@
 	namelen = sizeof(peer_authname) - 1;
     BCOPY(name, peer_authname, namelen);
     peer_authname[namelen] = 0;
+
+    /*
+     * If we have overridden addresses based on auth info
+     * then set that information now before continuing.
+     */
+    auth_set_ip_addr(unit);
+
     script_setenv("PEERNAME", peer_authname);
 
     /*
@@ -403,6 +423,12 @@
     }
 
     /*
+     * If we have overridden addresses based on auth info
+     * then set that information now before continuing.
+     */
+    auth_set_ip_addr(unit);
+
+    /*
      * If there is no more authentication still being done,
      * proceed to the network (or callback) phase.
      */
@@ -621,14 +647,17 @@
     char passwd[256], user[256];
     char secret[MAXWORDLEN];
     static int attempts = 0;
+    int len;
 
     /*
      * Make copies of apasswd and auser, then null-terminate them.
      */
-    BCOPY(apasswd, passwd, passwdlen);
-    passwd[passwdlen] = '\0';
-    BCOPY(auser, user, userlen);
-    user[userlen] = '\0';
+    len = MIN(passwdlen, sizeof(passwd) - 1);
+    BCOPY(apasswd, passwd, len);
+    passwd[len] = '\0';
+    len = MIN(userlen, sizeof(user) - 1);
+    BCOPY(auser, user, len);
+    user[len] = '\0';
     *msg = (char *) 0;
 
     /*
@@ -647,11 +676,17 @@
 	check_access(f, filename);
 	remote = ipwo->accept_remote? 0: ipwo->hisaddr;
 	if (scan_authfile(f, user, our_name, remote,
-			  secret, &addrs, filename) < 0
-	    || (secret[0] != 0 && (cryptpap || strcmp(passwd, secret) != 0)
-		&& strcmp(crypt(passwd, secret), secret) != 0)) {
-	    syslog(LOG_WARNING, "PAP authentication failure for %s", user);
-	    ret = UPAP_AUTHNAK;
+	    secret, &addrs, filename) < 0) {
+		warn("no PAP secret found for %s", user);
+	} else {
+	    if (secret[0] != 0) {
+		/* password given in pap-secrets - must match */
+		if ((cryptpap || strcmp(passwd, secret) != 0)
+		    && strcmp(crypt(passwd, secret), secret) != 0) {
+			ret = UPAP_AUTHNAK;
+			warn("PAP authentication failure for %s", user);
+		}
+	    }
 	}
 	fclose(f);
     }
@@ -697,6 +732,38 @@
 }
 
 /*
+ * Check if an "entry" is in the file "fname" - used by ppplogin.
+ * Taken from libexec/ftpd/ftpd.c
+ * Returns: 0 if not found, 1 if found, 2 if file can't be opened for reading.
+ */
+static int
+checkfile(fname, name)
+	char *fname;
+	char *name;
+{
+	FILE *fd;
+	int found = 0;
+	char *p, line[BUFSIZ];
+
+	if ((fd = fopen(fname, "r")) != NULL) {
+		while (fgets(line, sizeof(line), fd) != NULL)
+			if ((p = strchr(line, '\n')) != NULL) {
+				*p = '\0';
+				if (line[0] == '#')
+					continue;
+				if (strcmp(line, name) == 0) {
+					found = 1;
+					break;
+				}
+			}
+		(void) fclose(fd);
+	} else {
+		return(2);
+	}
+	return (found);
+}
+
+/*
  * This function is needed for PAM.
  */
 
@@ -767,6 +834,8 @@
  *	UPAP_AUTHNAK: Login failed.
  *	UPAP_AUTHACK: Login succeeded.
  * In either case, msg points to an appropriate message.
+ *
+ * UPAP_AUTHACK should only be returned *after* wtmp and utmp are updated.
  */
 
 static int
@@ -829,6 +898,8 @@
 #else /* #ifdef USE_PAM */
 
     struct passwd *pw;
+    struct utmp utmp;
+    struct timeval tp;
     char *tty;
 
 #ifdef HAS_SHADOW
@@ -841,6 +912,23 @@
     if (pw == NULL) {
 	return (UPAP_AUTHNAK);
     }
+/*
+ * Check that the user is not listed in /etc/ppp/ppp.deny
+ * and that the user's shell is listed in /etc/ppp/ppp.shells
+ * if /etc/ppp/ppp.shells exists.
+ */
+
+    if (checkfile(_PATH_PPPDENY, user) == 1) {
+	    	syslog(LOG_WARNING, "upap user %s: login denied in %s",
+			user, _PATH_PPPDENY);
+		return (UPAP_AUTHNAK);
+    }
+
+    if (checkfile(_PATH_PPPSHELLS, pw->pw_shell) == 0) {
+	    	syslog(LOG_WARNING, "upap user %s: shell %s not in %s",
+			user, pw->pw_shell, _PATH_PPPSHELLS);
+		return (UPAP_AUTHNAK);
+    }
 
 #ifdef HAS_SHADOW
     spwd = getspnam(user);
@@ -867,20 +955,28 @@
 	|| strcmp(crypt(passwd, pw->pw_passwd), pw->pw_passwd) != 0)
 	return (UPAP_AUTHNAK);
 
+    if (pw->pw_expire) {
+	(void)gettimeofday(&tp, (struct timezone *)NULL);
+	if (tp.tv_sec >= pw->pw_expire) {
+	    syslog(LOG_INFO, "pap user %s account expired", user);
+	    return (UPAP_AUTHNAK);
+	}
+    }
+
     /* These functions are not enabled for PAM. The reason for this is that */
     /* there is not necessarily a "passwd" entry for this user. That is     */
     /* real purpose of 'PAM' -- to virtualize the account data from the     */
     /* application. If you want to do the same thing, write the entry in    */
     /* the 'session' hook.                                                  */
 
-    /*
-     * Write a wtmp entry for this user.
-     */
+    /* Log in wtmp and utmp using login() */
 
     tty = devnam;
-    if (strncmp(tty, "/dev/", 5) == 0)
+    if (strncmp(tty, _PATH_DEV, sizeof _PATH_DEV - 1) == 0)
 	tty += 5;
-    logwtmp(tty, user, remote_name);		/* Add wtmp login entry */
+
+    if (logout(tty))		/* Already entered (by login?) */
+        logwtmp(tty, "", "");
 
 #if defined(_PATH_LASTLOG)
     {
@@ -898,6 +994,13 @@
     }
 #endif
 
+    memset((void *)&utmp, 0, sizeof(utmp));
+    utmp.ut_time = time(NULL);
+    (void)strncpy(utmp.ut_name, user, sizeof(utmp.ut_name));
+    (void)strncpy(utmp.ut_host, ":PPP", sizeof(utmp.ut_host));
+    (void)strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line));
+    login(&utmp);		/* This logs us in wtmp too */
+
 #endif /* #ifdef USE_PAM */
 
     syslog(LOG_INFO, "user %s logged in", user);
@@ -935,9 +1038,10 @@
     char *tty;
 
     tty = devnam;
-    if (strncmp(tty, "/dev/", 5) == 0)
+    if (strncmp(tty, _PATH_DEV, sizeof _PATH_DEV - 1) == 0)
 	tty += 5;
-    logwtmp(tty, "", "");		/* Wipe out utmp logout entry */
+    logwtmp(tty, "", "");		/* Wipe out wtmp logout entry */
+    logout(tty);			/* Wipe out utmp */
 #endif
 
     logged_in = FALSE;
@@ -1169,6 +1273,23 @@
     }
 }
 
+static void
+auth_set_ip_addr(unit)
+    int unit;
+{
+    struct wordlist *addrs;
+
+    if (non_wildclient && (addrs = addresses[unit]) != NULL) {
+	for (; addrs != NULL; addrs = addrs->next) {
+	    /* Look for address overrides, and set them if we have any */
+	    if (strchr(addrs->word, ':') != NULL) {
+		if (setipaddr(addrs->word))
+		    break;
+	    }
+	}
+    }
+}
+
 /*
  * auth_ip_addr - check whether the peer is authorized to use
  * a given IP address.  Returns 1 if authorized, 0 otherwise.
@@ -1186,6 +1307,7 @@
     u_int32_t addr;
     struct wordlist *addrs;
 {
+    int x, y;
     u_int32_t a, mask, ah;
     int accept;
     char *ptr_word, *ptr_mask;
@@ -1199,7 +1321,9 @@
     if (addrs == NULL)
 	return !auth_required;		/* no addresses authorized */
 
+    x = y = 0;
     for (; addrs != NULL; addrs = addrs->next) {
+	y++;
 	/* "-" means no addresses authorized, "*" means any address allowed */
 	ptr_word = addrs->word;
 	if (strcmp(ptr_word, "-") == 0)
@@ -1207,6 +1331,14 @@
 	if (strcmp(ptr_word, "*") == 0)
 	    return 1;
 
+	/*
+	 * A colon in the string means that we wish to force a specific
+	 * local:remote address, but we ignore these for now.
+	 */
+	if (strchr(addrs->word, ':') != NULL)
+	    x++;
+	else {
+
 	accept = 1;
 	if (*ptr_word == '!') {
 	    accept = 0;
@@ -1263,8 +1395,9 @@
 	       and mask is in host order. */
 	    if (((addr ^ a) & htonl(mask)) == 0)
 		return accept;
+    }	/* else */
     }
-    return 0;			/* not in list => can't have it */
+    return x == y;			/* not in list => can't have it */
 }
 
 /*
@@ -1449,6 +1582,8 @@
     else if (addr_list != NULL)
 	free_wordlist(addr_list);
 
+    non_wildclient = (best_flag & NONWILD_CLIENT) && client != NULL &&
+      *client != '\0';
     return best_flag;
 }
 
diff -ruN pppd/ccp.c /usr/src/usr.sbin/pppd/ccp.c
--- pppd/ccp.c	Tue Mar 24 20:24:58 1998
+++ /usr/src/usr.sbin/pppd/ccp.c	Mon Jul  7 16:59:27 2003
@@ -37,7 +37,7 @@
 #include "pppd.h"
 #include "fsm.h"
 #include "ccp.h"
-#include <net/ppp-comp.h>
+#include <net/ppp_comp.h>
 
 /*
  * Protocol entry points from main code.
diff -ruN pppd/ccp.h /usr/src/usr.sbin/pppd/ccp.h
--- pppd/ccp.h	Tue Mar 24 20:24:59 1998
+++ /usr/src/usr.sbin/pppd/ccp.h	Mon Jul  7 16:59:27 2003
@@ -24,18 +24,20 @@
  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
  * OR MODIFICATIONS.
  *
- * $Id: ccp.h,v 1.8 1998/03/25 01:25:03 paulus Exp $
+ * $FreeBSD: src/usr.sbin/pppd/ccp.h,v 1.8 1999/08/28 01:19:00 peter Exp $
  */
 
 typedef struct ccp_options {
     u_int bsd_compress: 1;	/* do BSD Compress? */
-    u_int deflate: 1;		/* do Deflate? */
+    u_int deflate: 1;		/* do Deflate? (RFC code) */
+    u_int baddeflate: 1;	/* do Deflate? (Magnalink!) */
     u_int predictor_1: 1;	/* do Predictor-1? */
     u_int predictor_2: 1;	/* do Predictor-2? */
     u_int deflate_correct: 1;	/* use correct code for deflate? */
     u_int deflate_draft: 1;	/* use draft RFC code for deflate? */
     u_short bsd_bits;		/* # bits/code for BSD Compress */
     u_short deflate_size;	/* lg(window size) for Deflate */
+    u_short baddeflate_size;	/* lg(window size) for Deflate */
     short method;		/* code for chosen compression method */
 } ccp_options;
 
diff -ruN pppd/chap.c /usr/src/usr.sbin/pppd/chap.c
--- pppd/chap.c	Thu Nov 27 01:07:48 1997
+++ /usr/src/usr.sbin/pppd/chap.c	Mon Jul  7 16:59:27 2003
@@ -46,6 +46,7 @@
 #include <sys/types.h>
 #include <sys/time.h>
 #include <syslog.h>
+#include <md5.h>
 
 #include "pppd.h"
 #include "chap.h"
diff -ruN pppd/chap_ms.c /usr/src/usr.sbin/pppd/chap_ms.c
--- pppd/chap_ms.c	Tue Mar 31 19:15:48 1998
+++ /usr/src/usr.sbin/pppd/chap_ms.c	Mon Jul  7 16:59:27 2003
@@ -54,7 +54,7 @@
 #include "md4.h"
 
 #ifndef USE_CRYPT
-#include <des.h>
+#include <openssl/des.h>
 #endif
 
 typedef struct {
@@ -266,7 +266,7 @@
 	unicodePassword[i * 2] = (u_char)secret[i];
 
     MD4Init(&md4Context);
-    MD4Update(&md4Context, unicodePassword, secret_len * 2 * 8);	/* Unicode is 2 bytes/char, *8 for bit count */
+    MD4Update(&md4Context, unicodePassword, secret_len * 2);	/* Unicode is 2 bytes/char */
 
     MD4Final(hash, &md4Context); 	/* Tell MD4 we're done */
 
diff -ruN pppd/fsm.c /usr/src/usr.sbin/pppd/fsm.c
--- pppd/fsm.c	Wed Apr 30 00:52:17 1997
+++ /usr/src/usr.sbin/pppd/fsm.c	Mon Jul  7 16:59:27 2003
@@ -170,7 +170,7 @@
 
     case CLOSING:
 	f->state = STOPPING;
-	/* fall through */
+	/* FALLTHROUGH */
     case STOPPED:
     case OPENED:
 	if( f->flags & OPT_RESTART ){
@@ -674,7 +674,7 @@
     switch( f->state ){
     case CLOSING:
 	UNTIMEOUT(fsm_timeout, f);	/* Cancel timeout */
-	/* fall through */
+	/* FALLTHROUGH */
     case CLOSED:
 	f->state = CLOSED;
 	if( f->callbacks->finished )
@@ -686,7 +686,7 @@
     case ACKRCVD:
     case ACKSENT:
 	UNTIMEOUT(fsm_timeout, f);	/* Cancel timeout */
-	/* fall through */
+	/* FALLTHROUGH */
     case STOPPED:
 	f->state = STOPPED;
 	if( f->callbacks->finished )
diff -ruN pppd/main.c /usr/src/usr.sbin/pppd/main.c
--- pppd/main.c	Tue May  5 00:24:17 1998
+++ /usr/src/usr.sbin/pppd/main.c	Mon Jul  7 16:59:27 2003
@@ -74,9 +74,12 @@
 char *progname;			/* Name of this program */
 char hostname[MAXNAMELEN];	/* Our hostname */
 static char pidfilename[MAXPATHLEN];	/* name of pid file */
+static char iffilename[MAXPATHLEN];	/* name of if file */
 static char default_devnam[MAXPATHLEN];	/* name of default device */
 static pid_t pid;		/* Our pid */
 static uid_t uid;		/* Our real user-id */
+time_t		etime,stime;	/* End and Start time */
+int		minutes;	/* connection duration */
 static int conn_running;	/* we have a [dis]connector running */
 
 int ttyfd = -1;			/* Serial port file descriptor */
@@ -164,14 +167,16 @@
     int argc;
     char *argv[];
 {
-    int i, fdflags;
+    int i, n, fdflags;
     struct sigaction sa;
+    FILE *iffile;
     char *p;
     struct passwd *pw;
     struct timeval timo;
     sigset_t mask;
     struct protent *protp;
     struct stat statbuf;
+    int connect_attempts = 0;
     char numbuf[16];
 
     phase = PHASE_INITIALIZE;
@@ -275,6 +280,7 @@
 	detach();
     pid = getpid();
     p = getlogin();
+    stime = time((time_t *) NULL);
     if (p == NULL) {
 	pw = getpwuid(uid);
 	if (pw != NULL && pw->pw_name != NULL)
@@ -477,6 +483,7 @@
 	    if (device_script(connector, ttyfd, ttyfd) < 0) {
 		syslog(LOG_ERR, "Connect script failed");
 		setdtr(ttyfd, FALSE);
+		connect_attempts++;
 		goto fail;
 	    }
 
@@ -485,6 +492,8 @@
 	    sleep(1);		/* give it time to set up its terminal */
 	}
 
+	connect_attempts = 0;	/* we made it through ok */
+
 	/* set line speed, flow control, etc.; clear CLOCAL if modem option */
 	set_up_tty(ttyfd, 0);
 
@@ -493,7 +502,8 @@
 	    while ((i = open(devnam, O_RDWR)) < 0) {
 		if (errno != EINTR)
 		    syslog(LOG_ERR, "Failed to reopen %s: %m", devnam);
-		if (!persist || errno != EINTR || hungup || kill_link)
+		if (!persist || errno != EINTR ||
+			hungup || kill_link)
 		    goto fail;
 	    }
 	    close(i);
@@ -512,9 +522,25 @@
 	    
 	    syslog(LOG_INFO, "Using interface ppp%d", ifunit);
 	    (void) sprintf(ifname, "ppp%d", ifunit);
-	    script_setenv("IFNAME", ifname);
-
+	    
 	    create_pidfile();	/* write pid to file */
+
+	    /* write interface unit number to file */
+	    for (n = strlen(devnam); n > 0 ; n--)
+		    if (devnam[n] == '/') { 
+			    n++;
+			    break;
+		    }
+	    (void) sprintf(iffilename, "%s%s.if", _PATH_VARRUN, &devnam[n]);
+	    if ((iffile = fopen(iffilename, "w")) != NULL) {
+		fprintf(iffile, "ppp%d\n", ifunit);
+		(void) fclose(iffile);
+	    } else {
+		syslog(LOG_ERR, "Failed to create if file %s: %m", iffilename);
+		iffilename[0] = 0;
+	    }
+
+	    script_setenv("IFNAME", ifname);
 	}
 
 	/*
@@ -522,6 +548,7 @@
 	 * incoming events (reply, timeout, etc.).
 	 */
 	syslog(LOG_NOTICE, "Connect: %s <--> %s", ifname, devnam);
+	stime = time((time_t *) NULL);
 	lcp_lowerup(0);
 	lcp_open(0);		/* Start protocol */
 	for (phase = PHASE_ESTABLISH; phase != PHASE_DEAD; ) {
@@ -578,8 +605,18 @@
 		&& unlink(pidfilename) < 0 && errno != ENOENT) 
 		syslog(LOG_WARNING, "unable to delete pid file: %m");
 	    pidfilename[0] = 0;
+
+	    if (iffile)
+		    if (unlink(iffilename) < 0 && errno != ENOENT) 
+			    syslog(LOG_WARNING, "unable to delete if file: %m");
+	    iffilename[0] = 0;
 	}
 
+	/* limit to retries? */
+	if (max_con_attempts)
+	    if (connect_attempts >= max_con_attempts)
+		break;
+
 	if (!persist)
 	    die(1);
 
@@ -671,7 +708,9 @@
 	return;
 
     if (len == 0) {
-	syslog(LOG_NOTICE, "Modem hangup");
+	etime = time((time_t *) NULL);
+	minutes = (etime-stime)/60;
+	syslog(LOG_NOTICE, "Modem hangup, connected for %d minutes", (minutes >1) ? minutes : 1);
 	hungup = 1;
 	lcp_lowerdown(0);	/* serial link is no longer available */
 	link_terminated(0);
@@ -794,7 +833,7 @@
     restore_tty(ttyfd);
 
     if (tty_mode != (mode_t) -1)
-	chmod(devnam, tty_mode);
+	fchmod(ttyfd, tty_mode);
 
     close(ttyfd);
     ttyfd = -1;
diff -ruN pppd/options.c /usr/src/usr.sbin/pppd/options.c
--- pppd/options.c	Wed Mar 25 23:46:07 1998
+++ /usr/src/usr.sbin/pppd/options.c	Mon Jul  7 16:59:27 2003
@@ -31,6 +31,7 @@
 #include <syslog.h>
 #include <string.h>
 #include <netdb.h>
+#include <paths.h>
 #include <pwd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -58,7 +59,7 @@
 #include "ipxcp.h"
 #endif /* IPX_CHANGE */
 
-#include <net/ppp-comp.h>
+#include <net/ppp_comp.h>
 
 #define FALSE	0
 #define TRUE	1
@@ -80,7 +81,7 @@
 int	debug = 0;		/* Debug flag */
 int	kdebugflag = 0;		/* Tell kernel to print debug messages */
 int	default_device = 1;	/* Using /dev/tty or equivalent */
-char	devnam[MAXPATHLEN] = "/dev/tty";	/* Device name */
+char	devnam[MAXPATHLEN] = _PATH_TTY;	/* Device name */
 int	crtscts = 0;		/* Use hardware flow control */
 int	modem = 1;		/* Use modem control lines */
 int	inspeed = 0;		/* Input/Output speed requested */
@@ -90,6 +91,7 @@
 char	*connector = NULL;	/* Script to establish physical link */
 char	*disconnector = NULL;	/* Script to disestablish physical link */
 char	*welcomer = NULL;	/* Script to run after phys link estab. */
+int	max_con_attempts = 0;	/* Maximum connect tries in non-demand mode */
 int	maxconnect = 0;		/* Maximum connect time */
 char	user[MAXNAMELEN];	/* Username for PAP */
 char	passwd[MAXSECRETLEN];	/* Password for PAP */
@@ -133,7 +135,6 @@
  * Prototypes
  */
 static int setdevname __P((char *, int));
-static int setipaddr __P((char *));
 static int setspeed __P((char *));
 static int setdebug __P((char **));
 static int setkdebug __P((char **));
@@ -166,6 +167,7 @@
 static int setconnector __P((char **));
 static int setdisconnector __P((char **));
 static int setwelcomer __P((char **));
+static int setmaxcon __P((char **));
 static int setmaxconnect __P((char **));
 static int setdomain __P((char **));
 static int setnetmask __P((char **));
@@ -307,6 +309,7 @@
     {"connect", 1, setconnector}, /* A program to set up a connection */
     {"disconnect", 1, setdisconnector},	/* program to disconnect serial dev. */
     {"welcome", 1, setwelcomer},/* Script to welcome client */
+    {"connect-max-attempts", 1, setmaxcon},  /* maximum # connect attempts */
     {"maxconnect", 1, setmaxconnect},  /* specify a maximum connect time */
     {"crtscts", 0, setcrtscts},	/* set h/w flow control */
     {"nocrtscts", 0, setnocrtscts}, /* clear h/w flow control */
@@ -379,6 +382,10 @@
     {"papcrypt", 0, setpapcrypt},	/* PAP passwords encrypted */
     {"idle", 1, setidle},		/* idle time limit (seconds) */
     {"holdoff", 1, setholdoff},		/* set holdoff time (seconds) */
+/* backwards compat hack */
+    {"dns1", 1, setdnsaddr},		/* DNS address for the peer's use */
+    {"dns2", 1, setdnsaddr},		/* DNS address for the peer's use */
+/* end compat hack */
     {"ms-dns", 1, setdnsaddr},		/* DNS address for the peer's use */
     {"ms-wins", 1, setwinsaddr},	/* Nameserver for SMB over TCP/IP for peer */
     {"noipx",  0, resetipxproto},	/* Disable IPXCP (and IPX) */
@@ -424,7 +431,7 @@
 #define IMPLEMENTATION ""
 #endif
 
-static char *usage_string = "\
+static const char usage_string[] = "\
 pppd version %s patch level %d%s\n\
 Usage: %s [ options ], where options are:\n\
 	<device>	Communicate over the named device\n\
@@ -688,7 +695,7 @@
     int ret;
 
     dev = devnam;
-    if (strncmp(dev, "/dev/", 5) == 0)
+    if (strncmp(dev, _PATH_DEV, sizeof _PATH_DEV - 1) == 0)
 	dev += 5;
     if (strcmp(dev, "tty") == 0)
 	return 1;		/* don't look for /etc/ppp/options.tty */
@@ -1532,6 +1539,13 @@
     return (1);
 }
 
+static int
+setmaxcon(argv)
+    char **argv;
+{
+    return int_option(*argv, &max_con_attempts);
+}
+
 /*
  * setmaxconnect - Set the maximum connect time
  */
@@ -1658,9 +1672,9 @@
     if (*cp == 0)
 	return 0;
 
-    if (strncmp("/dev/", cp, 5) != 0) {
-	strcpy(dev, "/dev/");
-	strncat(dev, cp, MAXPATHLEN - 5);
+    if (strncmp(_PATH_DEV, cp, sizeof _PATH_DEV - 1) != 0) {
+	strcpy(dev, _PATH_DEV);
+	strncat(dev, cp, MAXPATHLEN - sizeof _PATH_DEV - 1);
 	dev[MAXPATHLEN-1] = 0;
 	cp = dev;
     }
@@ -1688,7 +1702,7 @@
 /*
  * setipaddr - Set the IP address
  */
-static int
+int
 setipaddr(arg)
     char *arg;
 {
@@ -1796,44 +1810,14 @@
 setnetmask(argv)
     char **argv;
 {
-    u_int32_t mask, b;
-    int n, ok;
-    char *p, *endp;
+    struct in_addr mask;
 
-    /*
-     * Unfortunately, if we use inet_addr, we can't tell whether
-     * a result of all 1s is an error or a valid 255.255.255.255.
-     */
-    p = *argv;
-    ok = 0;
-    mask = 0;
-    for (n = 3;; --n) {
-	b = strtoul(p, &endp, 0);
-	if (endp == p)
-	    break;
-	if (b < 0 || b > 255) {
-	    if (n == 3) {
-		/* accept e.g. 0xffffff00 */
-		p = endp;
-		mask = b;
-	    }
-	    break;
-	}
-	mask |= b << (n * 8);
-	p = endp;
-	if (*p != '.' || n == 0)
-	    break;
-	++p;
+    if (!inet_aton(*argv, &mask) || (netmask & ~mask.s_addr)) {
+	fprintf(stderr, "Invalid netmask %s\n", *argv);
+	return (0);
     }
 
-    mask = htonl(mask);
-
-    if (*p != 0 || (netmask & ~mask) != 0) {
-	option_error("invalid netmask value '%s'", *argv);
-	return 0;
-    }
-
-    netmask = mask;
+    netmask = mask.s_addr;
     return (1);
 }
 
@@ -2249,6 +2233,13 @@
 	ccp_allowoptions[0].deflate_size = abits;
     } else
 	ccp_allowoptions[0].deflate = 0;
+
+    /* XXX copy over settings for switch compatibility */
+    ccp_wantoptions[0].baddeflate = ccp_wantoptions[0].deflate;
+    ccp_wantoptions[0].baddeflate_size = ccp_wantoptions[0].deflate_size;
+    ccp_allowoptions[0].baddeflate = ccp_allowoptions[0].deflate;
+    ccp_allowoptions[0].baddeflate_size = ccp_allowoptions[0].deflate_size;
+
     return 1;
 }
 
diff -ruN pppd/pathnames.h /usr/src/usr.sbin/pppd/pathnames.h
--- pppd/pathnames.h	Sat Sep 14 00:20:38 1996
+++ /usr/src/usr.sbin/pppd/pathnames.h	Mon Jul  7 16:59:27 2003
@@ -20,9 +20,11 @@
 #define _PATH_AUTHUP	"/etc/ppp/auth-up"
 #define _PATH_AUTHDOWN	"/etc/ppp/auth-down"
 #define _PATH_TTYOPT	"/etc/ppp/options."
-#define _PATH_CONNERRS	"/etc/ppp/connect-errors"
+#define _PATH_CONNERRS	"/var/log/connect-errors"
 #define _PATH_USEROPT	".ppprc"
 #define _PATH_PEERFILES	"/etc/ppp/peers/"
+#define _PATH_PPPDENY  "/etc/ppp/ppp.deny"
+#define _PATH_PPPSHELLS	"/etc/ppp/ppp.shells"
 
 #ifdef IPX_CHANGE
 #define _PATH_IPXUP	"/etc/ppp/ipx-up"
diff -ruN pppd/ppp.pam /usr/src/usr.sbin/pppd/ppp.pam
--- pppd/ppp.pam	Tue Feb  3 21:50:32 1998
+++ /usr/src/usr.sbin/pppd/ppp.pam	Wed Dec 31 19:00:00 1969
@@ -1,6 +0,0 @@
-#%PAM-1.0
-# Information for the PPPD process with the 'login' option.
-auth	required	/lib/security/pam_pwdb.so shadow nullok
-auth	required	/lib/security/pam_nologin.so
-account	required	/lib/security/pam_permit.so
-session	required	/lib/security/pam_permit.so
diff -ruN pppd/pppd.8 /usr/src/usr.sbin/pppd/pppd.8
--- pppd/pppd.8	Mon Mar 30 23:30:58 1998
+++ /usr/src/usr.sbin/pppd/pppd.8	Mon Jul  7 16:59:27 2003
@@ -42,8 +42,9 @@
 .TP
 .I <speed>
 Set the baud rate to <speed> (a decimal number).  On systems such as
-4.4BSD and NetBSD, any speed can be specified.  Other systems
-(e.g. SunOS) allow only a limited set of speeds.
+4.4BSD and NetBSD, any speed can be specified, providing that it is
+supported by the serial device driver.  Other systems
+(e.g. SunOS, Linux) allow only a limited set of speeds.
 .TP
 .B active-filter \fIfilter-expression
 Specifies a packet filter to be applied to data packets to determine
@@ -57,8 +58,9 @@
 except that qualifiers which are inappropriate for a PPP link, such as
 \fBether\fR and \fBarp\fR, are not permitted.  Generally the filter
 expression should be enclosed in single-quotes to prevent whitespace
-in the expression from being interpreted by the shell. This option
-is currently only available under NetBSD, and then only
+in the expression from being interpreted by the shell.
+This option
+only available
 if both the kernel and pppd were compiled with PPP_FILTER defined.
 .TP
 .B asyncmap \fI<map>
@@ -91,6 +93,11 @@
 program to dial the modem and start the remote ppp session.  This
 option is privileged if the \fInoauth\fR option is used.
 .TP
+.B connect-max-attempts \fI<n>
+Attempt dial-out connection to remote system no more than specified number
+of times (default = 1).  If the connection is not made, pppd will exit.
+Requires that \fBpersist\fR has been specified.
+.TP
 .B crtscts
 Use hardware flow control (i.e. RTS/CTS) to control the flow of data
 on the serial port.  If neither the \fIcrtscts\fR nor the
@@ -130,7 +137,8 @@
 serial device to ensure exclusive access to the device.
 .TP
 .B mru \fIn
-Set the MRU [Maximum Receive Unit] value to \fIn\fR. Pppd
+Set the MRU [Maximum Receive Unit] value to \fIn\fR.
+Pppd
 will ask the peer to send packets of no more than \fIn\fR bytes.  The
 minimum MRU value is 128.  The default MRU value is 1500.  A value of
 296 is recommended for slow links (40 bytes for TCP/IP header + 256
@@ -140,7 +148,7 @@
 Set the MTU [Maximum Transmit Unit] value to \fIn\fR.  Unless the
 peer requests a smaller value via MRU negotiation, pppd will
 request that the kernel networking code send data packets of no more
-than \fIn\fR bytes through the PPP network interface. 
+than \fIn\fR bytes through the PPP network interface.
 .TP
 .B passive
 Enables the "passive" option in the LCP.  With this option, pppd will
@@ -299,55 +307,74 @@
 the IPX protocol will not be started.
 .TP
 .B ipx-node \fIn\fB:\fIm
-Set the IPX node numbers. The two node numbers are separated from each
-other with a colon character. The first number \fIn\fR is the local
-node number. The second number \fIm\fR is the peer's node number. Each
-node number is a hexadecimal number, at most 10 digits long. The node
-numbers on the ipx-network must be unique. There is no valid
-default. If this option is not specified then the node numbers are
+Set the IPX node numbers.
+The two node numbers are separated from each
+other with a colon character.
+The first number \fIn\fR is the local
+node number.
+The second number \fIm\fR is the peer's node number.
+Each
+node number is a hexadecimal number, at most 10 digits long.
+The node
+numbers on the ipx-network must be unique.
+There is no valid
+default.
+If this option is not specified then the node numbers are
 obtained from the peer.
 .TP
 .B ipx-router-name \fI<string>
-Set the name of the router. This is a string and is sent to the peer
+Set the name of the router.
+This is a string and is sent to the peer
 as information data.
 .TP
 .B ipx-routing \fIn
-Set the routing protocol to be received by this option. More than one
-instance of \fIipx-routing\fR may be specified. The '\fInone\fR'
-option (0) may be specified as the only instance of ipx-routing. The
+Set the routing protocol to be received by this option.
+More than one
+instance of \fIipx-routing\fR may be specified.
+The '\fInone\fR'
+option (0) may be specified as the only instance of ipx-routing.
+The
 values may be \fI0\fR for \fINONE\fR, \fI2\fR for \fIRIP/SAP\fR, and
 \fI4\fR for \fINLSP\fR.
 .TP
 .B ipxcp-accept-local
 Accept the peer's NAK for the node number specified in the ipx-node
-option. If a node number was specified, and non-zero, the default is
-to insist that the value be used. If you include this option then you
+option.
+If a node number was specified, and non-zero, the default is
+to insist that the value be used.
+If you include this option then you
 will permit the peer to override the entry of the node number.
 .TP
 .B ipxcp-accept-network
 Accept the peer's NAK for the network number specified in the
-ipx-network option. If a network number was specified, and non-zero, the
-default is to insist that the value be used. If you include this
+ipx-network option.
+If a network number was specified, and non-zero, the
+default is to insist that the value be used.
+If you include this
 option then you will permit the peer to override the entry of the node
 number.
 .TP
 .B ipxcp-accept-remote
 Use the peer's network number specified in the configure request
-frame. If a node number was specified for the peer and this option was
+frame.
+If a node number was specified for the peer and this option was
 not specified, the peer will be forced to use the value which you have
 specified.
 .TP
 .B ipxcp-max-configure \fIn
 Set the maximum number of IPXCP configure request frames which the
-system will send to \fIn\fR. The default is 10.
+system will send to \fIn\fR.
+The default is 10.
 .TP
 .B ipxcp-max-failure \fIn
 Set the maximum number of IPXCP NAK frames which the local system will
-send before it rejects the options. The default value is 3.
+send before it rejects the options.
+The default value is 3.
 .TP
 .B ipxcp-max-terminate \fIn
 Set the maximum nuber of IPXCP terminate request frames before the
-local system considers that the peer is not listening to them. The
+local system considers that the peer is not listening to them.
+The
 default value is 3.
 .TP
 .B kdebug \fIn
@@ -568,7 +595,8 @@
 expression should be enclosed in single-quotes to prevent whitespace
 in the expression from being interpreted by the shell.  Note that it
 is possible to apply different constraints to incoming and outgoing
-packets using the \fBinbound\fR and \fBoutbound\fR qualifiers. This
+packets using the \fBinbound\fR and \fBoutbound\fR qualifiers.
+This
 option is currently only available under NetBSD, and then only if both
 the kernel and pppd were compiled with PPP_FILTER defined.
 .TP
@@ -736,7 +764,11 @@
 client name, server name and secrets fields must each be one word,
 with any embedded spaces or other special characters quoted or
 escaped.  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
+of acceptable IP addresses for that client, or an
+override for "local:remote" addresses (the same format used on the
+command line or in the options file) when on a line that contains a
+specific client name (not a wildcard nor empty).
+If there are only 3 words
 on the line, or if the first word is "-", then all IP addresses are
 disallowed.  To allow any address, use "*".
 A word starting with "!" indicates that the
@@ -794,6 +826,11 @@
 password supplied by the peer.  This avoids the need to have the same
 secret in two places.
 .LP
+Additional checks are performed when the \fBlogin\fR option is used.
+If the file /etc/ppp/ppp.deny exists, and the user is listed in it,
+the authentication fails.  If the file /etc/ppp/ppp.shells exists and
+the user's normal login shell is not listed, the authentication fails.
+.LP
 Authentication must be satisfactorily completed before IPCP (or any
 other Network Control Protocol) can be started.  If the peer is
 required to authenticate itself, and fails to do so, pppd will
@@ -1027,7 +1064,7 @@
 .IP
 \fIinterface-name tty-device speed network-number local-IPX-node-address
 remote-IPX-node-address local-IPX-routing-protocol remote-IPX-routing-protocol
-local-IPX-router-name remote-IPX-router-name ipparam pppd-pid\fR 
+local-IPX-router-name remote-IPX-router-name ipparam pppd-pid\fR
 .IP
 The local-IPX-routing-protocol and remote-IPX-routing-protocol field
 may be one of the following:
@@ -1082,7 +1119,19 @@
 system administrator can create options files in this directory to
 permit non-privileged users to dial out without requiring the peer to
 authenticate, but only to certain trusted peers.
+.TP
+.B /etc/ppp/ppp.deny
+Lists users who may not use the system password PAP authentication.
+.TP
+.B /etc/ppp/ppp.shells
+Lists user shells which are approved for system password PAP authentication
+logins.
+.TP
+.B /usr/share/examples/pppd/
+Sample pppd configuration files.
 .SH SEE ALSO
+.IR chat(8),
+.IR ppp(8)
 .TP
 .B RFC1144
 Jacobson, V.
diff -ruN pppd/pppd.h /usr/src/usr.sbin/pppd/pppd.h
--- pppd/pppd.h	Wed Mar 25 23:46:07 1998
+++ /usr/src/usr.sbin/pppd/pppd.h	Mon Jul  7 16:59:27 2003
@@ -88,6 +88,7 @@
 extern char	*connector;	/* Script to establish physical link */
 extern char	*disconnector;	/* Script to disestablish physical link */
 extern char	*welcomer;	/* Script to welcome client after connection */
+extern int	max_con_attempts;/* Maximum number of times to try dialing */
 extern int	maxconnect;	/* Maximum connect time (seconds) */
 extern char	user[];		/* Our name for authenticating ourselves */
 extern char	passwd[];	/* Password for PAP */
@@ -319,6 +320,8 @@
 				/* Read a word from a file */
 void option_error __P((char *fmt, ...));
 				/* Print an error message about an option */
+int setipaddr __P((char *));	/* set IP addresses */
+
 
 /*
  * This structure is used to store information about certain
diff -ruN pppd/sys-bsd.c /usr/src/usr.sbin/pppd/sys-bsd.c
--- pppd/sys-bsd.c	Thu Apr  2 07:04:12 1998
+++ /usr/src/usr.sbin/pppd/sys-bsd.c	Mon Jul  7 16:59:27 2003
@@ -44,6 +44,7 @@
 #include <sys/time.h>
 #include <sys/stat.h>
 #include <sys/param.h>
+#include <sys/module.h>
 #ifdef NetBSD1_2
 #include <util.h>
 #endif
@@ -58,6 +59,10 @@
 #include <net/if_dl.h>
 #include <netinet/in.h>
 
+#ifdef IPX_CHANGE
+#include <netipx/ipx.h>
+#endif
+
 #if RTM_VERSION >= 3
 #include <sys/param.h>
 #if defined(NetBSD) && (NetBSD >= 199703)
@@ -165,28 +170,29 @@
 }
 
 /*
- * ppp_available - check whether the system has any ppp interfaces
- * (in fact we check whether we can do an ioctl on ppp0).
+ * ppp_available - check whether the system has the ppp module loaded
+ * or compiled in. If it doesn't, and we're actually root (not just SUID
+ * root) try loading it before giving up.
  */
 int
 ppp_available()
 {
-    int s, ok;
-    struct ifreq ifr;
+    const char *modname = "if_ppp";
     extern char *no_ppp_msg;
 
-    if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
-	return 1;		/* can't tell */
+    if (modfind(modname) != -1) {
+	return 1;
+    }
 
-    strncpy(ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
-    ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0;
-    close(s);
+    if (getuid() == 0 && kldload(modname) != -1)
+	return 1;
 
     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;
+in the kernel, please add \"device ppp\" to your kernel config or \n\
+load the if_ppp module.\n";
+
+    return 0;
 }
 
 /*
@@ -562,6 +568,10 @@
     fd_set ready;
     int n;
 
+    if (ttyfd >= FD_SETSIZE) {
+	    syslog(LOG_ERR, "descriptor too big");
+	    die(1);
+    }
     FD_ZERO(&ready);
     FD_SET(ttyfd, &ready);
     n = select(ttyfd+1, &ready, NULL, &ready, timo);
@@ -584,6 +594,10 @@
     fd_set ready;
     int n;
 
+    if (loop_master >= FD_SETSIZE) {
+	    syslog(LOG_ERR, "descriptor too big");
+	    die(1);
+    }
     FD_ZERO(&ready);
     FD_SET(loop_master, &ready);
     n = select(loop_master + 1, &ready, NULL, &ready, timo);
@@ -1060,7 +1074,7 @@
 
     memset(&rtmsg, 0, sizeof(rtmsg));
     rtmsg.hdr.rtm_type = cmd == 's'? RTM_ADD: RTM_DELETE;
-    rtmsg.hdr.rtm_flags = RTF_UP | RTF_GATEWAY;
+    rtmsg.hdr.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
     rtmsg.hdr.rtm_version = RTM_VERSION;
     rtmsg.hdr.rtm_seq = ++rtm_seq;
     rtmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
@@ -1243,6 +1257,106 @@
 }
 #endif	/* RTM_VERSION */
 
+#ifdef IPX_CHANGE
+/********************************************************************
+ *
+ * sipxfaddr - Config the interface IPX networknumber
+ */
+
+int
+sipxfaddr (int unit, unsigned long int network, unsigned char * node )
+  {
+    int    result = 1;
+
+    int    skfd; 
+    struct sockaddr_ipx  ipx_addr;
+    struct ifreq         ifr;
+    struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &ifr.ifr_addr;
+    union ipx_net_u net;
+
+    skfd = socket (AF_IPX, SOCK_DGRAM, 0);
+    if (skfd < 0)
+      { 
+	syslog (LOG_DEBUG, "socket(AF_IPX): %m(%d)", errno);
+	result = 0;
+      }
+    else
+      {
+	memset (&ifr, '\0', sizeof (ifr));
+	strcpy (ifr.ifr_name, ifname);
+
+	memcpy (sipx->sipx_addr.x_host.c_host, node, 6);
+	sipx->sipx_len     = sizeof(sipx);
+	sipx->sipx_family  = AF_IPX;
+	sipx->sipx_port    = 0;
+	memset(&net, 0, sizeof(net));
+	net.long_e = htonl (network);
+	sipx->sipx_addr.x_net = net.net_e;
+/*
+ *  Set the IPX device
+ */
+	if (ioctl(skfd, SIOCSIFADDR, (caddr_t) &ifr) < 0)
+	  {
+	    result = 0;
+	    if (errno != EEXIST)
+	      {
+		syslog (LOG_DEBUG,
+			    "ioctl(SIOCAIFADDR, CRTITF): %m(%d)", errno);
+	      }
+	    else
+	      {
+		syslog (LOG_WARNING,
+			"ioctl(SIOCAIFADDR, CRTITF): Address already exists");
+	      }
+	  }
+	close (skfd);
+      }
+    return result;
+  }
+
+/********************************************************************
+ *
+ * cipxfaddr - Clear the information for the IPX network. The IPX routes
+ *	       are removed and the device is no longer able to pass IPX
+ *	       frames.
+ */
+
+int cipxfaddr (int unit)
+  {
+    int    result = 1;
+
+    int    skfd; 
+    struct sockaddr_ipx  ipx_addr;
+    struct ifreq         ifr;
+    struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &ifr.ifr_addr;
+
+    skfd = socket (AF_IPX, SOCK_DGRAM, 0);
+    if (skfd < 0)
+      { 
+	syslog (LOG_DEBUG, "socket(AF_IPX): %m(%d)", errno);
+	result = 0;
+      }
+    else
+      {
+	memset (&ifr, '\0', sizeof (ifr));
+	strcpy (ifr.ifr_name, ifname);
+
+	sipx->sipx_len     = sizeof(sipx);
+	sipx->sipx_family  = AF_IPX;
+/*
+ *  Set the IPX device
+ */
+	if (ioctl(skfd, SIOCSIFADDR, (caddr_t) &ifr) < 0)
+	  {
+	    syslog (LOG_INFO,
+			"ioctl(SIOCAIFADDR, IPX_DLTITF): %m(%d)", errno);
+	    result = 0;
+	  }
+	close (skfd);
+      }
+    return result;
+  }
+#endif
 
 /*
  * get_ether_addr - get the hardware address of an interface on the
@@ -1274,8 +1388,9 @@
      * address on the same subnet as `ipaddr'.
      */
     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)) {
+    for (ifr = ifc.ifc_req; ifr < ifend;
+		ifr = (struct ifreq *) ((char *)&ifr->ifr_addr
+		    + MAX(ifr->ifr_addr.sa_len, sizeof(ifr->ifr_addr)))) {
 	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));
@@ -1321,7 +1436,8 @@
 	    BCOPY(dla, hwaddr, dla->sdl_len);
 	    return 1;
 	}
-	ifr = (struct ifreq *) ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len);
+	ifr = (struct ifreq *) ((char *)&ifr->ifr_addr
+	    + MAX(ifr->ifr_addr.sa_len, sizeof(ifr->ifr_addr)));
     }
 
     return 0;
@@ -1364,8 +1480,9 @@
 	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)) {
+    for (ifr = ifc.ifc_req; ifr < ifend;
+		ifr = (struct ifreq *) ((char *)&ifr->ifr_addr
+		    + MAX(ifr->ifr_addr.sa_len, sizeof(ifr->ifr_addr)))) {
 	/*
 	 * Check the interface's internet address.
 	 */

Reply to: