11ae349f5Scvs2svn /* 21ae349f5Scvs2svn * PPP IP Control Protocol (IPCP) Module 31ae349f5Scvs2svn * 41ae349f5Scvs2svn * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 51ae349f5Scvs2svn * 61ae349f5Scvs2svn * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 71ae349f5Scvs2svn * 81ae349f5Scvs2svn * Redistribution and use in source and binary forms are permitted 91ae349f5Scvs2svn * provided that the above copyright notice and this paragraph are 101ae349f5Scvs2svn * duplicated in all such forms and that any documentation, 111ae349f5Scvs2svn * advertising materials, and other materials related to such 121ae349f5Scvs2svn * distribution and use acknowledge that the software was developed 131ae349f5Scvs2svn * by the Internet Initiative Japan, Inc. The name of the 141ae349f5Scvs2svn * IIJ may not be used to endorse or promote products derived 151ae349f5Scvs2svn * from this software without specific prior written permission. 161ae349f5Scvs2svn * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 171ae349f5Scvs2svn * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 181ae349f5Scvs2svn * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 191ae349f5Scvs2svn * 206f384573SBrian Somers * $Id: ipcp.c,v 1.50.2.47 1998/04/28 01:25:26 brian Exp $ 211ae349f5Scvs2svn * 221ae349f5Scvs2svn * TODO: 231ae349f5Scvs2svn * o More RFC1772 backwoard compatibility 241ae349f5Scvs2svn */ 251ae349f5Scvs2svn #include <sys/param.h> 261ae349f5Scvs2svn #include <netinet/in_systm.h> 271ae349f5Scvs2svn #include <netinet/in.h> 281ae349f5Scvs2svn #include <netinet/ip.h> 291ae349f5Scvs2svn #include <arpa/inet.h> 301ae349f5Scvs2svn #include <sys/socket.h> 311ae349f5Scvs2svn #include <netdb.h> 32455aabc3SBrian Somers #include <net/if.h> 33455aabc3SBrian Somers #include <sys/sockio.h> 341fa665f5SBrian Somers #include <sys/un.h> 351ae349f5Scvs2svn 363edeb0c6SBrian Somers #include <fcntl.h> 373edeb0c6SBrian Somers #include <resolv.h> 381ae349f5Scvs2svn #include <stdlib.h> 391ae349f5Scvs2svn #include <string.h> 40455aabc3SBrian Somers #include <sys/errno.h> 416140ba11SBrian Somers #include <termios.h> 421ae349f5Scvs2svn #include <unistd.h> 431ae349f5Scvs2svn 441ae349f5Scvs2svn #include "command.h" 451ae349f5Scvs2svn #include "mbuf.h" 461ae349f5Scvs2svn #include "log.h" 471ae349f5Scvs2svn #include "defs.h" 481ae349f5Scvs2svn #include "timer.h" 491ae349f5Scvs2svn #include "fsm.h" 501ae349f5Scvs2svn #include "lcpproto.h" 511ae349f5Scvs2svn #include "lcp.h" 521ae349f5Scvs2svn #include "iplist.h" 5329e275ceSBrian Somers #include "throughput.h" 541ae349f5Scvs2svn #include "slcompress.h" 55eaa4df37SBrian Somers #include "ipcp.h" 565ca5389aSBrian Somers #include "filter.h" 572f786681SBrian Somers #include "descriptor.h" 581ae349f5Scvs2svn #include "loadalias.h" 591ae349f5Scvs2svn #include "vjcomp.h" 60879ed6faSBrian Somers #include "lqr.h" 618c07a7b2SBrian Somers #include "hdlc.h" 626140ba11SBrian Somers #include "async.h" 633b0f8d2eSBrian Somers #include "ccp.h" 648c07a7b2SBrian Somers #include "link.h" 6563b73463SBrian Somers #include "physical.h" 663b0f8d2eSBrian Somers #include "mp.h" 673b0f8d2eSBrian Somers #include "bundle.h" 68455aabc3SBrian Somers #include "id.h" 69455aabc3SBrian Somers #include "arp.h" 70455aabc3SBrian Somers #include "systems.h" 7185b542cfSBrian Somers #include "prompt.h" 721ae349f5Scvs2svn 73503a7782SBrian Somers #undef REJECTED 74503a7782SBrian Somers #define REJECTED(p, x) ((p)->peer_reject & (1<<(x))) 753edeb0c6SBrian Somers #define issep(ch) ((ch) == ' ' || (ch) == '\t') 763edeb0c6SBrian Somers #define isip(ch) (((ch) >= '0' && (ch) <= '9') || (ch) == '.') 77503a7782SBrian Somers 7829e275ceSBrian Somers struct compreq { 7929e275ceSBrian Somers u_short proto; 8029e275ceSBrian Somers u_char slots; 8129e275ceSBrian Somers u_char compcid; 8229e275ceSBrian Somers }; 831ae349f5Scvs2svn 846f384573SBrian Somers static int IpcpLayerUp(struct fsm *); 851ae349f5Scvs2svn static void IpcpLayerDown(struct fsm *); 867308ec68SBrian Somers static void IpcpLayerStart(struct fsm *); 877308ec68SBrian Somers static void IpcpLayerFinish(struct fsm *); 881ae349f5Scvs2svn static void IpcpInitRestartCounter(struct fsm *); 897308ec68SBrian Somers static void IpcpSendConfigReq(struct fsm *); 902267893fSBrian Somers static void IpcpSentTerminateReq(struct fsm *); 912267893fSBrian Somers static void IpcpSendTerminateAck(struct fsm *, u_char); 9230c2f2ffSBrian Somers static void IpcpDecodeConfig(struct fsm *, u_char *, int, int, 9330c2f2ffSBrian Somers struct fsm_decode *); 9483d1af55SBrian Somers 9583d1af55SBrian Somers static struct fsm_callbacks ipcp_Callbacks = { 9683d1af55SBrian Somers IpcpLayerUp, 9783d1af55SBrian Somers IpcpLayerDown, 9883d1af55SBrian Somers IpcpLayerStart, 996d666775SBrian Somers IpcpLayerFinish, 10083d1af55SBrian Somers IpcpInitRestartCounter, 10183d1af55SBrian Somers IpcpSendConfigReq, 1022267893fSBrian Somers IpcpSentTerminateReq, 10383d1af55SBrian Somers IpcpSendTerminateAck, 10483d1af55SBrian Somers IpcpDecodeConfig, 105503a7782SBrian Somers NullRecvResetReq, 106503a7782SBrian Somers NullRecvResetAck 10783d1af55SBrian Somers }; 1081ae349f5Scvs2svn 1091ae349f5Scvs2svn static const char *cftypes[] = { 1101ae349f5Scvs2svn /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */ 1111ae349f5Scvs2svn "???", 1121ae349f5Scvs2svn "IPADDRS", /* 1: IP-Addresses */ /* deprecated */ 1131ae349f5Scvs2svn "COMPPROTO", /* 2: IP-Compression-Protocol */ 1141ae349f5Scvs2svn "IPADDR", /* 3: IP-Address */ 1151ae349f5Scvs2svn }; 1161ae349f5Scvs2svn 1171ae349f5Scvs2svn #define NCFTYPES (sizeof cftypes/sizeof cftypes[0]) 1181ae349f5Scvs2svn 1191ae349f5Scvs2svn static const char *cftypes128[] = { 1201ae349f5Scvs2svn /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */ 1211ae349f5Scvs2svn "???", 1221ae349f5Scvs2svn "PRIDNS", /* 129: Primary DNS Server Address */ 1231ae349f5Scvs2svn "PRINBNS", /* 130: Primary NBNS Server Address */ 1241ae349f5Scvs2svn "SECDNS", /* 131: Secondary DNS Server Address */ 1251ae349f5Scvs2svn "SECNBNS", /* 132: Secondary NBNS Server Address */ 1261ae349f5Scvs2svn }; 1271ae349f5Scvs2svn 1281ae349f5Scvs2svn #define NCFTYPES128 (sizeof cftypes128/sizeof cftypes128[0]) 1291ae349f5Scvs2svn 1301ae349f5Scvs2svn void 1315828db6dSBrian Somers ipcp_AddInOctets(struct ipcp *ipcp, int n) 1321ae349f5Scvs2svn { 1335828db6dSBrian Somers throughput_addin(&ipcp->throughput, n); 1341ae349f5Scvs2svn } 1351ae349f5Scvs2svn 1361ae349f5Scvs2svn void 1375828db6dSBrian Somers ipcp_AddOutOctets(struct ipcp *ipcp, int n) 1381ae349f5Scvs2svn { 1395828db6dSBrian Somers throughput_addout(&ipcp->throughput, n); 1401ae349f5Scvs2svn } 1411ae349f5Scvs2svn 1423edeb0c6SBrian Somers static void 1433edeb0c6SBrian Somers getdns(struct ipcp *ipcp, struct in_addr addr[2]) 1443edeb0c6SBrian Somers { 1453edeb0c6SBrian Somers FILE *fp; 1463edeb0c6SBrian Somers 1473edeb0c6SBrian Somers addr[0].s_addr = addr[1].s_addr = INADDR_ANY; 1483edeb0c6SBrian Somers if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { 1493edeb0c6SBrian Somers char buf[LINE_LEN], *cp, *end; 1503edeb0c6SBrian Somers int n; 1513edeb0c6SBrian Somers 1523edeb0c6SBrian Somers n = 0; 1533edeb0c6SBrian Somers buf[sizeof buf - 1] = '\0'; 1543edeb0c6SBrian Somers while (fgets(buf, sizeof buf - 1, fp)) { 1553edeb0c6SBrian Somers if (!strncmp(buf, "nameserver", 10) && issep(buf[10])) { 1563edeb0c6SBrian Somers for (cp = buf + 11; issep(*cp); cp++) 1573edeb0c6SBrian Somers ; 1583edeb0c6SBrian Somers for (end = cp; isip(*end); end++) 1593edeb0c6SBrian Somers ; 1603edeb0c6SBrian Somers *end = '\0'; 1613edeb0c6SBrian Somers if (inet_aton(cp, addr+n) && ++n == 2) 1623edeb0c6SBrian Somers break; 1633edeb0c6SBrian Somers } 1643edeb0c6SBrian Somers } 1653edeb0c6SBrian Somers if (n == 1) 1663edeb0c6SBrian Somers addr[1] = addr[0]; 1673edeb0c6SBrian Somers fclose(fp); 1683edeb0c6SBrian Somers } 1693edeb0c6SBrian Somers } 1703edeb0c6SBrian Somers 1713edeb0c6SBrian Somers static int 1723edeb0c6SBrian Somers setdns(struct ipcp *ipcp, struct in_addr addr[2]) 1733edeb0c6SBrian Somers { 1743edeb0c6SBrian Somers FILE *fp; 1753edeb0c6SBrian Somers char wbuf[LINE_LEN + 54]; 1763edeb0c6SBrian Somers int wlen; 1773edeb0c6SBrian Somers 1783edeb0c6SBrian Somers if (addr[0].s_addr == INADDR_ANY || addr[1].s_addr == INADDR_ANY) { 1793edeb0c6SBrian Somers struct in_addr old[2]; 1803edeb0c6SBrian Somers 1813edeb0c6SBrian Somers getdns(ipcp, old); 1823edeb0c6SBrian Somers if (addr[0].s_addr == INADDR_ANY) 1833edeb0c6SBrian Somers addr[0] = old[0]; 1843edeb0c6SBrian Somers if (addr[1].s_addr == INADDR_ANY) 1853edeb0c6SBrian Somers addr[1] = old[1]; 1863edeb0c6SBrian Somers } 1873edeb0c6SBrian Somers 1883edeb0c6SBrian Somers if (addr[0].s_addr == INADDR_ANY && addr[1].s_addr == INADDR_ANY) { 1893edeb0c6SBrian Somers LogPrintf(LogWARN, "%s not modified: All nameservers NAKd\n", 1903edeb0c6SBrian Somers _PATH_RESCONF); 1913edeb0c6SBrian Somers return 0; 1923edeb0c6SBrian Somers } 1933edeb0c6SBrian Somers 1943edeb0c6SBrian Somers wlen = 0; 1953edeb0c6SBrian Somers if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { 1963edeb0c6SBrian Somers char buf[LINE_LEN]; 1973edeb0c6SBrian Somers int len; 1983edeb0c6SBrian Somers 1993edeb0c6SBrian Somers buf[sizeof buf - 1] = '\0'; 2003edeb0c6SBrian Somers while (fgets(buf, sizeof buf - 1, fp)) { 2013edeb0c6SBrian Somers if (strncmp(buf, "nameserver", 10) || !issep(buf[10])) { 2023edeb0c6SBrian Somers len = strlen(buf); 2033edeb0c6SBrian Somers if (len > sizeof wbuf - wlen) { 2043edeb0c6SBrian Somers LogPrintf(LogWARN, "%s: Can only cope with max file size %d\n", 2053edeb0c6SBrian Somers _PATH_RESCONF, LINE_LEN); 2063edeb0c6SBrian Somers fclose(fp); 2073edeb0c6SBrian Somers return 0; 2083edeb0c6SBrian Somers } 2093edeb0c6SBrian Somers memcpy(wbuf + wlen, buf, len); 2103edeb0c6SBrian Somers wlen += len; 2113edeb0c6SBrian Somers } 2123edeb0c6SBrian Somers } 2133edeb0c6SBrian Somers fclose(fp); 2143edeb0c6SBrian Somers } 2153edeb0c6SBrian Somers 2163edeb0c6SBrian Somers if (addr[0].s_addr != INADDR_ANY) { 2173edeb0c6SBrian Somers snprintf(wbuf + wlen, sizeof wbuf - wlen, "nameserver %s\n", 2183edeb0c6SBrian Somers inet_ntoa(addr[0])); 2193edeb0c6SBrian Somers LogPrintf(LogIPCP, "Primary nameserver set to %s", wbuf + wlen + 11); 2203edeb0c6SBrian Somers wlen += strlen(wbuf + wlen); 2213edeb0c6SBrian Somers } 2223edeb0c6SBrian Somers 2233edeb0c6SBrian Somers if (addr[1].s_addr != INADDR_ANY && addr[1].s_addr != addr[0].s_addr) { 2243edeb0c6SBrian Somers snprintf(wbuf + wlen, sizeof wbuf - wlen, "nameserver %s\n", 2253edeb0c6SBrian Somers inet_ntoa(addr[1])); 2263edeb0c6SBrian Somers LogPrintf(LogIPCP, "Secondary nameserver set to %s", wbuf + wlen + 11); 2273edeb0c6SBrian Somers wlen += strlen(wbuf + wlen); 2283edeb0c6SBrian Somers } 2293edeb0c6SBrian Somers 2303edeb0c6SBrian Somers if (wlen) { 2313edeb0c6SBrian Somers int fd; 2323edeb0c6SBrian Somers 2333edeb0c6SBrian Somers if ((fd = ID0open(_PATH_RESCONF, O_WRONLY|O_CREAT, 0644)) != -1) { 2343edeb0c6SBrian Somers if (write(fd, wbuf, wlen) != wlen) { 2353edeb0c6SBrian Somers LogPrintf(LogERROR, "setdns: write(): %s\n", strerror(errno)); 2363edeb0c6SBrian Somers close(fd); 2373edeb0c6SBrian Somers return 0; 2383edeb0c6SBrian Somers } 2393edeb0c6SBrian Somers if (ftruncate(fd, wlen) == -1) { 2403edeb0c6SBrian Somers LogPrintf(LogERROR, "setdns: truncate(): %s\n", strerror(errno)); 2413edeb0c6SBrian Somers close(fd); 2423edeb0c6SBrian Somers return 0; 2433edeb0c6SBrian Somers } 2443edeb0c6SBrian Somers close(fd); 2453edeb0c6SBrian Somers } else { 2463edeb0c6SBrian Somers LogPrintf(LogERROR, "setdns: open(): %s\n", strerror(errno)); 2473edeb0c6SBrian Somers return 0; 2483edeb0c6SBrian Somers } 2493edeb0c6SBrian Somers } 2503edeb0c6SBrian Somers 2513edeb0c6SBrian Somers return 1; 2523edeb0c6SBrian Somers } 2533edeb0c6SBrian Somers 2541ae349f5Scvs2svn int 2551ae349f5Scvs2svn ReportIpcpStatus(struct cmdargs const *arg) 2561ae349f5Scvs2svn { 257b6217683SBrian Somers prompt_Printf(arg->prompt, "%s [%s]\n", arg->bundle->ncp.ipcp.fsm.name, 2581e991daaSBrian Somers State2Nam(arg->bundle->ncp.ipcp.fsm.state)); 2595828db6dSBrian Somers if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) { 260b6217683SBrian Somers prompt_Printf(arg->prompt, " His side: %s, %s\n", 2615828db6dSBrian Somers inet_ntoa(arg->bundle->ncp.ipcp.peer_ip), 2625828db6dSBrian Somers vj2asc(arg->bundle->ncp.ipcp.peer_compproto)); 263b6217683SBrian Somers prompt_Printf(arg->prompt, " My side: %s, %s\n", 2645828db6dSBrian Somers inet_ntoa(arg->bundle->ncp.ipcp.my_ip), 2655828db6dSBrian Somers vj2asc(arg->bundle->ncp.ipcp.my_compproto)); 2661ae349f5Scvs2svn } 2671ae349f5Scvs2svn 268b6217683SBrian Somers prompt_Printf(arg->prompt, "\nDefaults:\n"); 26950abd4c8SBrian Somers prompt_Printf(arg->prompt, " My Address: %s/%d", 2705828db6dSBrian Somers inet_ntoa(arg->bundle->ncp.ipcp.cfg.my_range.ipaddr), 2715828db6dSBrian Somers arg->bundle->ncp.ipcp.cfg.my_range.width); 27250abd4c8SBrian Somers 27350abd4c8SBrian Somers if (arg->bundle->ncp.ipcp.cfg.HaveTriggerAddress) 27450abd4c8SBrian Somers prompt_Printf(arg->prompt, " (trigger with %s)", 27550abd4c8SBrian Somers inet_ntoa(arg->bundle->ncp.ipcp.cfg.TriggerAddress)); 27650abd4c8SBrian Somers prompt_Printf(arg->prompt, "\n VJ compression: %s (%d slots %s slot " 27750abd4c8SBrian Somers "compression)\n", 27850abd4c8SBrian Somers command_ShowNegval(arg->bundle->ncp.ipcp.cfg.vj.neg), 27950abd4c8SBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slots, 28050abd4c8SBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slotcomp ? "with" : "without"); 28150abd4c8SBrian Somers 2825828db6dSBrian Somers if (iplist_isvalid(&arg->bundle->ncp.ipcp.cfg.peer_list)) 283b6217683SBrian Somers prompt_Printf(arg->prompt, " His Address: %s\n", 2845828db6dSBrian Somers arg->bundle->ncp.ipcp.cfg.peer_list.src); 2851ae349f5Scvs2svn else 286b6217683SBrian Somers prompt_Printf(arg->prompt, " His Address: %s/%d\n", 2875828db6dSBrian Somers inet_ntoa(arg->bundle->ncp.ipcp.cfg.peer_range.ipaddr), 2885828db6dSBrian Somers arg->bundle->ncp.ipcp.cfg.peer_range.width); 28950abd4c8SBrian Somers 2903edeb0c6SBrian Somers prompt_Printf(arg->prompt, " DNS: %s, ", 2913edeb0c6SBrian Somers inet_ntoa(arg->bundle->ncp.ipcp.cfg.ns.dns[0])); 29250abd4c8SBrian Somers prompt_Printf(arg->prompt, "%s, %s\n", 29350abd4c8SBrian Somers inet_ntoa(arg->bundle->ncp.ipcp.cfg.ns.dns[1]), 29450abd4c8SBrian Somers command_ShowNegval(arg->bundle->ncp.ipcp.cfg.ns.dns_neg)); 2953edeb0c6SBrian Somers prompt_Printf(arg->prompt, " NetBIOS NS: %s, ", 2963edeb0c6SBrian Somers inet_ntoa(arg->bundle->ncp.ipcp.cfg.ns.nbns[0])); 2973edeb0c6SBrian Somers prompt_Printf(arg->prompt, "%s\n", 2983edeb0c6SBrian Somers inet_ntoa(arg->bundle->ncp.ipcp.cfg.ns.nbns[1])); 2991342caedSBrian Somers 300b6217683SBrian Somers prompt_Printf(arg->prompt, "\n"); 301b6217683SBrian Somers throughput_disp(&arg->bundle->ncp.ipcp.throughput, arg->prompt); 3021ae349f5Scvs2svn 3031ae349f5Scvs2svn return 0; 3041ae349f5Scvs2svn } 3051ae349f5Scvs2svn 3061ae349f5Scvs2svn int 3075828db6dSBrian Somers SetInitVJ(struct cmdargs const *arg) 3081ae349f5Scvs2svn { 30925092092SBrian Somers if (arg->argc != arg->argn+2) 3101ae349f5Scvs2svn return -1; 31125092092SBrian Somers if (!strcasecmp(arg->argv[arg->argn], "slots")) { 3121ae349f5Scvs2svn int slots; 3131ae349f5Scvs2svn 31425092092SBrian Somers slots = atoi(arg->argv[arg->argn+1]); 3151ae349f5Scvs2svn if (slots < 4 || slots > 16) 3161ae349f5Scvs2svn return 1; 3171342caedSBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slots = slots; 3181ae349f5Scvs2svn return 0; 31925092092SBrian Somers } else if (!strcasecmp(arg->argv[arg->argn], "slotcomp")) { 32025092092SBrian Somers if (!strcasecmp(arg->argv[arg->argn+1], "on")) 3211342caedSBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 1; 32225092092SBrian Somers else if (!strcasecmp(arg->argv[arg->argn+1], "off")) 3231342caedSBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 0; 3241ae349f5Scvs2svn else 3251ae349f5Scvs2svn return 2; 3261ae349f5Scvs2svn return 0; 3271ae349f5Scvs2svn } 3281ae349f5Scvs2svn return -1; 3291ae349f5Scvs2svn } 3301ae349f5Scvs2svn 3311ae349f5Scvs2svn void 3326d666775SBrian Somers ipcp_Init(struct ipcp *ipcp, struct bundle *bundle, struct link *l, 3336d666775SBrian Somers const struct fsm_parent *parent) 3341ae349f5Scvs2svn { 335503a7782SBrian Somers struct hostent *hp; 336503a7782SBrian Somers char name[MAXHOSTNAMELEN]; 3373b0f8d2eSBrian Somers static const char *timer_names[] = 3383b0f8d2eSBrian Somers {"IPCP restart", "IPCP openmode", "IPCP stopped"}; 33929e275ceSBrian Somers 3403b0f8d2eSBrian Somers fsm_Init(&ipcp->fsm, "IPCP", PROTO_IPCP, 1, IPCP_MAXCODE, 10, LogIPCP, 3413b0f8d2eSBrian Somers bundle, l, parent, &ipcp_Callbacks, timer_names); 342503a7782SBrian Somers 3431342caedSBrian Somers ipcp->cfg.vj.slots = DEF_VJ_STATES; 3441342caedSBrian Somers ipcp->cfg.vj.slotcomp = 1; 345503a7782SBrian Somers memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range); 346503a7782SBrian Somers if (gethostname(name, sizeof name) == 0) { 347503a7782SBrian Somers hp = gethostbyname(name); 348503a7782SBrian Somers if (hp && hp->h_addrtype == AF_INET) { 349503a7782SBrian Somers memcpy(&ipcp->cfg.my_range.ipaddr.s_addr, hp->h_addr, hp->h_length); 350503a7782SBrian Somers ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 351503a7782SBrian Somers ipcp->cfg.peer_range.width = 32; 3521ae349f5Scvs2svn } 353503a7782SBrian Somers } 35430c2f2ffSBrian Somers ipcp->cfg.netmask.s_addr = INADDR_ANY; 355503a7782SBrian Somers memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 356503a7782SBrian Somers iplist_setsrc(&ipcp->cfg.peer_list, ""); 357503a7782SBrian Somers ipcp->cfg.HaveTriggerAddress = 0; 358503a7782SBrian Somers 3593edeb0c6SBrian Somers ipcp->cfg.ns.dns[0].s_addr = INADDR_ANY; 3603edeb0c6SBrian Somers ipcp->cfg.ns.dns[1].s_addr = INADDR_ANY; 3613edeb0c6SBrian Somers ipcp->cfg.ns.dns_neg = 0; 3623edeb0c6SBrian Somers ipcp->cfg.ns.nbns[0].s_addr = INADDR_ANY; 3633edeb0c6SBrian Somers ipcp->cfg.ns.nbns[1].s_addr = INADDR_ANY; 364cd9647a1SBrian Somers 365cd9647a1SBrian Somers ipcp->cfg.fsmretry = DEF_FSMRETRY; 3661342caedSBrian Somers ipcp->cfg.vj.neg = NEG_ENABLED|NEG_ACCEPTED; 367503a7782SBrian Somers 368eaa4df37SBrian Somers memset(&ipcp->vj, '\0', sizeof ipcp->vj); 369eaa4df37SBrian Somers 370503a7782SBrian Somers ipcp->my_ifip.s_addr = INADDR_ANY; 371503a7782SBrian Somers ipcp->peer_ifip.s_addr = INADDR_ANY; 372503a7782SBrian Somers 373fdf61171SBrian Somers throughput_init(&ipcp->throughput); 374503a7782SBrian Somers ipcp_Setup(ipcp); 375503a7782SBrian Somers } 376503a7782SBrian Somers 377503a7782SBrian Somers void 378ce828a6eSBrian Somers ipcp_SetLink(struct ipcp *ipcp, struct link *l) 379ce828a6eSBrian Somers { 380ce828a6eSBrian Somers ipcp->fsm.link = l; 381ce828a6eSBrian Somers } 382ce828a6eSBrian Somers 383ce828a6eSBrian Somers void 384503a7782SBrian Somers ipcp_Setup(struct ipcp *ipcp) 385503a7782SBrian Somers { 386503a7782SBrian Somers int pos; 387503a7782SBrian Somers 388503a7782SBrian Somers ipcp->fsm.open_mode = 0; 3895454ccd9SBrian Somers ipcp->fsm.maxconfig = 10; 390503a7782SBrian Somers 391503a7782SBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 392503a7782SBrian Somers if (ipcp->my_ifip.s_addr != INADDR_ANY && 393503a7782SBrian Somers (pos = iplist_ip2pos(&ipcp->cfg.peer_list, ipcp->my_ifip)) != -1) 394503a7782SBrian Somers ipcp->cfg.peer_range.ipaddr = iplist_setcurpos(&ipcp->cfg.peer_list, pos); 395503a7782SBrian Somers else 396503a7782SBrian Somers ipcp->cfg.peer_range.ipaddr = iplist_setrandpos(&ipcp->cfg.peer_list); 397503a7782SBrian Somers ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 398503a7782SBrian Somers ipcp->cfg.peer_range.width = 32; 399503a7782SBrian Somers } 400503a7782SBrian Somers 401503a7782SBrian Somers ipcp->heis1172 = 0; 402503a7782SBrian Somers 403503a7782SBrian Somers ipcp->peer_ip = ipcp->cfg.peer_range.ipaddr; 404503a7782SBrian Somers ipcp->peer_compproto = 0; 4051ae349f5Scvs2svn 4068390b576SBrian Somers if (ipcp->cfg.HaveTriggerAddress) { 4071ae349f5Scvs2svn /* 4081ae349f5Scvs2svn * Some implementations of PPP require that we send a 4091ae349f5Scvs2svn * *special* value as our address, even though the rfc specifies 4101ae349f5Scvs2svn * full negotiation (e.g. "0.0.0.0" or Not "0.0.0.0"). 4111ae349f5Scvs2svn */ 412503a7782SBrian Somers ipcp->my_ip = ipcp->cfg.TriggerAddress; 41329e275ceSBrian Somers LogPrintf(LogIPCP, "Using trigger address %s\n", 414503a7782SBrian Somers inet_ntoa(ipcp->cfg.TriggerAddress)); 4158390b576SBrian Somers } else if ((ipcp->my_ifip.s_addr & ipcp->cfg.my_range.mask.s_addr) == 4168390b576SBrian Somers (ipcp->cfg.my_range.ipaddr.s_addr & 4178390b576SBrian Somers ipcp->cfg.my_range.mask.s_addr)) 4188390b576SBrian Somers /* 4198390b576SBrian Somers * Otherwise, if we've been assigned an IP number before, we really 4208390b576SBrian Somers * want to keep the same IP number so that we can keep any existing 4218390b576SBrian Somers * connections that are bound to that IP. 4228390b576SBrian Somers */ 4238390b576SBrian Somers ipcp->my_ip = ipcp->my_ifip; 4248390b576SBrian Somers else 425503a7782SBrian Somers ipcp->my_ip = ipcp->cfg.my_range.ipaddr; 42629e275ceSBrian Somers 4271342caedSBrian Somers if (IsEnabled(ipcp->cfg.vj.neg)) 428503a7782SBrian Somers ipcp->my_compproto = (PROTO_VJCOMP << 16) + 4291342caedSBrian Somers ((ipcp->cfg.vj.slots - 1) << 8) + 4301342caedSBrian Somers ipcp->cfg.vj.slotcomp; 4311ae349f5Scvs2svn else 432503a7782SBrian Somers ipcp->my_compproto = 0; 4331342caedSBrian Somers sl_compress_init(&ipcp->vj.cslc, ipcp->cfg.vj.slots - 1); 43429e275ceSBrian Somers 435503a7782SBrian Somers ipcp->peer_reject = 0; 436503a7782SBrian Somers ipcp->my_reject = 0; 437503a7782SBrian Somers 438fdf61171SBrian Somers throughput_stop(&ipcp->throughput); 439503a7782SBrian Somers throughput_init(&ipcp->throughput); 4401ae349f5Scvs2svn } 4411ae349f5Scvs2svn 442455aabc3SBrian Somers static int 44330c2f2ffSBrian Somers ipcp_SetIPaddress(struct bundle *bundle, struct in_addr myaddr, 44430c2f2ffSBrian Somers struct in_addr hisaddr, int silent) 445455aabc3SBrian Somers { 446455aabc3SBrian Somers struct sockaddr_in *sock_in; 447455aabc3SBrian Somers int s; 448455aabc3SBrian Somers u_long mask, addr; 449455aabc3SBrian Somers struct ifaliasreq ifra; 450455aabc3SBrian Somers 451455aabc3SBrian Somers /* If given addresses are alreay set, then ignore this request */ 45230c2f2ffSBrian Somers if (bundle->ncp.ipcp.my_ifip.s_addr == myaddr.s_addr && 45330c2f2ffSBrian Somers bundle->ncp.ipcp.peer_ifip.s_addr == hisaddr.s_addr) 454455aabc3SBrian Somers return 0; 455455aabc3SBrian Somers 456565e35e5SBrian Somers IpcpCleanInterface(&bundle->ncp.ipcp); 45768a0f0ccSBrian Somers 458455aabc3SBrian Somers s = ID0socket(AF_INET, SOCK_DGRAM, 0); 459455aabc3SBrian Somers if (s < 0) { 460455aabc3SBrian Somers LogPrintf(LogERROR, "SetIpDevice: socket(): %s\n", strerror(errno)); 461455aabc3SBrian Somers return (-1); 462455aabc3SBrian Somers } 463455aabc3SBrian Somers 464455aabc3SBrian Somers memset(&ifra, '\0', sizeof ifra); 465455aabc3SBrian Somers strncpy(ifra.ifra_name, bundle->ifname, sizeof ifra.ifra_name - 1); 466455aabc3SBrian Somers ifra.ifra_name[sizeof ifra.ifra_name - 1] = '\0'; 467455aabc3SBrian Somers 468455aabc3SBrian Somers /* Set interface address */ 469455aabc3SBrian Somers sock_in = (struct sockaddr_in *)&ifra.ifra_addr; 470455aabc3SBrian Somers sock_in->sin_family = AF_INET; 471455aabc3SBrian Somers sock_in->sin_addr = myaddr; 472455aabc3SBrian Somers sock_in->sin_len = sizeof *sock_in; 473455aabc3SBrian Somers 474455aabc3SBrian Somers /* Set destination address */ 475455aabc3SBrian Somers sock_in = (struct sockaddr_in *)&ifra.ifra_broadaddr; 476455aabc3SBrian Somers sock_in->sin_family = AF_INET; 477455aabc3SBrian Somers sock_in->sin_addr = hisaddr; 478455aabc3SBrian Somers sock_in->sin_len = sizeof *sock_in; 479455aabc3SBrian Somers 480455aabc3SBrian Somers addr = ntohl(myaddr.s_addr); 481455aabc3SBrian Somers if (IN_CLASSA(addr)) 482455aabc3SBrian Somers mask = IN_CLASSA_NET; 483455aabc3SBrian Somers else if (IN_CLASSB(addr)) 484455aabc3SBrian Somers mask = IN_CLASSB_NET; 485455aabc3SBrian Somers else 486455aabc3SBrian Somers mask = IN_CLASSC_NET; 487455aabc3SBrian Somers 488455aabc3SBrian Somers /* if subnet mask is given, use it instead of class mask */ 48930c2f2ffSBrian Somers if (bundle->ncp.ipcp.cfg.netmask.s_addr != INADDR_ANY && 49030c2f2ffSBrian Somers (ntohl(bundle->ncp.ipcp.cfg.netmask.s_addr) & mask) == mask) 49130c2f2ffSBrian Somers mask = ntohl(bundle->ncp.ipcp.cfg.netmask.s_addr); 492455aabc3SBrian Somers 493455aabc3SBrian Somers sock_in = (struct sockaddr_in *)&ifra.ifra_mask; 494455aabc3SBrian Somers sock_in->sin_family = AF_INET; 495455aabc3SBrian Somers sock_in->sin_addr.s_addr = htonl(mask); 496455aabc3SBrian Somers sock_in->sin_len = sizeof *sock_in; 497455aabc3SBrian Somers 498455aabc3SBrian Somers if (ID0ioctl(s, SIOCAIFADDR, &ifra) < 0) { 499455aabc3SBrian Somers if (!silent) 500455aabc3SBrian Somers LogPrintf(LogERROR, "SetIpDevice: ioctl(SIOCAIFADDR): %s\n", 501455aabc3SBrian Somers strerror(errno)); 502455aabc3SBrian Somers close(s); 503455aabc3SBrian Somers return (-1); 504455aabc3SBrian Somers } 505455aabc3SBrian Somers 50630c2f2ffSBrian Somers bundle->ncp.ipcp.peer_ifip.s_addr = hisaddr.s_addr; 50730c2f2ffSBrian Somers bundle->ncp.ipcp.my_ifip.s_addr = myaddr.s_addr; 508455aabc3SBrian Somers 5091342caedSBrian Somers if (Enabled(bundle, OPT_PROXY)) 51030c2f2ffSBrian Somers sifproxyarp(bundle, bundle->ncp.ipcp.peer_ifip, s); 511455aabc3SBrian Somers 512455aabc3SBrian Somers close(s); 513455aabc3SBrian Somers return (0); 514455aabc3SBrian Somers } 515455aabc3SBrian Somers 516455aabc3SBrian Somers static struct in_addr 51730c2f2ffSBrian Somers ChooseHisAddr(struct bundle *bundle, const struct in_addr gw) 518455aabc3SBrian Somers { 519455aabc3SBrian Somers struct in_addr try; 520455aabc3SBrian Somers int f; 521455aabc3SBrian Somers 5225828db6dSBrian Somers for (f = 0; f < bundle->ncp.ipcp.cfg.peer_list.nItems; f++) { 5235828db6dSBrian Somers try = iplist_next(&bundle->ncp.ipcp.cfg.peer_list); 524455aabc3SBrian Somers LogPrintf(LogDEBUG, "ChooseHisAddr: Check item %d (%s)\n", 525455aabc3SBrian Somers f, inet_ntoa(try)); 52630c2f2ffSBrian Somers if (ipcp_SetIPaddress(bundle, gw, try, 1) == 0) { 527d47dceb8SBrian Somers LogPrintf(LogIPCP, "Selected IP address %s\n", inet_ntoa(try)); 528455aabc3SBrian Somers break; 529455aabc3SBrian Somers } 530455aabc3SBrian Somers } 531455aabc3SBrian Somers 5325828db6dSBrian Somers if (f == bundle->ncp.ipcp.cfg.peer_list.nItems) { 533455aabc3SBrian Somers LogPrintf(LogDEBUG, "ChooseHisAddr: All addresses in use !\n"); 534455aabc3SBrian Somers try.s_addr = INADDR_ANY; 535455aabc3SBrian Somers } 536455aabc3SBrian Somers 537455aabc3SBrian Somers return try; 538455aabc3SBrian Somers } 539455aabc3SBrian Somers 5401ae349f5Scvs2svn static void 5411ae349f5Scvs2svn IpcpInitRestartCounter(struct fsm * fp) 5421ae349f5Scvs2svn { 5437308ec68SBrian Somers /* Set fsm timer load */ 544cd9647a1SBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 545cd9647a1SBrian Somers 546cd9647a1SBrian Somers fp->FsmTimer.load = ipcp->cfg.fsmretry * SECTICKS; 5471ae349f5Scvs2svn fp->restart = 5; 5481ae349f5Scvs2svn } 5491ae349f5Scvs2svn 5501ae349f5Scvs2svn static void 5511ae349f5Scvs2svn IpcpSendConfigReq(struct fsm *fp) 5521ae349f5Scvs2svn { 5537308ec68SBrian Somers /* Send config REQ please */ 5548c07a7b2SBrian Somers struct physical *p = link2physical(fp->link); 555aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 5563edeb0c6SBrian Somers u_char buff[24]; 5572267893fSBrian Somers struct lcp_opt *o; 5581ae349f5Scvs2svn 5592267893fSBrian Somers o = (struct lcp_opt *)buff; 56030c2f2ffSBrian Somers 56183d1af55SBrian Somers if ((p && !Physical_IsSync(p)) || !REJECTED(ipcp, TY_IPADDR)) { 5622267893fSBrian Somers *(u_int32_t *)o->data = ipcp->my_ip.s_addr; 5632267893fSBrian Somers INC_LCP_OPT(TY_IPADDR, 6, o); 5641ae349f5Scvs2svn } 5651ae349f5Scvs2svn 566e43ebac1SBrian Somers if (ipcp->my_compproto && !REJECTED(ipcp, TY_COMPPROTO)) { 56783d1af55SBrian Somers if (ipcp->heis1172) { 5682267893fSBrian Somers *(u_short *)o->data = htons(PROTO_VJCOMP); 5692267893fSBrian Somers INC_LCP_OPT(TY_COMPPROTO, 4, o); 5701ae349f5Scvs2svn } else { 5712267893fSBrian Somers *(u_long *)o->data = htonl(ipcp->my_compproto); 5722267893fSBrian Somers INC_LCP_OPT(TY_COMPPROTO, 6, o); 5731ae349f5Scvs2svn } 574e43ebac1SBrian Somers } 5752267893fSBrian Somers 5763edeb0c6SBrian Somers if (IsEnabled(ipcp->cfg.ns.dns_neg) && 5773edeb0c6SBrian Somers !REJECTED(ipcp, TY_PRIMARY_DNS - TY_ADJUST_NS) && 5783edeb0c6SBrian Somers !REJECTED(ipcp, TY_SECONDARY_DNS - TY_ADJUST_NS)) { 5793edeb0c6SBrian Somers struct in_addr dns[2]; 5803edeb0c6SBrian Somers getdns(ipcp, dns); 5813edeb0c6SBrian Somers *(u_int32_t *)o->data = dns[0].s_addr; 5823edeb0c6SBrian Somers INC_LCP_OPT(TY_PRIMARY_DNS, 6, o); 5833edeb0c6SBrian Somers *(u_int32_t *)o->data = dns[1].s_addr; 5843edeb0c6SBrian Somers INC_LCP_OPT(TY_SECONDARY_DNS, 6, o); 5853edeb0c6SBrian Somers } 5863edeb0c6SBrian Somers 5872267893fSBrian Somers FsmOutput(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff); 5881ae349f5Scvs2svn } 5891ae349f5Scvs2svn 5901ae349f5Scvs2svn static void 5912267893fSBrian Somers IpcpSentTerminateReq(struct fsm * fp) 5921ae349f5Scvs2svn { 5937308ec68SBrian Somers /* Term REQ just sent by FSM */ 5941ae349f5Scvs2svn } 5951ae349f5Scvs2svn 5961ae349f5Scvs2svn static void 5972267893fSBrian Somers IpcpSendTerminateAck(struct fsm *fp, u_char id) 5981ae349f5Scvs2svn { 5997308ec68SBrian Somers /* Send Term ACK please */ 6002267893fSBrian Somers FsmOutput(fp, CODE_TERMACK, id, NULL, 0); 6011ae349f5Scvs2svn } 6021ae349f5Scvs2svn 6031ae349f5Scvs2svn static void 6041ae349f5Scvs2svn IpcpLayerStart(struct fsm * fp) 6051ae349f5Scvs2svn { 6067308ec68SBrian Somers /* We're about to start up ! */ 607d47dceb8SBrian Somers LogPrintf(LogIPCP, "%s: IpcpLayerStart.\n", fp->link->name); 608455aabc3SBrian Somers 609565e35e5SBrian Somers /* This is where we should be setting up the interface in DEMAND mode */ 6101ae349f5Scvs2svn } 6111ae349f5Scvs2svn 6121ae349f5Scvs2svn static void 6131ae349f5Scvs2svn IpcpLayerFinish(struct fsm *fp) 6141ae349f5Scvs2svn { 6157308ec68SBrian Somers /* We're now down */ 616d47dceb8SBrian Somers LogPrintf(LogIPCP, "%s: IpcpLayerFinish.\n", fp->link->name); 6171ae349f5Scvs2svn } 6181ae349f5Scvs2svn 61968a0f0ccSBrian Somers void 620565e35e5SBrian Somers IpcpCleanInterface(struct ipcp *ipcp) 62168a0f0ccSBrian Somers { 62268a0f0ccSBrian Somers struct ifaliasreq ifra; 62368a0f0ccSBrian Somers struct sockaddr_in *me, *peer; 62468a0f0ccSBrian Somers int s; 62568a0f0ccSBrian Somers 62668a0f0ccSBrian Somers s = ID0socket(AF_INET, SOCK_DGRAM, 0); 62768a0f0ccSBrian Somers if (s < 0) { 62868a0f0ccSBrian Somers LogPrintf(LogERROR, "IpcpCleanInterface: socket: %s\n", strerror(errno)); 62968a0f0ccSBrian Somers return; 63068a0f0ccSBrian Somers } 63168a0f0ccSBrian Somers 6321342caedSBrian Somers if (Enabled(ipcp->fsm.bundle, OPT_PROXY)) 633565e35e5SBrian Somers cifproxyarp(ipcp->fsm.bundle, ipcp->peer_ifip, s); 63468a0f0ccSBrian Somers 635503a7782SBrian Somers if (ipcp->my_ifip.s_addr != INADDR_ANY || 636503a7782SBrian Somers ipcp->peer_ifip.s_addr != INADDR_ANY) { 63768a0f0ccSBrian Somers memset(&ifra, '\0', sizeof ifra); 638565e35e5SBrian Somers strncpy(ifra.ifra_name, ipcp->fsm.bundle->ifname, 639565e35e5SBrian Somers sizeof ifra.ifra_name - 1); 64068a0f0ccSBrian Somers ifra.ifra_name[sizeof ifra.ifra_name - 1] = '\0'; 64168a0f0ccSBrian Somers me = (struct sockaddr_in *)&ifra.ifra_addr; 64268a0f0ccSBrian Somers peer = (struct sockaddr_in *)&ifra.ifra_broadaddr; 64368a0f0ccSBrian Somers me->sin_family = peer->sin_family = AF_INET; 64468a0f0ccSBrian Somers me->sin_len = peer->sin_len = sizeof(struct sockaddr_in); 645503a7782SBrian Somers me->sin_addr = ipcp->my_ifip; 646503a7782SBrian Somers peer->sin_addr = ipcp->peer_ifip; 64768a0f0ccSBrian Somers if (ID0ioctl(s, SIOCDIFADDR, &ifra) < 0) { 64868a0f0ccSBrian Somers LogPrintf(LogERROR, "IpcpCleanInterface: ioctl(SIOCDIFADDR): %s\n", 64968a0f0ccSBrian Somers strerror(errno)); 65068a0f0ccSBrian Somers close(s); 65168a0f0ccSBrian Somers } 652503a7782SBrian Somers ipcp->my_ifip.s_addr = ipcp->peer_ifip.s_addr = INADDR_ANY; 65368a0f0ccSBrian Somers } 65468a0f0ccSBrian Somers 65568a0f0ccSBrian Somers close(s); 65668a0f0ccSBrian Somers } 65768a0f0ccSBrian Somers 6581ae349f5Scvs2svn static void 6591ae349f5Scvs2svn IpcpLayerDown(struct fsm *fp) 6601ae349f5Scvs2svn { 6617308ec68SBrian Somers /* About to come down */ 662aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 663455aabc3SBrian Somers const char *s; 664455aabc3SBrian Somers 665503a7782SBrian Somers s = inet_ntoa(ipcp->peer_ifip); 666d47dceb8SBrian Somers LogPrintf(LogIPCP, "%s: IpcpLayerDown: %s\n", fp->link->name, s); 667455aabc3SBrian Somers 66883d1af55SBrian Somers throughput_stop(&ipcp->throughput); 66983d1af55SBrian Somers throughput_log(&ipcp->throughput, LogIPCP, NULL); 670455aabc3SBrian Somers /* 671455aabc3SBrian Somers * XXX this stuff should really live in the FSM. Our config should 672455aabc3SBrian Somers * associate executable sections in files with events. 673455aabc3SBrian Somers */ 674e43ebac1SBrian Somers if (SelectSystem(fp->bundle, s, LINKDOWNFILE, NULL) < 0) { 67549052c95SBrian Somers if (bundle_GetLabel(fp->bundle)) { 67649052c95SBrian Somers if (SelectSystem(fp->bundle, bundle_GetLabel(fp->bundle), 67749052c95SBrian Somers LINKDOWNFILE, NULL) < 0) 678b6217683SBrian Somers SelectSystem(fp->bundle, "MYADDR", LINKDOWNFILE, NULL); 679455aabc3SBrian Somers } else 680b6217683SBrian Somers SelectSystem(fp->bundle, "MYADDR", LINKDOWNFILE, NULL); 681e43ebac1SBrian Somers } 682455aabc3SBrian Somers 683ba081e43SBrian Somers if (!(ipcp->fsm.bundle->phys_type & PHYS_DEMAND)) 684565e35e5SBrian Somers IpcpCleanInterface(ipcp); 6851ae349f5Scvs2svn } 6861ae349f5Scvs2svn 6876f384573SBrian Somers static int 6881ae349f5Scvs2svn IpcpLayerUp(struct fsm *fp) 6891ae349f5Scvs2svn { 6907308ec68SBrian Somers /* We're now up */ 691aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 6921ae349f5Scvs2svn char tbuff[100]; 6931ae349f5Scvs2svn 694d47dceb8SBrian Somers LogPrintf(LogIPCP, "%s: IpcpLayerUp.\n", fp->link->name); 695503a7782SBrian Somers snprintf(tbuff, sizeof tbuff, "myaddr = %s ", inet_ntoa(ipcp->my_ip)); 696d47dceb8SBrian Somers LogPrintf(LogIPCP, " %s hisaddr = %s\n", tbuff, inet_ntoa(ipcp->peer_ip)); 6971ae349f5Scvs2svn 698503a7782SBrian Somers if (ipcp->peer_compproto >> 16 == PROTO_VJCOMP) 699eaa4df37SBrian Somers sl_compress_init(&ipcp->vj.cslc, (ipcp->peer_compproto >> 8) & 255); 7001ae349f5Scvs2svn 701ba081e43SBrian Somers if (ipcp_SetIPaddress(fp->bundle, ipcp->my_ip, ipcp->peer_ip, 0) < 0) { 7021ae349f5Scvs2svn LogPrintf(LogERROR, "IpcpLayerUp: unable to set ip address\n"); 7036f384573SBrian Somers return 0; 7041ae349f5Scvs2svn } 705455aabc3SBrian Somers 7061ae349f5Scvs2svn #ifndef NOALIAS 70785602e52SBrian Somers if (AliasEnabled()) 7082764b86aSBrian Somers (*PacketAlias.SetAddress)(ipcp->my_ip); 7091ae349f5Scvs2svn #endif 710455aabc3SBrian Somers 711455aabc3SBrian Somers /* 712455aabc3SBrian Somers * XXX this stuff should really live in the FSM. Our config should 713455aabc3SBrian Somers * associate executable sections in files with events. 714455aabc3SBrian Somers */ 715e43ebac1SBrian Somers if (SelectSystem(fp->bundle, inet_ntoa(ipcp->my_ifip), LINKUPFILE, NULL) 716e43ebac1SBrian Somers < 0) { 71749052c95SBrian Somers if (bundle_GetLabel(fp->bundle)) { 71849052c95SBrian Somers if (SelectSystem(fp->bundle, bundle_GetLabel(fp->bundle), 71949052c95SBrian Somers LINKUPFILE, NULL) < 0) 720b6217683SBrian Somers SelectSystem(fp->bundle, "MYADDR", LINKUPFILE, NULL); 721455aabc3SBrian Somers } else 722b6217683SBrian Somers SelectSystem(fp->bundle, "MYADDR", LINKUPFILE, NULL); 723e43ebac1SBrian Somers } 724455aabc3SBrian Somers 7251342caedSBrian Somers throughput_start(&ipcp->throughput, "IPCP throughput", 7261342caedSBrian Somers Enabled(fp->bundle, OPT_THROUGHPUT)); 727b6217683SBrian Somers bundle_DisplayPrompt(fp->bundle); 7286f384573SBrian Somers return 1; 7291ae349f5Scvs2svn } 7301ae349f5Scvs2svn 7311ae349f5Scvs2svn static int 7321ae349f5Scvs2svn AcceptableAddr(struct in_range *prange, struct in_addr ipaddr) 7331ae349f5Scvs2svn { 7347308ec68SBrian Somers /* Is the given IP in the given range ? */ 7351ae349f5Scvs2svn return (prange->ipaddr.s_addr & prange->mask.s_addr) == 7361ae349f5Scvs2svn (ipaddr.s_addr & prange->mask.s_addr) && ipaddr.s_addr; 7371ae349f5Scvs2svn } 7381ae349f5Scvs2svn 7391ae349f5Scvs2svn static void 74030c2f2ffSBrian Somers IpcpDecodeConfig(struct fsm *fp, u_char * cp, int plen, int mode_type, 74130c2f2ffSBrian Somers struct fsm_decode *dec) 7421ae349f5Scvs2svn { 7437308ec68SBrian Somers /* Deal with incoming PROTO_IPCP */ 744aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 7451ae349f5Scvs2svn int type, length; 746fe3125a0SBrian Somers u_int32_t compproto; 7471ae349f5Scvs2svn struct compreq *pcomp; 7483edeb0c6SBrian Somers struct in_addr ipaddr, dstipaddr, have_ip, dns[2], dnsnak[2]; 74930c2f2ffSBrian Somers char tbuff[100], tbuff2[100]; 7503edeb0c6SBrian Somers int gotdns, gotdnsnak; 7513edeb0c6SBrian Somers 7523edeb0c6SBrian Somers gotdns = 0; 7533edeb0c6SBrian Somers gotdnsnak = 0; 7543edeb0c6SBrian Somers dnsnak[0].s_addr = dnsnak[1].s_addr = INADDR_ANY; 7551ae349f5Scvs2svn 7561ae349f5Scvs2svn while (plen >= sizeof(struct fsmconfig)) { 7571ae349f5Scvs2svn type = *cp; 7581ae349f5Scvs2svn length = cp[1]; 759d47dceb8SBrian Somers 760d47dceb8SBrian Somers if (length == 0) { 761d47dceb8SBrian Somers LogPrintf(LogIPCP, "%s: IPCP size zero\n", fp->link->name); 762d47dceb8SBrian Somers break; 763d47dceb8SBrian Somers } 764d47dceb8SBrian Somers 7651ae349f5Scvs2svn if (type < NCFTYPES) 7661ae349f5Scvs2svn snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes[type], length); 7671ae349f5Scvs2svn else if (type > 128 && type < 128 + NCFTYPES128) 7681ae349f5Scvs2svn snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes128[type-128], length); 7691ae349f5Scvs2svn else 7701ae349f5Scvs2svn snprintf(tbuff, sizeof tbuff, " <%d>[%d] ", type, length); 7711ae349f5Scvs2svn 7721ae349f5Scvs2svn switch (type) { 7731ae349f5Scvs2svn case TY_IPADDR: /* RFC1332 */ 774fe3125a0SBrian Somers ipaddr.s_addr = *(u_int32_t *)(cp + 2); 7751ae349f5Scvs2svn LogPrintf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 7761ae349f5Scvs2svn 7771ae349f5Scvs2svn switch (mode_type) { 7781ae349f5Scvs2svn case MODE_REQ: 779503a7782SBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 7801ae349f5Scvs2svn if (ipaddr.s_addr == INADDR_ANY || 781503a7782SBrian Somers iplist_ip2pos(&ipcp->cfg.peer_list, ipaddr) < 0 || 78230c2f2ffSBrian Somers ipcp_SetIPaddress(fp->bundle, ipcp->cfg.my_range.ipaddr, 78330c2f2ffSBrian Somers ipaddr, 1)) { 7841ae349f5Scvs2svn LogPrintf(LogIPCP, "%s: Address invalid or already in use\n", 7851ae349f5Scvs2svn inet_ntoa(ipaddr)); 7868390b576SBrian Somers if (iplist_ip2pos(&ipcp->cfg.peer_list, ipcp->peer_ifip) >= 0) 7878390b576SBrian Somers /* 7888390b576SBrian Somers * If we've already got a valid address configured for the peer 789565e35e5SBrian Somers * (in DEMAND mode), try NAKing with that so that we don't 7908390b576SBrian Somers * have to upset things too much. 7918390b576SBrian Somers */ 7928390b576SBrian Somers ipcp->peer_ip = ipcp->peer_ifip; 7938390b576SBrian Somers else 7948390b576SBrian Somers /* Just pick an IP number from our list */ 795503a7782SBrian Somers ipcp->peer_ip = ChooseHisAddr 79630c2f2ffSBrian Somers (fp->bundle, ipcp->cfg.my_range.ipaddr); 7978390b576SBrian Somers 798503a7782SBrian Somers if (ipcp->peer_ip.s_addr == INADDR_ANY) { 79930c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 80030c2f2ffSBrian Somers dec->rejend += length; 8011ae349f5Scvs2svn } else { 80230c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 80330c2f2ffSBrian Somers memcpy(dec->nakend+2, &ipcp->peer_ip.s_addr, length - 2); 80430c2f2ffSBrian Somers dec->nakend += length; 8051ae349f5Scvs2svn } 8061ae349f5Scvs2svn break; 8071ae349f5Scvs2svn } 808503a7782SBrian Somers } else if (!AcceptableAddr(&ipcp->cfg.peer_range, ipaddr)) { 8091ae349f5Scvs2svn /* 8108390b576SBrian Somers * If destination address is not acceptable, NAK with what we 8111ae349f5Scvs2svn * want to use. 8121ae349f5Scvs2svn */ 81330c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 8148390b576SBrian Somers if ((ipcp->peer_ifip.s_addr & ipcp->cfg.peer_range.mask.s_addr) == 8158390b576SBrian Somers (ipcp->cfg.peer_range.ipaddr.s_addr & 8168390b576SBrian Somers ipcp->cfg.peer_range.mask.s_addr)) 8178390b576SBrian Somers /* We prefer the already-configured address */ 8188390b576SBrian Somers memcpy(dec->nakend+2, &ipcp->peer_ifip.s_addr, length - 2); 8198390b576SBrian Somers else 82030c2f2ffSBrian Somers memcpy(dec->nakend+2, &ipcp->peer_ip.s_addr, length - 2); 82130c2f2ffSBrian Somers dec->nakend += length; 8221ae349f5Scvs2svn break; 8231ae349f5Scvs2svn } 824503a7782SBrian Somers ipcp->peer_ip = ipaddr; 82530c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 82630c2f2ffSBrian Somers dec->ackend += length; 8271ae349f5Scvs2svn break; 8281ae349f5Scvs2svn case MODE_NAK: 829503a7782SBrian Somers if (AcceptableAddr(&ipcp->cfg.my_range, ipaddr)) { 8301ae349f5Scvs2svn /* Use address suggested by peer */ 8311ae349f5Scvs2svn snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s ", tbuff, 832503a7782SBrian Somers inet_ntoa(ipcp->my_ip)); 8331ae349f5Scvs2svn LogPrintf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 834503a7782SBrian Somers ipcp->my_ip = ipaddr; 8351ae349f5Scvs2svn } else { 8368390b576SBrian Somers LogPrintf(LogIsKept(LogIPCP) ? LogIPCP : LogPHASE, 8378390b576SBrian Somers "%s: Unacceptable address!\n", inet_ntoa(ipaddr)); 83883d1af55SBrian Somers FsmClose(&ipcp->fsm); 8391ae349f5Scvs2svn } 8401ae349f5Scvs2svn break; 8411ae349f5Scvs2svn case MODE_REJ: 842503a7782SBrian Somers ipcp->peer_reject |= (1 << type); 8431ae349f5Scvs2svn break; 8441ae349f5Scvs2svn } 8451ae349f5Scvs2svn break; 8461ae349f5Scvs2svn case TY_COMPPROTO: 847fe3125a0SBrian Somers compproto = htonl(*(u_int32_t *)(cp + 2)); 8481ae349f5Scvs2svn LogPrintf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto)); 8491ae349f5Scvs2svn 8501ae349f5Scvs2svn switch (mode_type) { 8511ae349f5Scvs2svn case MODE_REQ: 8521342caedSBrian Somers if (!IsAccepted(ipcp->cfg.vj.neg)) { 85330c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 85430c2f2ffSBrian Somers dec->rejend += length; 8551ae349f5Scvs2svn } else { 8561ae349f5Scvs2svn pcomp = (struct compreq *) (cp + 2); 8571ae349f5Scvs2svn switch (length) { 8581ae349f5Scvs2svn case 4: /* RFC1172 */ 8591ae349f5Scvs2svn if (ntohs(pcomp->proto) == PROTO_VJCOMP) { 8601ae349f5Scvs2svn LogPrintf(LogWARN, "Peer is speaking RFC1172 compression protocol !\n"); 86183d1af55SBrian Somers ipcp->heis1172 = 1; 862503a7782SBrian Somers ipcp->peer_compproto = compproto; 86330c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 86430c2f2ffSBrian Somers dec->ackend += length; 8651ae349f5Scvs2svn } else { 86630c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 8671ae349f5Scvs2svn pcomp->proto = htons(PROTO_VJCOMP); 86830c2f2ffSBrian Somers memcpy(dec->nakend+2, &pcomp, 2); 86930c2f2ffSBrian Somers dec->nakend += length; 8701ae349f5Scvs2svn } 8711ae349f5Scvs2svn break; 8721ae349f5Scvs2svn case 6: /* RFC1332 */ 8731ae349f5Scvs2svn if (ntohs(pcomp->proto) == PROTO_VJCOMP 874503a7782SBrian Somers && pcomp->slots <= MAX_VJ_STATES 875503a7782SBrian Somers && pcomp->slots >= MIN_VJ_STATES) { 876503a7782SBrian Somers ipcp->peer_compproto = compproto; 87783d1af55SBrian Somers ipcp->heis1172 = 0; 87830c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 87930c2f2ffSBrian Somers dec->ackend += length; 8801ae349f5Scvs2svn } else { 88130c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 8821ae349f5Scvs2svn pcomp->proto = htons(PROTO_VJCOMP); 883503a7782SBrian Somers pcomp->slots = DEF_VJ_STATES; 8841ae349f5Scvs2svn pcomp->compcid = 0; 88530c2f2ffSBrian Somers memcpy(dec->nakend+2, &pcomp, sizeof pcomp); 88630c2f2ffSBrian Somers dec->nakend += length; 8871ae349f5Scvs2svn } 8881ae349f5Scvs2svn break; 8891ae349f5Scvs2svn default: 89030c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 89130c2f2ffSBrian Somers dec->rejend += length; 8921ae349f5Scvs2svn break; 8931ae349f5Scvs2svn } 8941ae349f5Scvs2svn } 8951ae349f5Scvs2svn break; 8961ae349f5Scvs2svn case MODE_NAK: 8971ae349f5Scvs2svn LogPrintf(LogIPCP, "%s changing compproto: %08x --> %08x\n", 898503a7782SBrian Somers tbuff, ipcp->my_compproto, compproto); 899503a7782SBrian Somers ipcp->my_compproto = compproto; 9001ae349f5Scvs2svn break; 9011ae349f5Scvs2svn case MODE_REJ: 902503a7782SBrian Somers ipcp->peer_reject |= (1 << type); 9031ae349f5Scvs2svn break; 9041ae349f5Scvs2svn } 9051ae349f5Scvs2svn break; 9061ae349f5Scvs2svn case TY_IPADDRS: /* RFC1172 */ 907fe3125a0SBrian Somers ipaddr.s_addr = *(u_int32_t *)(cp + 2); 908fe3125a0SBrian Somers dstipaddr.s_addr = *(u_int32_t *)(cp + 6); 9091ae349f5Scvs2svn snprintf(tbuff2, sizeof tbuff2, "%s %s,", tbuff, inet_ntoa(ipaddr)); 9101ae349f5Scvs2svn LogPrintf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr)); 9111ae349f5Scvs2svn 9121ae349f5Scvs2svn switch (mode_type) { 9131ae349f5Scvs2svn case MODE_REQ: 914503a7782SBrian Somers ipcp->peer_ip = ipaddr; 915503a7782SBrian Somers ipcp->my_ip = dstipaddr; 91630c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 91730c2f2ffSBrian Somers dec->ackend += length; 9181ae349f5Scvs2svn break; 9191ae349f5Scvs2svn case MODE_NAK: 9201ae349f5Scvs2svn snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s", tbuff, 921503a7782SBrian Somers inet_ntoa(ipcp->my_ip)); 9221ae349f5Scvs2svn LogPrintf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 923503a7782SBrian Somers ipcp->my_ip = ipaddr; 924503a7782SBrian Somers ipcp->peer_ip = dstipaddr; 9251ae349f5Scvs2svn break; 9261ae349f5Scvs2svn case MODE_REJ: 927503a7782SBrian Somers ipcp->peer_reject |= (1 << type); 9281ae349f5Scvs2svn break; 9291ae349f5Scvs2svn } 9301ae349f5Scvs2svn break; 9311ae349f5Scvs2svn 9323edeb0c6SBrian Somers case TY_PRIMARY_DNS: /* DNS negotiation (rfc1877) */ 9331ae349f5Scvs2svn case TY_SECONDARY_DNS: 9343edeb0c6SBrian Somers ipaddr.s_addr = *(u_int32_t *)(cp + 2); 9353edeb0c6SBrian Somers LogPrintf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 9363edeb0c6SBrian Somers 93730c2f2ffSBrian Somers switch (mode_type) { 93830c2f2ffSBrian Somers case MODE_REQ: 9393edeb0c6SBrian Somers if (!IsAccepted(ipcp->cfg.ns.dns_neg)) { 9403edeb0c6SBrian Somers ipcp->my_reject |= (1 << (type - TY_ADJUST_NS)); 94130c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 94230c2f2ffSBrian Somers dec->rejend += length; 9431ae349f5Scvs2svn break; 9441ae349f5Scvs2svn } 9453edeb0c6SBrian Somers if (!gotdns) { 9463edeb0c6SBrian Somers dns[0] = ipcp->cfg.ns.dns[0]; 9473edeb0c6SBrian Somers dns[1] = ipcp->cfg.ns.dns[1]; 9483edeb0c6SBrian Somers if (dns[0].s_addr == INADDR_ANY && dns[1].s_addr == INADDR_ANY) 9493edeb0c6SBrian Somers getdns(ipcp, dns); 9503edeb0c6SBrian Somers gotdns = 1; 9513edeb0c6SBrian Somers } 9523edeb0c6SBrian Somers have_ip = dns[type == TY_PRIMARY_DNS ? 0 : 1]; 9531ae349f5Scvs2svn 9543edeb0c6SBrian Somers if (ipaddr.s_addr != have_ip.s_addr) { 9551ae349f5Scvs2svn /* 9563edeb0c6SBrian Somers * The client has got the DNS stuff wrong (first request) so 9571ae349f5Scvs2svn * we'll tell 'em how it is 9581ae349f5Scvs2svn */ 95930c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); /* copy first two (type/length) */ 9603edeb0c6SBrian Somers memcpy(dec->nakend + 2, &have_ip.s_addr, length - 2); 96130c2f2ffSBrian Somers dec->nakend += length; 9623edeb0c6SBrian Somers } else { 9631ae349f5Scvs2svn /* 9641ae349f5Scvs2svn * Otherwise they have it right (this time) so we send a ack packet 9651ae349f5Scvs2svn * back confirming it... end of story 9661ae349f5Scvs2svn */ 96730c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 96830c2f2ffSBrian Somers dec->ackend += length; 9693edeb0c6SBrian Somers } 9701ae349f5Scvs2svn break; 9711ae349f5Scvs2svn case MODE_NAK: /* what does this mean?? */ 9723edeb0c6SBrian Somers if (IsEnabled(ipcp->cfg.ns.dns_neg)) { 9733edeb0c6SBrian Somers gotdnsnak = 1; 9743edeb0c6SBrian Somers dnsnak[type == TY_PRIMARY_DNS ? 0 : 1].s_addr = 9753edeb0c6SBrian Somers *(u_int32_t *)(cp + 2); 9763edeb0c6SBrian Somers } 9771ae349f5Scvs2svn break; 9783edeb0c6SBrian Somers case MODE_REJ: /* Can't do much, stop asking */ 9793edeb0c6SBrian Somers ipcp->peer_reject |= (1 << (type - TY_ADJUST_NS)); 9801ae349f5Scvs2svn break; 9811ae349f5Scvs2svn } 9821ae349f5Scvs2svn break; 9831ae349f5Scvs2svn 9843edeb0c6SBrian Somers case TY_PRIMARY_NBNS: /* M$ NetBIOS nameserver hack (rfc1877) */ 9851ae349f5Scvs2svn case TY_SECONDARY_NBNS: 9863edeb0c6SBrian Somers ipaddr.s_addr = *(u_int32_t *)(cp + 2); 9873edeb0c6SBrian Somers LogPrintf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 9883edeb0c6SBrian Somers 98930c2f2ffSBrian Somers switch (mode_type) { 99030c2f2ffSBrian Somers case MODE_REQ: 9913edeb0c6SBrian Somers have_ip.s_addr = 9923edeb0c6SBrian Somers ipcp->cfg.ns.nbns[type == TY_PRIMARY_NBNS ? 0 : 1].s_addr; 9933edeb0c6SBrian Somers 9943edeb0c6SBrian Somers if (have_ip.s_addr == INADDR_ANY) { 9953edeb0c6SBrian Somers LogPrintf(LogIPCP, "NBNS REQ - rejected - nbns not set\n"); 9963edeb0c6SBrian Somers ipcp->my_reject |= (1 << (type - TY_ADJUST_NS)); 99730c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 99830c2f2ffSBrian Somers dec->rejend += length; 9991ae349f5Scvs2svn break; 10001ae349f5Scvs2svn } 10013edeb0c6SBrian Somers 10023edeb0c6SBrian Somers if (ipaddr.s_addr != have_ip.s_addr) { 100330c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 10043edeb0c6SBrian Somers memcpy(dec->nakend+2, &have_ip.s_addr, length); 100530c2f2ffSBrian Somers dec->nakend += length; 10063edeb0c6SBrian Somers } else { 100730c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 100830c2f2ffSBrian Somers dec->ackend += length; 10093edeb0c6SBrian Somers } 10101ae349f5Scvs2svn break; 10111ae349f5Scvs2svn case MODE_NAK: 10121ae349f5Scvs2svn LogPrintf(LogIPCP, "MS NBNS req %d - NAK??\n", type); 10131ae349f5Scvs2svn break; 10141ae349f5Scvs2svn case MODE_REJ: 10151ae349f5Scvs2svn LogPrintf(LogIPCP, "MS NBNS req %d - REJ??\n", type); 10161ae349f5Scvs2svn break; 10171ae349f5Scvs2svn } 10181ae349f5Scvs2svn break; 10191ae349f5Scvs2svn 10201ae349f5Scvs2svn default: 102130c2f2ffSBrian Somers if (mode_type != MODE_NOP) { 102283d1af55SBrian Somers ipcp->my_reject |= (1 << type); 102330c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 102430c2f2ffSBrian Somers dec->rejend += length; 102530c2f2ffSBrian Somers } 10261ae349f5Scvs2svn break; 10271ae349f5Scvs2svn } 10281ae349f5Scvs2svn plen -= length; 10291ae349f5Scvs2svn cp += length; 10301ae349f5Scvs2svn } 10311342caedSBrian Somers 10323edeb0c6SBrian Somers if (gotdnsnak) 10333edeb0c6SBrian Somers if (!setdns(ipcp, dnsnak)) { 10343edeb0c6SBrian Somers ipcp->peer_reject |= (1 << (TY_PRIMARY_DNS - TY_ADJUST_NS)); 10353edeb0c6SBrian Somers ipcp->peer_reject |= (1 << (TY_SECONDARY_DNS - TY_ADJUST_NS)); 10363edeb0c6SBrian Somers } 10373edeb0c6SBrian Somers 1038e43ebac1SBrian Somers if (mode_type != MODE_NOP) { 10391342caedSBrian Somers if (dec->rejend != dec->rej) { 10401342caedSBrian Somers /* rejects are preferred */ 10411342caedSBrian Somers dec->ackend = dec->ack; 10421342caedSBrian Somers dec->nakend = dec->nak; 10431342caedSBrian Somers } else if (dec->nakend != dec->nak) 10441342caedSBrian Somers /* then NAKs */ 10451342caedSBrian Somers dec->ackend = dec->ack; 10461ae349f5Scvs2svn } 1047e43ebac1SBrian Somers } 10481ae349f5Scvs2svn 10491ae349f5Scvs2svn void 10505828db6dSBrian Somers IpcpInput(struct ipcp *ipcp, struct mbuf * bp) 10511ae349f5Scvs2svn { 10527308ec68SBrian Somers /* Got PROTO_IPCP from link */ 10535828db6dSBrian Somers FsmInput(&ipcp->fsm, bp); 10541ae349f5Scvs2svn } 10551ae349f5Scvs2svn 10561ae349f5Scvs2svn int 10577a6f8720SBrian Somers UseHisaddr(struct bundle *bundle, const char *hisaddr, int setaddr) 10581ae349f5Scvs2svn { 10595828db6dSBrian Somers struct ipcp *ipcp = &bundle->ncp.ipcp; 10605828db6dSBrian Somers 10617308ec68SBrian Somers /* Use `hisaddr' for the peers address (set iface if `setaddr') */ 10625828db6dSBrian Somers memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 10635828db6dSBrian Somers iplist_reset(&ipcp->cfg.peer_list); 10641ae349f5Scvs2svn if (strpbrk(hisaddr, ",-")) { 10655828db6dSBrian Somers iplist_setsrc(&ipcp->cfg.peer_list, hisaddr); 10665828db6dSBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 10675828db6dSBrian Somers iplist_setrandpos(&ipcp->cfg.peer_list); 106830c2f2ffSBrian Somers ipcp->peer_ip = ChooseHisAddr(bundle, ipcp->my_ip); 10695828db6dSBrian Somers if (ipcp->peer_ip.s_addr == INADDR_ANY) { 1070d47dceb8SBrian Somers LogPrintf(LogWARN, "%s: None available !\n", ipcp->cfg.peer_list.src); 10711ae349f5Scvs2svn return(0); 10721ae349f5Scvs2svn } 10735828db6dSBrian Somers ipcp->cfg.peer_range.ipaddr.s_addr = ipcp->peer_ip.s_addr; 10745828db6dSBrian Somers ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 10755828db6dSBrian Somers ipcp->cfg.peer_range.width = 32; 10761ae349f5Scvs2svn } else { 10771ae349f5Scvs2svn LogPrintf(LogWARN, "%s: Invalid range !\n", hisaddr); 10781ae349f5Scvs2svn return 0; 10791ae349f5Scvs2svn } 10805828db6dSBrian Somers } else if (ParseAddr(ipcp, 1, &hisaddr, &ipcp->cfg.peer_range.ipaddr, 10815828db6dSBrian Somers &ipcp->cfg.peer_range.mask, 10825828db6dSBrian Somers &ipcp->cfg.peer_range.width) != 0) { 10835828db6dSBrian Somers ipcp->peer_ip.s_addr = ipcp->cfg.peer_range.ipaddr.s_addr; 10841ae349f5Scvs2svn 108530c2f2ffSBrian Somers if (setaddr && ipcp_SetIPaddress(bundle, ipcp->cfg.my_range.ipaddr, 108630c2f2ffSBrian Somers ipcp->cfg.peer_range.ipaddr, 0) < 0) { 10875828db6dSBrian Somers ipcp->cfg.my_range.ipaddr.s_addr = INADDR_ANY; 10885828db6dSBrian Somers ipcp->cfg.peer_range.ipaddr.s_addr = INADDR_ANY; 10891ae349f5Scvs2svn return 0; 10901ae349f5Scvs2svn } 10911ae349f5Scvs2svn } else 10921ae349f5Scvs2svn return 0; 10931ae349f5Scvs2svn 10941ae349f5Scvs2svn return 1; 10951ae349f5Scvs2svn } 1096