Module Name:    src
Committed By:   christos
Date:           Sat Aug  7 20:38:13 UTC 2010

Modified Files:
        src/dist/pppd/pppd: ipcp.c

Log Message:
Apply changes from 2.4.5. Supposedly fixes some 3G issues.


To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.5 src/dist/pppd/pppd/ipcp.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/dist/pppd/pppd/ipcp.c
diff -u src/dist/pppd/pppd/ipcp.c:1.4 src/dist/pppd/pppd/ipcp.c:1.5
--- src/dist/pppd/pppd/ipcp.c:1.4	Thu Jun 29 17:50:17 2006
+++ src/dist/pppd/pppd/ipcp.c	Sat Aug  7 16:38:13 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: ipcp.c,v 1.4 2006/06/29 21:50:17 christos Exp $	*/
+/*	$NetBSD: ipcp.c,v 1.5 2010/08/07 20:38:13 christos Exp $	*/
 
 /*
  * ipcp.c - PPP IP Control Protocol.
@@ -45,9 +45,10 @@
 #include <sys/cdefs.h>
 #ifndef lint
 #if 0
+#define RCSID	"Id: ipcp.c,v 1.73 2008/05/26 08:33:22 paulus Exp"
 #define RCSID	"Id: ipcp.c,v 1.70 2005/08/25 23:59:34 paulus Exp"
 #else
-__RCSID("$NetBSD: ipcp.c,v 1.4 2006/06/29 21:50:17 christos Exp $");
+__RCSID("$NetBSD: ipcp.c,v 1.5 2010/08/07 20:38:13 christos Exp $");
 #endif
 #endif
 
@@ -83,6 +84,7 @@
 u_int32_t netmask = 0;		/* IP netmask to set on interface */
 
 bool	disable_defaultip = 0;	/* Don't use hostname for default IP adrs */
+bool	noremoteip = 0;		/* Let him have no IP address */
 
 /* Hook for a plugin to know when IP protocol has come up */
 void (*ip_up_hook) __P((void)) = NULL;
@@ -229,6 +231,13 @@
     { "ipcp-no-address", o_bool, &ipcp_wantoptions[0].neg_addr,
       "Disable IP-Address usage", OPT_A2CLR,
       &ipcp_allowoptions[0].neg_addr },
+#ifdef __linux__
+    { "noremoteip", o_bool, &noremoteip,
+      "Allow peer to have no IP address", 1 },
+#endif
+    { "nosendip", o_bool, &ipcp_wantoptions[0].neg_addr,
+      "Don't send our IP address to peer", OPT_A2CLR,
+      &ipcp_wantoptions[0].old_addrs},
 
     { "IP addresses", o_wild, (void *) &setipaddr,
       "set local and remote IP addresses",
@@ -578,6 +587,14 @@
     f->callbacks = &ipcp_callbacks;
     fsm_init(&ipcp_fsm[unit]);
 
+    /*
+     * Some 3G modems use repeated IPCP NAKs as a way of stalling
+     * until they can contact a server on the network, so we increase
+     * the default number of NAKs we accept before we start treating
+     * them as rejects.
+     */
+    f->maxnakloops = 100;
+
     memset(wo, 0, sizeof(*wo));
     memset(ao, 0, sizeof(*ao));
 
@@ -726,7 +743,8 @@
 #define LENCIADDRS(neg)		(neg ? CILEN_ADDRS : 0)
 #define LENCIVJ(neg, old)	(neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0)
 #define LENCIADDR(neg)		(neg ? CILEN_ADDR : 0)
-#define LENCIDNS(neg)		(neg ? (CILEN_ADDR) : 0)
+#define LENCIDNS(neg)		LENCIADDR(neg)
+#define LENCIWINS(neg)		LENCIADDR(neg)
 
     /*
      * First see if we want to change our options to the old
@@ -748,7 +766,9 @@
 	    LENCIVJ(go->neg_vj, go->old_vj) +
 	    LENCIADDR(go->neg_addr) +
 	    LENCIDNS(go->req_dns1) +
-	    LENCIDNS(go->req_dns2)) ;
+	    LENCIDNS(go->req_dns2) +
+	    LENCIWINS(go->winsaddr[0]) +
+	    LENCIWINS(go->winsaddr[1])) ;
 }
 
 
@@ -822,6 +842,19 @@
 	    neg = 0; \
     }
 
+#define ADDCIWINS(opt, addr) \
+    if (addr) { \
+	if (len >= CILEN_ADDR) { \
+	    u_int32_t l; \
+	    PUTCHAR(opt, ucp); \
+	    PUTCHAR(CILEN_ADDR, ucp); \
+	    l = ntohl(addr); \
+	    PUTLONG(l, ucp); \
+	    len -= CILEN_ADDR; \
+	} else \
+	    addr = 0; \
+    }
+
     ADDCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr,
 	       go->hisaddr);
 
@@ -834,6 +867,10 @@
 
     ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);
 
+    ADDCIWINS(CI_MS_WINS1, go->winsaddr[0]);
+
+    ADDCIWINS(CI_MS_WINS2, go->winsaddr[1]);
+    
     *lenp -= len;
 }
 
@@ -1128,6 +1165,8 @@
      * on an option that we didn't include in our request packet.
      * If they want to negotiate about IP addresses, we comply.
      * If they want us to ask for compression, we refuse.
+     * If they want us to ask for ms-dns, we do that, since some
+     * peers get huffy if we don't.
      */
     while (len >= CILEN_VOID) {
 	GETCHAR(citype, p);
@@ -1170,6 +1209,31 @@
 		try.neg_addr = 1;
 	    no.neg_addr = 1;
 	    break;
+	case CI_MS_DNS1:
+	    if (go->req_dns1 || no.req_dns1 || cilen != CILEN_ADDR)
+		goto bad;
+	    GETLONG(l, p);
+	    try.dnsaddr[0] = htonl(l);
+	    try.req_dns1 = 1;
+	    no.req_dns1 = 1;
+	    break;
+	case CI_MS_DNS2:
+	    if (go->req_dns2 || no.req_dns2 || cilen != CILEN_ADDR)
+		goto bad;
+	    GETLONG(l, p);
+	    try.dnsaddr[1] = htonl(l);
+	    try.req_dns2 = 1;
+	    no.req_dns2 = 1;
+	    break;
+	case CI_MS_WINS1:
+	case CI_MS_WINS2:
+	    if (cilen != CILEN_ADDR)
+		goto bad;
+	    GETLONG(l, p);
+	    ciaddr1 = htonl(l);
+	    if (ciaddr1)
+		try.winsaddr[citype == CI_MS_WINS2] = ciaddr1;
+	    break;
 	}
 	p = next;
     }
@@ -1286,6 +1350,21 @@
 	try.neg = 0; \
     }
 
+#define REJCIWINS(opt, addr) \
+    if (addr && \
+	((cilen = p[1]) == CILEN_ADDR) && \
+	len >= cilen && \
+	p[0] == opt) { \
+	u_int32_t l; \
+	len -= cilen; \
+	INCPTR(2, p); \
+	GETLONG(l, p); \
+	cilong = htonl(l); \
+	/* Check rejected value. */ \
+	if (cilong != addr) \
+	    goto bad; \
+	try.winsaddr[opt == CI_MS_WINS2] = 0; \
+    }
 
     REJCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs,
 	       go->ouraddr, go->hisaddr);
@@ -1299,6 +1378,10 @@
 
     REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]);
 
+    REJCIWINS(CI_MS_WINS1, go->winsaddr[0]);
+
+    REJCIWINS(CI_MS_WINS2, go->winsaddr[1]);
+
     /*
      * If there are any remaining CIs, then this packet is bad.
      */
@@ -1592,7 +1675,7 @@
      * option safely.
      */
     if (rc != CONFREJ && !ho->neg_addr && !ho->old_addrs &&
-	wo->req_addr && !reject_if_disagree) {
+	wo->req_addr && !reject_if_disagree && !noremoteip) {
 	if (rc == CONFACK) {
 	    rc = CONFNAK;
 	    ucp = inp;			/* reset pointer */
@@ -1652,7 +1735,7 @@
 {
     ipcp_options *wo = &ipcp_wantoptions[u];
 
-    if (wo->hisaddr == 0) {
+    if (wo->hisaddr == 0 && !noremoteip) {
 	/* make up an arbitrary address for the peer */
 	wo->hisaddr = htonl(0x0a707070 + ifunit);
 	wo->accept_remote = 1;
@@ -1678,7 +1761,8 @@
 	    proxy_arp_set[u] = 1;
 
     notice("local  IP address %I", wo->ouraddr);
-    notice("remote IP address %I", wo->hisaddr);
+    if (wo->hisaddr)
+	notice("remote IP address %I", wo->hisaddr);
 
     return 1;
 }
@@ -1717,14 +1801,19 @@
 	ipcp_close(f->unit, "Could not determine local IP address");
 	return;
     }
-    if (ho->hisaddr == 0) {
+    if (ho->hisaddr == 0 && !noremoteip) {
 	ho->hisaddr = htonl(0x0a404040 + ifunit);
 	warn("Could not determine remote IP address: defaulting to %I",
 	     ho->hisaddr);
     }
     script_setenv("IPLOCAL", ip_ntoa(go->ouraddr), 0);
-    script_setenv("IPREMOTE", ip_ntoa(ho->hisaddr), 1);
+    if (ho->hisaddr != 0)
+	script_setenv("IPREMOTE", ip_ntoa(ho->hisaddr), 1);
 
+    if (!go->req_dns1)
+	go->dnsaddr[0] = 0;
+    if (!go->req_dns2)
+	go->dnsaddr[1] = 0;
     if (go->dnsaddr[0])
 	script_setenv("DNS1", ip_ntoa(go->dnsaddr[0]), 0);
     if (go->dnsaddr[1])
@@ -1737,7 +1826,7 @@
     /*
      * Check that the peer is allowed to use the IP address it wants.
      */
-    if (!auth_ip_addr(f->unit, ho->hisaddr)) {
+    if (ho->hisaddr != 0 && !auth_ip_addr(f->unit, ho->hisaddr)) {
 	error("Peer is not authorized to use remote address %I", ho->hisaddr);
 	ipcp_close(f->unit, "Unauthorized remote IP address");
 	return;
@@ -1760,7 +1849,7 @@
 		wo->ouraddr = go->ouraddr;
 	    } else
 		script_unsetenv("OLDIPLOCAL");
-	    if (ho->hisaddr != wo->hisaddr) {
+	    if (ho->hisaddr != wo->hisaddr && wo->hisaddr != 0) {
 		warn("Remote IP address changed to %I", ho->hisaddr);
 		script_setenv("OLDIPREMOTE", ip_ntoa(wo->hisaddr), 0);
 		wo->hisaddr = ho->hisaddr;
@@ -1777,7 +1866,7 @@
 	    }
 
 	    /* assign a default route through the interface if required */
-	    if (ipcp_wantoptions[f->unit].default_route) 
+	    if (ho->hisaddr != 0 && ipcp_wantoptions[f->unit].default_route) 
 		if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
 		    default_route_set[f->unit] = 1;
 
@@ -1832,14 +1921,15 @@
 		default_route_set[f->unit] = 1;
 
 	/* Make a proxy ARP entry if requested. */
-	if (ipcp_wantoptions[f->unit].proxy_arp)
+	if (ho->hisaddr != 0 && ipcp_wantoptions[f->unit].proxy_arp)
 	    if (sifproxyarp(f->unit, ho->hisaddr))
 		proxy_arp_set[f->unit] = 1;
 
 	ipcp_wantoptions[0].ouraddr = go->ouraddr;
 
 	notice("local  IP address %I", go->ouraddr);
-	notice("remote IP address %I", ho->hisaddr);
+	if (ho->hisaddr != 0)
+	    notice("remote IP address %I", ho->hisaddr);
 	if (go->dnsaddr[0])
 	    notice("primary   DNS address %I", go->dnsaddr[0]);
 	if (go->dnsaddr[1])
@@ -2125,7 +2215,7 @@
 	    case CI_MS_DNS2:
 	        p += 2;
 		GETLONG(cilong, p);
-		printer(arg, "ms-dns%d %I", code - CI_MS_DNS1 + 1,
+		printer(arg, "ms-dns%d %I", (code == CI_MS_DNS1? 1: 2),
 			htonl(cilong));
 		break;
 	    case CI_MS_WINS1:

Reply via email to