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 * 20e43ebac1SBrian Somers * $Id: ipcp.c,v 1.50.2.45 1998/04/25 00:09:11 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> 341ae349f5Scvs2svn 353edeb0c6SBrian Somers #include <fcntl.h> 363edeb0c6SBrian Somers #include <resolv.h> 371ae349f5Scvs2svn #include <stdlib.h> 381ae349f5Scvs2svn #include <string.h> 39455aabc3SBrian Somers #include <sys/errno.h> 406140ba11SBrian Somers #include <termios.h> 411ae349f5Scvs2svn #include <unistd.h> 421ae349f5Scvs2svn 431ae349f5Scvs2svn #include "command.h" 441ae349f5Scvs2svn #include "mbuf.h" 451ae349f5Scvs2svn #include "log.h" 461ae349f5Scvs2svn #include "defs.h" 471ae349f5Scvs2svn #include "timer.h" 481ae349f5Scvs2svn #include "fsm.h" 491ae349f5Scvs2svn #include "lcpproto.h" 501ae349f5Scvs2svn #include "lcp.h" 511ae349f5Scvs2svn #include "iplist.h" 5229e275ceSBrian Somers #include "throughput.h" 531ae349f5Scvs2svn #include "slcompress.h" 54eaa4df37SBrian Somers #include "ipcp.h" 555ca5389aSBrian Somers #include "filter.h" 562f786681SBrian Somers #include "descriptor.h" 571ae349f5Scvs2svn #include "loadalias.h" 581ae349f5Scvs2svn #include "vjcomp.h" 59879ed6faSBrian Somers #include "lqr.h" 608c07a7b2SBrian Somers #include "hdlc.h" 616140ba11SBrian Somers #include "async.h" 623b0f8d2eSBrian Somers #include "ccp.h" 638c07a7b2SBrian Somers #include "link.h" 6463b73463SBrian Somers #include "physical.h" 653b0f8d2eSBrian Somers #include "mp.h" 663b0f8d2eSBrian Somers #include "bundle.h" 67455aabc3SBrian Somers #include "id.h" 68455aabc3SBrian Somers #include "arp.h" 69455aabc3SBrian Somers #include "systems.h" 7085b542cfSBrian Somers #include "prompt.h" 711ae349f5Scvs2svn 72503a7782SBrian Somers #undef REJECTED 73503a7782SBrian Somers #define REJECTED(p, x) ((p)->peer_reject & (1<<(x))) 743edeb0c6SBrian Somers #define issep(ch) ((ch) == ' ' || (ch) == '\t') 753edeb0c6SBrian Somers #define isip(ch) (((ch) >= '0' && (ch) <= '9') || (ch) == '.') 76503a7782SBrian Somers 7729e275ceSBrian Somers struct compreq { 7829e275ceSBrian Somers u_short proto; 7929e275ceSBrian Somers u_char slots; 8029e275ceSBrian Somers u_char compcid; 8129e275ceSBrian Somers }; 821ae349f5Scvs2svn 831ae349f5Scvs2svn static void IpcpLayerUp(struct fsm *); 841ae349f5Scvs2svn static void IpcpLayerDown(struct fsm *); 857308ec68SBrian Somers static void IpcpLayerStart(struct fsm *); 867308ec68SBrian Somers static void IpcpLayerFinish(struct fsm *); 871ae349f5Scvs2svn static void IpcpInitRestartCounter(struct fsm *); 887308ec68SBrian Somers static void IpcpSendConfigReq(struct fsm *); 892267893fSBrian Somers static void IpcpSentTerminateReq(struct fsm *); 902267893fSBrian Somers static void IpcpSendTerminateAck(struct fsm *, u_char); 9130c2f2ffSBrian Somers static void IpcpDecodeConfig(struct fsm *, u_char *, int, int, 9230c2f2ffSBrian Somers struct fsm_decode *); 9383d1af55SBrian Somers 9483d1af55SBrian Somers static struct fsm_callbacks ipcp_Callbacks = { 9583d1af55SBrian Somers IpcpLayerUp, 9683d1af55SBrian Somers IpcpLayerDown, 9783d1af55SBrian Somers IpcpLayerStart, 986d666775SBrian Somers IpcpLayerFinish, 9983d1af55SBrian Somers IpcpInitRestartCounter, 10083d1af55SBrian Somers IpcpSendConfigReq, 1012267893fSBrian Somers IpcpSentTerminateReq, 10283d1af55SBrian Somers IpcpSendTerminateAck, 10383d1af55SBrian Somers IpcpDecodeConfig, 104503a7782SBrian Somers NullRecvResetReq, 105503a7782SBrian Somers NullRecvResetAck 10683d1af55SBrian Somers }; 1071ae349f5Scvs2svn 1081ae349f5Scvs2svn static const char *cftypes[] = { 1091ae349f5Scvs2svn /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */ 1101ae349f5Scvs2svn "???", 1111ae349f5Scvs2svn "IPADDRS", /* 1: IP-Addresses */ /* deprecated */ 1121ae349f5Scvs2svn "COMPPROTO", /* 2: IP-Compression-Protocol */ 1131ae349f5Scvs2svn "IPADDR", /* 3: IP-Address */ 1141ae349f5Scvs2svn }; 1151ae349f5Scvs2svn 1161ae349f5Scvs2svn #define NCFTYPES (sizeof cftypes/sizeof cftypes[0]) 1171ae349f5Scvs2svn 1181ae349f5Scvs2svn static const char *cftypes128[] = { 1191ae349f5Scvs2svn /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */ 1201ae349f5Scvs2svn "???", 1211ae349f5Scvs2svn "PRIDNS", /* 129: Primary DNS Server Address */ 1221ae349f5Scvs2svn "PRINBNS", /* 130: Primary NBNS Server Address */ 1231ae349f5Scvs2svn "SECDNS", /* 131: Secondary DNS Server Address */ 1241ae349f5Scvs2svn "SECNBNS", /* 132: Secondary NBNS Server Address */ 1251ae349f5Scvs2svn }; 1261ae349f5Scvs2svn 1271ae349f5Scvs2svn #define NCFTYPES128 (sizeof cftypes128/sizeof cftypes128[0]) 1281ae349f5Scvs2svn 1291ae349f5Scvs2svn void 1305828db6dSBrian Somers ipcp_AddInOctets(struct ipcp *ipcp, int n) 1311ae349f5Scvs2svn { 1325828db6dSBrian Somers throughput_addin(&ipcp->throughput, n); 1331ae349f5Scvs2svn } 1341ae349f5Scvs2svn 1351ae349f5Scvs2svn void 1365828db6dSBrian Somers ipcp_AddOutOctets(struct ipcp *ipcp, int n) 1371ae349f5Scvs2svn { 1385828db6dSBrian Somers throughput_addout(&ipcp->throughput, n); 1391ae349f5Scvs2svn } 1401ae349f5Scvs2svn 1413edeb0c6SBrian Somers static void 1423edeb0c6SBrian Somers getdns(struct ipcp *ipcp, struct in_addr addr[2]) 1433edeb0c6SBrian Somers { 1443edeb0c6SBrian Somers FILE *fp; 1453edeb0c6SBrian Somers 1463edeb0c6SBrian Somers addr[0].s_addr = addr[1].s_addr = INADDR_ANY; 1473edeb0c6SBrian Somers if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { 1483edeb0c6SBrian Somers char buf[LINE_LEN], *cp, *end; 1493edeb0c6SBrian Somers int n; 1503edeb0c6SBrian Somers 1513edeb0c6SBrian Somers n = 0; 1523edeb0c6SBrian Somers buf[sizeof buf - 1] = '\0'; 1533edeb0c6SBrian Somers while (fgets(buf, sizeof buf - 1, fp)) { 1543edeb0c6SBrian Somers if (!strncmp(buf, "nameserver", 10) && issep(buf[10])) { 1553edeb0c6SBrian Somers for (cp = buf + 11; issep(*cp); cp++) 1563edeb0c6SBrian Somers ; 1573edeb0c6SBrian Somers for (end = cp; isip(*end); end++) 1583edeb0c6SBrian Somers ; 1593edeb0c6SBrian Somers *end = '\0'; 1603edeb0c6SBrian Somers if (inet_aton(cp, addr+n) && ++n == 2) 1613edeb0c6SBrian Somers break; 1623edeb0c6SBrian Somers } 1633edeb0c6SBrian Somers } 1643edeb0c6SBrian Somers if (n == 1) 1653edeb0c6SBrian Somers addr[1] = addr[0]; 1663edeb0c6SBrian Somers fclose(fp); 1673edeb0c6SBrian Somers } 1683edeb0c6SBrian Somers } 1693edeb0c6SBrian Somers 1703edeb0c6SBrian Somers static int 1713edeb0c6SBrian Somers setdns(struct ipcp *ipcp, struct in_addr addr[2]) 1723edeb0c6SBrian Somers { 1733edeb0c6SBrian Somers FILE *fp; 1743edeb0c6SBrian Somers char wbuf[LINE_LEN + 54]; 1753edeb0c6SBrian Somers int wlen; 1763edeb0c6SBrian Somers 1773edeb0c6SBrian Somers if (addr[0].s_addr == INADDR_ANY || addr[1].s_addr == INADDR_ANY) { 1783edeb0c6SBrian Somers struct in_addr old[2]; 1793edeb0c6SBrian Somers 1803edeb0c6SBrian Somers getdns(ipcp, old); 1813edeb0c6SBrian Somers if (addr[0].s_addr == INADDR_ANY) 1823edeb0c6SBrian Somers addr[0] = old[0]; 1833edeb0c6SBrian Somers if (addr[1].s_addr == INADDR_ANY) 1843edeb0c6SBrian Somers addr[1] = old[1]; 1853edeb0c6SBrian Somers } 1863edeb0c6SBrian Somers 1873edeb0c6SBrian Somers if (addr[0].s_addr == INADDR_ANY && addr[1].s_addr == INADDR_ANY) { 1883edeb0c6SBrian Somers LogPrintf(LogWARN, "%s not modified: All nameservers NAKd\n", 1893edeb0c6SBrian Somers _PATH_RESCONF); 1903edeb0c6SBrian Somers return 0; 1913edeb0c6SBrian Somers } 1923edeb0c6SBrian Somers 1933edeb0c6SBrian Somers wlen = 0; 1943edeb0c6SBrian Somers if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { 1953edeb0c6SBrian Somers char buf[LINE_LEN]; 1963edeb0c6SBrian Somers int len; 1973edeb0c6SBrian Somers 1983edeb0c6SBrian Somers buf[sizeof buf - 1] = '\0'; 1993edeb0c6SBrian Somers while (fgets(buf, sizeof buf - 1, fp)) { 2003edeb0c6SBrian Somers if (strncmp(buf, "nameserver", 10) || !issep(buf[10])) { 2013edeb0c6SBrian Somers len = strlen(buf); 2023edeb0c6SBrian Somers if (len > sizeof wbuf - wlen) { 2033edeb0c6SBrian Somers LogPrintf(LogWARN, "%s: Can only cope with max file size %d\n", 2043edeb0c6SBrian Somers _PATH_RESCONF, LINE_LEN); 2053edeb0c6SBrian Somers fclose(fp); 2063edeb0c6SBrian Somers return 0; 2073edeb0c6SBrian Somers } 2083edeb0c6SBrian Somers memcpy(wbuf + wlen, buf, len); 2093edeb0c6SBrian Somers wlen += len; 2103edeb0c6SBrian Somers } 2113edeb0c6SBrian Somers } 2123edeb0c6SBrian Somers fclose(fp); 2133edeb0c6SBrian Somers } 2143edeb0c6SBrian Somers 2153edeb0c6SBrian Somers if (addr[0].s_addr != INADDR_ANY) { 2163edeb0c6SBrian Somers snprintf(wbuf + wlen, sizeof wbuf - wlen, "nameserver %s\n", 2173edeb0c6SBrian Somers inet_ntoa(addr[0])); 2183edeb0c6SBrian Somers LogPrintf(LogIPCP, "Primary nameserver set to %s", wbuf + wlen + 11); 2193edeb0c6SBrian Somers wlen += strlen(wbuf + wlen); 2203edeb0c6SBrian Somers } 2213edeb0c6SBrian Somers 2223edeb0c6SBrian Somers if (addr[1].s_addr != INADDR_ANY && addr[1].s_addr != addr[0].s_addr) { 2233edeb0c6SBrian Somers snprintf(wbuf + wlen, sizeof wbuf - wlen, "nameserver %s\n", 2243edeb0c6SBrian Somers inet_ntoa(addr[1])); 2253edeb0c6SBrian Somers LogPrintf(LogIPCP, "Secondary nameserver set to %s", wbuf + wlen + 11); 2263edeb0c6SBrian Somers wlen += strlen(wbuf + wlen); 2273edeb0c6SBrian Somers } 2283edeb0c6SBrian Somers 2293edeb0c6SBrian Somers if (wlen) { 2303edeb0c6SBrian Somers int fd; 2313edeb0c6SBrian Somers 2323edeb0c6SBrian Somers if ((fd = ID0open(_PATH_RESCONF, O_WRONLY|O_CREAT, 0644)) != -1) { 2333edeb0c6SBrian Somers if (write(fd, wbuf, wlen) != wlen) { 2343edeb0c6SBrian Somers LogPrintf(LogERROR, "setdns: write(): %s\n", strerror(errno)); 2353edeb0c6SBrian Somers close(fd); 2363edeb0c6SBrian Somers return 0; 2373edeb0c6SBrian Somers } 2383edeb0c6SBrian Somers if (ftruncate(fd, wlen) == -1) { 2393edeb0c6SBrian Somers LogPrintf(LogERROR, "setdns: truncate(): %s\n", strerror(errno)); 2403edeb0c6SBrian Somers close(fd); 2413edeb0c6SBrian Somers return 0; 2423edeb0c6SBrian Somers } 2433edeb0c6SBrian Somers close(fd); 2443edeb0c6SBrian Somers } else { 2453edeb0c6SBrian Somers LogPrintf(LogERROR, "setdns: open(): %s\n", strerror(errno)); 2463edeb0c6SBrian Somers return 0; 2473edeb0c6SBrian Somers } 2483edeb0c6SBrian Somers } 2493edeb0c6SBrian Somers 2503edeb0c6SBrian Somers return 1; 2513edeb0c6SBrian Somers } 2523edeb0c6SBrian Somers 2531ae349f5Scvs2svn int 2541ae349f5Scvs2svn ReportIpcpStatus(struct cmdargs const *arg) 2551ae349f5Scvs2svn { 256b6217683SBrian Somers prompt_Printf(arg->prompt, "%s [%s]\n", arg->bundle->ncp.ipcp.fsm.name, 2571e991daaSBrian Somers State2Nam(arg->bundle->ncp.ipcp.fsm.state)); 2585828db6dSBrian Somers if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) { 259b6217683SBrian Somers prompt_Printf(arg->prompt, " His side: %s, %s\n", 2605828db6dSBrian Somers inet_ntoa(arg->bundle->ncp.ipcp.peer_ip), 2615828db6dSBrian Somers vj2asc(arg->bundle->ncp.ipcp.peer_compproto)); 262b6217683SBrian Somers prompt_Printf(arg->prompt, " My side: %s, %s\n", 2635828db6dSBrian Somers inet_ntoa(arg->bundle->ncp.ipcp.my_ip), 2645828db6dSBrian Somers vj2asc(arg->bundle->ncp.ipcp.my_compproto)); 2651ae349f5Scvs2svn } 2661ae349f5Scvs2svn 267b6217683SBrian Somers prompt_Printf(arg->prompt, "\nDefaults:\n"); 26850abd4c8SBrian Somers prompt_Printf(arg->prompt, " My Address: %s/%d", 2695828db6dSBrian Somers inet_ntoa(arg->bundle->ncp.ipcp.cfg.my_range.ipaddr), 2705828db6dSBrian Somers arg->bundle->ncp.ipcp.cfg.my_range.width); 27150abd4c8SBrian Somers 27250abd4c8SBrian Somers if (arg->bundle->ncp.ipcp.cfg.HaveTriggerAddress) 27350abd4c8SBrian Somers prompt_Printf(arg->prompt, " (trigger with %s)", 27450abd4c8SBrian Somers inet_ntoa(arg->bundle->ncp.ipcp.cfg.TriggerAddress)); 27550abd4c8SBrian Somers prompt_Printf(arg->prompt, "\n VJ compression: %s (%d slots %s slot " 27650abd4c8SBrian Somers "compression)\n", 27750abd4c8SBrian Somers command_ShowNegval(arg->bundle->ncp.ipcp.cfg.vj.neg), 27850abd4c8SBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slots, 27950abd4c8SBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slotcomp ? "with" : "without"); 28050abd4c8SBrian Somers 2815828db6dSBrian Somers if (iplist_isvalid(&arg->bundle->ncp.ipcp.cfg.peer_list)) 282b6217683SBrian Somers prompt_Printf(arg->prompt, " His Address: %s\n", 2835828db6dSBrian Somers arg->bundle->ncp.ipcp.cfg.peer_list.src); 2841ae349f5Scvs2svn else 285b6217683SBrian Somers prompt_Printf(arg->prompt, " His Address: %s/%d\n", 2865828db6dSBrian Somers inet_ntoa(arg->bundle->ncp.ipcp.cfg.peer_range.ipaddr), 2875828db6dSBrian Somers arg->bundle->ncp.ipcp.cfg.peer_range.width); 28850abd4c8SBrian Somers 2893edeb0c6SBrian Somers prompt_Printf(arg->prompt, " DNS: %s, ", 2903edeb0c6SBrian Somers inet_ntoa(arg->bundle->ncp.ipcp.cfg.ns.dns[0])); 29150abd4c8SBrian Somers prompt_Printf(arg->prompt, "%s, %s\n", 29250abd4c8SBrian Somers inet_ntoa(arg->bundle->ncp.ipcp.cfg.ns.dns[1]), 29350abd4c8SBrian Somers command_ShowNegval(arg->bundle->ncp.ipcp.cfg.ns.dns_neg)); 2943edeb0c6SBrian Somers prompt_Printf(arg->prompt, " NetBIOS NS: %s, ", 2953edeb0c6SBrian Somers inet_ntoa(arg->bundle->ncp.ipcp.cfg.ns.nbns[0])); 2963edeb0c6SBrian Somers prompt_Printf(arg->prompt, "%s\n", 2973edeb0c6SBrian Somers inet_ntoa(arg->bundle->ncp.ipcp.cfg.ns.nbns[1])); 2981342caedSBrian Somers 299b6217683SBrian Somers prompt_Printf(arg->prompt, "\n"); 300b6217683SBrian Somers throughput_disp(&arg->bundle->ncp.ipcp.throughput, arg->prompt); 3011ae349f5Scvs2svn 3021ae349f5Scvs2svn return 0; 3031ae349f5Scvs2svn } 3041ae349f5Scvs2svn 3051ae349f5Scvs2svn int 3065828db6dSBrian Somers SetInitVJ(struct cmdargs const *arg) 3071ae349f5Scvs2svn { 30825092092SBrian Somers if (arg->argc != arg->argn+2) 3091ae349f5Scvs2svn return -1; 31025092092SBrian Somers if (!strcasecmp(arg->argv[arg->argn], "slots")) { 3111ae349f5Scvs2svn int slots; 3121ae349f5Scvs2svn 31325092092SBrian Somers slots = atoi(arg->argv[arg->argn+1]); 3141ae349f5Scvs2svn if (slots < 4 || slots > 16) 3151ae349f5Scvs2svn return 1; 3161342caedSBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slots = slots; 3171ae349f5Scvs2svn return 0; 31825092092SBrian Somers } else if (!strcasecmp(arg->argv[arg->argn], "slotcomp")) { 31925092092SBrian Somers if (!strcasecmp(arg->argv[arg->argn+1], "on")) 3201342caedSBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 1; 32125092092SBrian Somers else if (!strcasecmp(arg->argv[arg->argn+1], "off")) 3221342caedSBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 0; 3231ae349f5Scvs2svn else 3241ae349f5Scvs2svn return 2; 3251ae349f5Scvs2svn return 0; 3261ae349f5Scvs2svn } 3271ae349f5Scvs2svn return -1; 3281ae349f5Scvs2svn } 3291ae349f5Scvs2svn 3301ae349f5Scvs2svn void 3316d666775SBrian Somers ipcp_Init(struct ipcp *ipcp, struct bundle *bundle, struct link *l, 3326d666775SBrian Somers const struct fsm_parent *parent) 3331ae349f5Scvs2svn { 334503a7782SBrian Somers struct hostent *hp; 335503a7782SBrian Somers char name[MAXHOSTNAMELEN]; 3363b0f8d2eSBrian Somers static const char *timer_names[] = 3373b0f8d2eSBrian Somers {"IPCP restart", "IPCP openmode", "IPCP stopped"}; 33829e275ceSBrian Somers 3393b0f8d2eSBrian Somers fsm_Init(&ipcp->fsm, "IPCP", PROTO_IPCP, 1, IPCP_MAXCODE, 10, LogIPCP, 3403b0f8d2eSBrian Somers bundle, l, parent, &ipcp_Callbacks, timer_names); 341503a7782SBrian Somers 3421342caedSBrian Somers ipcp->cfg.vj.slots = DEF_VJ_STATES; 3431342caedSBrian Somers ipcp->cfg.vj.slotcomp = 1; 344503a7782SBrian Somers memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range); 345503a7782SBrian Somers if (gethostname(name, sizeof name) == 0) { 346503a7782SBrian Somers hp = gethostbyname(name); 347503a7782SBrian Somers if (hp && hp->h_addrtype == AF_INET) { 348503a7782SBrian Somers memcpy(&ipcp->cfg.my_range.ipaddr.s_addr, hp->h_addr, hp->h_length); 349503a7782SBrian Somers ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 350503a7782SBrian Somers ipcp->cfg.peer_range.width = 32; 3511ae349f5Scvs2svn } 352503a7782SBrian Somers } 35330c2f2ffSBrian Somers ipcp->cfg.netmask.s_addr = INADDR_ANY; 354503a7782SBrian Somers memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 355503a7782SBrian Somers iplist_setsrc(&ipcp->cfg.peer_list, ""); 356503a7782SBrian Somers ipcp->cfg.HaveTriggerAddress = 0; 357503a7782SBrian Somers 3583edeb0c6SBrian Somers ipcp->cfg.ns.dns[0].s_addr = INADDR_ANY; 3593edeb0c6SBrian Somers ipcp->cfg.ns.dns[1].s_addr = INADDR_ANY; 3603edeb0c6SBrian Somers ipcp->cfg.ns.dns_neg = 0; 3613edeb0c6SBrian Somers ipcp->cfg.ns.nbns[0].s_addr = INADDR_ANY; 3623edeb0c6SBrian Somers ipcp->cfg.ns.nbns[1].s_addr = INADDR_ANY; 363cd9647a1SBrian Somers 364cd9647a1SBrian Somers ipcp->cfg.fsmretry = DEF_FSMRETRY; 3651342caedSBrian Somers ipcp->cfg.vj.neg = NEG_ENABLED|NEG_ACCEPTED; 366503a7782SBrian Somers 367eaa4df37SBrian Somers memset(&ipcp->vj, '\0', sizeof ipcp->vj); 368eaa4df37SBrian Somers 369503a7782SBrian Somers ipcp->my_ifip.s_addr = INADDR_ANY; 370503a7782SBrian Somers ipcp->peer_ifip.s_addr = INADDR_ANY; 371503a7782SBrian Somers 372fdf61171SBrian Somers throughput_init(&ipcp->throughput); 373503a7782SBrian Somers ipcp_Setup(ipcp); 374503a7782SBrian Somers } 375503a7782SBrian Somers 376503a7782SBrian Somers void 377ce828a6eSBrian Somers ipcp_SetLink(struct ipcp *ipcp, struct link *l) 378ce828a6eSBrian Somers { 379ce828a6eSBrian Somers ipcp->fsm.link = l; 380ce828a6eSBrian Somers } 381ce828a6eSBrian Somers 382ce828a6eSBrian Somers void 383503a7782SBrian Somers ipcp_Setup(struct ipcp *ipcp) 384503a7782SBrian Somers { 385503a7782SBrian Somers int pos; 386503a7782SBrian Somers 387503a7782SBrian Somers ipcp->fsm.open_mode = 0; 3885454ccd9SBrian Somers ipcp->fsm.maxconfig = 10; 389503a7782SBrian Somers 390503a7782SBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 391503a7782SBrian Somers if (ipcp->my_ifip.s_addr != INADDR_ANY && 392503a7782SBrian Somers (pos = iplist_ip2pos(&ipcp->cfg.peer_list, ipcp->my_ifip)) != -1) 393503a7782SBrian Somers ipcp->cfg.peer_range.ipaddr = iplist_setcurpos(&ipcp->cfg.peer_list, pos); 394503a7782SBrian Somers else 395503a7782SBrian Somers ipcp->cfg.peer_range.ipaddr = iplist_setrandpos(&ipcp->cfg.peer_list); 396503a7782SBrian Somers ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 397503a7782SBrian Somers ipcp->cfg.peer_range.width = 32; 398503a7782SBrian Somers } 399503a7782SBrian Somers 400503a7782SBrian Somers ipcp->heis1172 = 0; 401503a7782SBrian Somers 402503a7782SBrian Somers ipcp->peer_ip = ipcp->cfg.peer_range.ipaddr; 403503a7782SBrian Somers ipcp->peer_compproto = 0; 4041ae349f5Scvs2svn 4058390b576SBrian Somers if (ipcp->cfg.HaveTriggerAddress) { 4061ae349f5Scvs2svn /* 4071ae349f5Scvs2svn * Some implementations of PPP require that we send a 4081ae349f5Scvs2svn * *special* value as our address, even though the rfc specifies 4091ae349f5Scvs2svn * full negotiation (e.g. "0.0.0.0" or Not "0.0.0.0"). 4101ae349f5Scvs2svn */ 411503a7782SBrian Somers ipcp->my_ip = ipcp->cfg.TriggerAddress; 41229e275ceSBrian Somers LogPrintf(LogIPCP, "Using trigger address %s\n", 413503a7782SBrian Somers inet_ntoa(ipcp->cfg.TriggerAddress)); 4148390b576SBrian Somers } else if ((ipcp->my_ifip.s_addr & ipcp->cfg.my_range.mask.s_addr) == 4158390b576SBrian Somers (ipcp->cfg.my_range.ipaddr.s_addr & 4168390b576SBrian Somers ipcp->cfg.my_range.mask.s_addr)) 4178390b576SBrian Somers /* 4188390b576SBrian Somers * Otherwise, if we've been assigned an IP number before, we really 4198390b576SBrian Somers * want to keep the same IP number so that we can keep any existing 4208390b576SBrian Somers * connections that are bound to that IP. 4218390b576SBrian Somers */ 4228390b576SBrian Somers ipcp->my_ip = ipcp->my_ifip; 4238390b576SBrian Somers else 424503a7782SBrian Somers ipcp->my_ip = ipcp->cfg.my_range.ipaddr; 42529e275ceSBrian Somers 4261342caedSBrian Somers if (IsEnabled(ipcp->cfg.vj.neg)) 427503a7782SBrian Somers ipcp->my_compproto = (PROTO_VJCOMP << 16) + 4281342caedSBrian Somers ((ipcp->cfg.vj.slots - 1) << 8) + 4291342caedSBrian Somers ipcp->cfg.vj.slotcomp; 4301ae349f5Scvs2svn else 431503a7782SBrian Somers ipcp->my_compproto = 0; 4321342caedSBrian Somers sl_compress_init(&ipcp->vj.cslc, ipcp->cfg.vj.slots - 1); 43329e275ceSBrian Somers 434503a7782SBrian Somers ipcp->peer_reject = 0; 435503a7782SBrian Somers ipcp->my_reject = 0; 436503a7782SBrian Somers 437fdf61171SBrian Somers throughput_stop(&ipcp->throughput); 438503a7782SBrian Somers throughput_init(&ipcp->throughput); 4391ae349f5Scvs2svn } 4401ae349f5Scvs2svn 441455aabc3SBrian Somers static int 44230c2f2ffSBrian Somers ipcp_SetIPaddress(struct bundle *bundle, struct in_addr myaddr, 44330c2f2ffSBrian Somers struct in_addr hisaddr, int silent) 444455aabc3SBrian Somers { 445455aabc3SBrian Somers struct sockaddr_in *sock_in; 446455aabc3SBrian Somers int s; 447455aabc3SBrian Somers u_long mask, addr; 448455aabc3SBrian Somers struct ifaliasreq ifra; 449455aabc3SBrian Somers 450455aabc3SBrian Somers /* If given addresses are alreay set, then ignore this request */ 45130c2f2ffSBrian Somers if (bundle->ncp.ipcp.my_ifip.s_addr == myaddr.s_addr && 45230c2f2ffSBrian Somers bundle->ncp.ipcp.peer_ifip.s_addr == hisaddr.s_addr) 453455aabc3SBrian Somers return 0; 454455aabc3SBrian Somers 455565e35e5SBrian Somers IpcpCleanInterface(&bundle->ncp.ipcp); 45668a0f0ccSBrian Somers 457455aabc3SBrian Somers s = ID0socket(AF_INET, SOCK_DGRAM, 0); 458455aabc3SBrian Somers if (s < 0) { 459455aabc3SBrian Somers LogPrintf(LogERROR, "SetIpDevice: socket(): %s\n", strerror(errno)); 460455aabc3SBrian Somers return (-1); 461455aabc3SBrian Somers } 462455aabc3SBrian Somers 463455aabc3SBrian Somers memset(&ifra, '\0', sizeof ifra); 464455aabc3SBrian Somers strncpy(ifra.ifra_name, bundle->ifname, sizeof ifra.ifra_name - 1); 465455aabc3SBrian Somers ifra.ifra_name[sizeof ifra.ifra_name - 1] = '\0'; 466455aabc3SBrian Somers 467455aabc3SBrian Somers /* Set interface address */ 468455aabc3SBrian Somers sock_in = (struct sockaddr_in *)&ifra.ifra_addr; 469455aabc3SBrian Somers sock_in->sin_family = AF_INET; 470455aabc3SBrian Somers sock_in->sin_addr = myaddr; 471455aabc3SBrian Somers sock_in->sin_len = sizeof *sock_in; 472455aabc3SBrian Somers 473455aabc3SBrian Somers /* Set destination address */ 474455aabc3SBrian Somers sock_in = (struct sockaddr_in *)&ifra.ifra_broadaddr; 475455aabc3SBrian Somers sock_in->sin_family = AF_INET; 476455aabc3SBrian Somers sock_in->sin_addr = hisaddr; 477455aabc3SBrian Somers sock_in->sin_len = sizeof *sock_in; 478455aabc3SBrian Somers 479455aabc3SBrian Somers addr = ntohl(myaddr.s_addr); 480455aabc3SBrian Somers if (IN_CLASSA(addr)) 481455aabc3SBrian Somers mask = IN_CLASSA_NET; 482455aabc3SBrian Somers else if (IN_CLASSB(addr)) 483455aabc3SBrian Somers mask = IN_CLASSB_NET; 484455aabc3SBrian Somers else 485455aabc3SBrian Somers mask = IN_CLASSC_NET; 486455aabc3SBrian Somers 487455aabc3SBrian Somers /* if subnet mask is given, use it instead of class mask */ 48830c2f2ffSBrian Somers if (bundle->ncp.ipcp.cfg.netmask.s_addr != INADDR_ANY && 48930c2f2ffSBrian Somers (ntohl(bundle->ncp.ipcp.cfg.netmask.s_addr) & mask) == mask) 49030c2f2ffSBrian Somers mask = ntohl(bundle->ncp.ipcp.cfg.netmask.s_addr); 491455aabc3SBrian Somers 492455aabc3SBrian Somers sock_in = (struct sockaddr_in *)&ifra.ifra_mask; 493455aabc3SBrian Somers sock_in->sin_family = AF_INET; 494455aabc3SBrian Somers sock_in->sin_addr.s_addr = htonl(mask); 495455aabc3SBrian Somers sock_in->sin_len = sizeof *sock_in; 496455aabc3SBrian Somers 497455aabc3SBrian Somers if (ID0ioctl(s, SIOCAIFADDR, &ifra) < 0) { 498455aabc3SBrian Somers if (!silent) 499455aabc3SBrian Somers LogPrintf(LogERROR, "SetIpDevice: ioctl(SIOCAIFADDR): %s\n", 500455aabc3SBrian Somers strerror(errno)); 501455aabc3SBrian Somers close(s); 502455aabc3SBrian Somers return (-1); 503455aabc3SBrian Somers } 504455aabc3SBrian Somers 50530c2f2ffSBrian Somers bundle->ncp.ipcp.peer_ifip.s_addr = hisaddr.s_addr; 50630c2f2ffSBrian Somers bundle->ncp.ipcp.my_ifip.s_addr = myaddr.s_addr; 507455aabc3SBrian Somers 5081342caedSBrian Somers if (Enabled(bundle, OPT_PROXY)) 50930c2f2ffSBrian Somers sifproxyarp(bundle, bundle->ncp.ipcp.peer_ifip, s); 510455aabc3SBrian Somers 511455aabc3SBrian Somers close(s); 512455aabc3SBrian Somers return (0); 513455aabc3SBrian Somers } 514455aabc3SBrian Somers 515455aabc3SBrian Somers static struct in_addr 51630c2f2ffSBrian Somers ChooseHisAddr(struct bundle *bundle, const struct in_addr gw) 517455aabc3SBrian Somers { 518455aabc3SBrian Somers struct in_addr try; 519455aabc3SBrian Somers int f; 520455aabc3SBrian Somers 5215828db6dSBrian Somers for (f = 0; f < bundle->ncp.ipcp.cfg.peer_list.nItems; f++) { 5225828db6dSBrian Somers try = iplist_next(&bundle->ncp.ipcp.cfg.peer_list); 523455aabc3SBrian Somers LogPrintf(LogDEBUG, "ChooseHisAddr: Check item %d (%s)\n", 524455aabc3SBrian Somers f, inet_ntoa(try)); 52530c2f2ffSBrian Somers if (ipcp_SetIPaddress(bundle, gw, try, 1) == 0) { 526d47dceb8SBrian Somers LogPrintf(LogIPCP, "Selected IP address %s\n", inet_ntoa(try)); 527455aabc3SBrian Somers break; 528455aabc3SBrian Somers } 529455aabc3SBrian Somers } 530455aabc3SBrian Somers 5315828db6dSBrian Somers if (f == bundle->ncp.ipcp.cfg.peer_list.nItems) { 532455aabc3SBrian Somers LogPrintf(LogDEBUG, "ChooseHisAddr: All addresses in use !\n"); 533455aabc3SBrian Somers try.s_addr = INADDR_ANY; 534455aabc3SBrian Somers } 535455aabc3SBrian Somers 536455aabc3SBrian Somers return try; 537455aabc3SBrian Somers } 538455aabc3SBrian Somers 5391ae349f5Scvs2svn static void 5401ae349f5Scvs2svn IpcpInitRestartCounter(struct fsm * fp) 5411ae349f5Scvs2svn { 5427308ec68SBrian Somers /* Set fsm timer load */ 543cd9647a1SBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 544cd9647a1SBrian Somers 545cd9647a1SBrian Somers fp->FsmTimer.load = ipcp->cfg.fsmretry * SECTICKS; 5461ae349f5Scvs2svn fp->restart = 5; 5471ae349f5Scvs2svn } 5481ae349f5Scvs2svn 5491ae349f5Scvs2svn static void 5501ae349f5Scvs2svn IpcpSendConfigReq(struct fsm *fp) 5511ae349f5Scvs2svn { 5527308ec68SBrian Somers /* Send config REQ please */ 5538c07a7b2SBrian Somers struct physical *p = link2physical(fp->link); 554aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 5553edeb0c6SBrian Somers u_char buff[24]; 5562267893fSBrian Somers struct lcp_opt *o; 5571ae349f5Scvs2svn 5582267893fSBrian Somers o = (struct lcp_opt *)buff; 55930c2f2ffSBrian Somers 56083d1af55SBrian Somers if ((p && !Physical_IsSync(p)) || !REJECTED(ipcp, TY_IPADDR)) { 5612267893fSBrian Somers *(u_int32_t *)o->data = ipcp->my_ip.s_addr; 5622267893fSBrian Somers INC_LCP_OPT(TY_IPADDR, 6, o); 5631ae349f5Scvs2svn } 5641ae349f5Scvs2svn 565e43ebac1SBrian Somers if (ipcp->my_compproto && !REJECTED(ipcp, TY_COMPPROTO)) { 56683d1af55SBrian Somers if (ipcp->heis1172) { 5672267893fSBrian Somers *(u_short *)o->data = htons(PROTO_VJCOMP); 5682267893fSBrian Somers INC_LCP_OPT(TY_COMPPROTO, 4, o); 5691ae349f5Scvs2svn } else { 5702267893fSBrian Somers *(u_long *)o->data = htonl(ipcp->my_compproto); 5712267893fSBrian Somers INC_LCP_OPT(TY_COMPPROTO, 6, o); 5721ae349f5Scvs2svn } 573e43ebac1SBrian Somers } 5742267893fSBrian Somers 5753edeb0c6SBrian Somers if (IsEnabled(ipcp->cfg.ns.dns_neg) && 5763edeb0c6SBrian Somers !REJECTED(ipcp, TY_PRIMARY_DNS - TY_ADJUST_NS) && 5773edeb0c6SBrian Somers !REJECTED(ipcp, TY_SECONDARY_DNS - TY_ADJUST_NS)) { 5783edeb0c6SBrian Somers struct in_addr dns[2]; 5793edeb0c6SBrian Somers getdns(ipcp, dns); 5803edeb0c6SBrian Somers *(u_int32_t *)o->data = dns[0].s_addr; 5813edeb0c6SBrian Somers INC_LCP_OPT(TY_PRIMARY_DNS, 6, o); 5823edeb0c6SBrian Somers *(u_int32_t *)o->data = dns[1].s_addr; 5833edeb0c6SBrian Somers INC_LCP_OPT(TY_SECONDARY_DNS, 6, o); 5843edeb0c6SBrian Somers } 5853edeb0c6SBrian Somers 5862267893fSBrian Somers FsmOutput(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff); 5871ae349f5Scvs2svn } 5881ae349f5Scvs2svn 5891ae349f5Scvs2svn static void 5902267893fSBrian Somers IpcpSentTerminateReq(struct fsm * fp) 5911ae349f5Scvs2svn { 5927308ec68SBrian Somers /* Term REQ just sent by FSM */ 5931ae349f5Scvs2svn } 5941ae349f5Scvs2svn 5951ae349f5Scvs2svn static void 5962267893fSBrian Somers IpcpSendTerminateAck(struct fsm *fp, u_char id) 5971ae349f5Scvs2svn { 5987308ec68SBrian Somers /* Send Term ACK please */ 5992267893fSBrian Somers FsmOutput(fp, CODE_TERMACK, id, NULL, 0); 6001ae349f5Scvs2svn } 6011ae349f5Scvs2svn 6021ae349f5Scvs2svn static void 6031ae349f5Scvs2svn IpcpLayerStart(struct fsm * fp) 6041ae349f5Scvs2svn { 6057308ec68SBrian Somers /* We're about to start up ! */ 606d47dceb8SBrian Somers LogPrintf(LogIPCP, "%s: IpcpLayerStart.\n", fp->link->name); 607455aabc3SBrian Somers 608565e35e5SBrian Somers /* This is where we should be setting up the interface in DEMAND mode */ 6091ae349f5Scvs2svn } 6101ae349f5Scvs2svn 6111ae349f5Scvs2svn static void 6121ae349f5Scvs2svn IpcpLayerFinish(struct fsm *fp) 6131ae349f5Scvs2svn { 6147308ec68SBrian Somers /* We're now down */ 615d47dceb8SBrian Somers LogPrintf(LogIPCP, "%s: IpcpLayerFinish.\n", fp->link->name); 6161ae349f5Scvs2svn } 6171ae349f5Scvs2svn 61868a0f0ccSBrian Somers void 619565e35e5SBrian Somers IpcpCleanInterface(struct ipcp *ipcp) 62068a0f0ccSBrian Somers { 62168a0f0ccSBrian Somers struct ifaliasreq ifra; 62268a0f0ccSBrian Somers struct sockaddr_in *me, *peer; 62368a0f0ccSBrian Somers int s; 62468a0f0ccSBrian Somers 62568a0f0ccSBrian Somers s = ID0socket(AF_INET, SOCK_DGRAM, 0); 62668a0f0ccSBrian Somers if (s < 0) { 62768a0f0ccSBrian Somers LogPrintf(LogERROR, "IpcpCleanInterface: socket: %s\n", strerror(errno)); 62868a0f0ccSBrian Somers return; 62968a0f0ccSBrian Somers } 63068a0f0ccSBrian Somers 6311342caedSBrian Somers if (Enabled(ipcp->fsm.bundle, OPT_PROXY)) 632565e35e5SBrian Somers cifproxyarp(ipcp->fsm.bundle, ipcp->peer_ifip, s); 63368a0f0ccSBrian Somers 634503a7782SBrian Somers if (ipcp->my_ifip.s_addr != INADDR_ANY || 635503a7782SBrian Somers ipcp->peer_ifip.s_addr != INADDR_ANY) { 63668a0f0ccSBrian Somers memset(&ifra, '\0', sizeof ifra); 637565e35e5SBrian Somers strncpy(ifra.ifra_name, ipcp->fsm.bundle->ifname, 638565e35e5SBrian Somers sizeof ifra.ifra_name - 1); 63968a0f0ccSBrian Somers ifra.ifra_name[sizeof ifra.ifra_name - 1] = '\0'; 64068a0f0ccSBrian Somers me = (struct sockaddr_in *)&ifra.ifra_addr; 64168a0f0ccSBrian Somers peer = (struct sockaddr_in *)&ifra.ifra_broadaddr; 64268a0f0ccSBrian Somers me->sin_family = peer->sin_family = AF_INET; 64368a0f0ccSBrian Somers me->sin_len = peer->sin_len = sizeof(struct sockaddr_in); 644503a7782SBrian Somers me->sin_addr = ipcp->my_ifip; 645503a7782SBrian Somers peer->sin_addr = ipcp->peer_ifip; 64668a0f0ccSBrian Somers if (ID0ioctl(s, SIOCDIFADDR, &ifra) < 0) { 64768a0f0ccSBrian Somers LogPrintf(LogERROR, "IpcpCleanInterface: ioctl(SIOCDIFADDR): %s\n", 64868a0f0ccSBrian Somers strerror(errno)); 64968a0f0ccSBrian Somers close(s); 65068a0f0ccSBrian Somers } 651503a7782SBrian Somers ipcp->my_ifip.s_addr = ipcp->peer_ifip.s_addr = INADDR_ANY; 65268a0f0ccSBrian Somers } 65368a0f0ccSBrian Somers 65468a0f0ccSBrian Somers close(s); 65568a0f0ccSBrian Somers } 65668a0f0ccSBrian Somers 6571ae349f5Scvs2svn static void 6581ae349f5Scvs2svn IpcpLayerDown(struct fsm *fp) 6591ae349f5Scvs2svn { 6607308ec68SBrian Somers /* About to come down */ 661aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 662455aabc3SBrian Somers const char *s; 663455aabc3SBrian Somers 664503a7782SBrian Somers s = inet_ntoa(ipcp->peer_ifip); 665d47dceb8SBrian Somers LogPrintf(LogIPCP, "%s: IpcpLayerDown: %s\n", fp->link->name, s); 666455aabc3SBrian Somers 66783d1af55SBrian Somers throughput_stop(&ipcp->throughput); 66883d1af55SBrian Somers throughput_log(&ipcp->throughput, LogIPCP, NULL); 669455aabc3SBrian Somers /* 670455aabc3SBrian Somers * XXX this stuff should really live in the FSM. Our config should 671455aabc3SBrian Somers * associate executable sections in files with events. 672455aabc3SBrian Somers */ 673e43ebac1SBrian Somers if (SelectSystem(fp->bundle, s, LINKDOWNFILE, NULL) < 0) { 67449052c95SBrian Somers if (bundle_GetLabel(fp->bundle)) { 67549052c95SBrian Somers if (SelectSystem(fp->bundle, bundle_GetLabel(fp->bundle), 67649052c95SBrian Somers LINKDOWNFILE, NULL) < 0) 677b6217683SBrian Somers SelectSystem(fp->bundle, "MYADDR", LINKDOWNFILE, NULL); 678455aabc3SBrian Somers } else 679b6217683SBrian Somers SelectSystem(fp->bundle, "MYADDR", LINKDOWNFILE, NULL); 680e43ebac1SBrian Somers } 681455aabc3SBrian Somers 682ba081e43SBrian Somers if (!(ipcp->fsm.bundle->phys_type & PHYS_DEMAND)) 683565e35e5SBrian Somers IpcpCleanInterface(ipcp); 6841ae349f5Scvs2svn } 6851ae349f5Scvs2svn 6861ae349f5Scvs2svn static void 6871ae349f5Scvs2svn IpcpLayerUp(struct fsm *fp) 6881ae349f5Scvs2svn { 6897308ec68SBrian Somers /* We're now up */ 690aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 6911ae349f5Scvs2svn char tbuff[100]; 6921ae349f5Scvs2svn 693d47dceb8SBrian Somers LogPrintf(LogIPCP, "%s: IpcpLayerUp.\n", fp->link->name); 694503a7782SBrian Somers snprintf(tbuff, sizeof tbuff, "myaddr = %s ", inet_ntoa(ipcp->my_ip)); 695d47dceb8SBrian Somers LogPrintf(LogIPCP, " %s hisaddr = %s\n", tbuff, inet_ntoa(ipcp->peer_ip)); 6961ae349f5Scvs2svn 697503a7782SBrian Somers if (ipcp->peer_compproto >> 16 == PROTO_VJCOMP) 698eaa4df37SBrian Somers sl_compress_init(&ipcp->vj.cslc, (ipcp->peer_compproto >> 8) & 255); 6991ae349f5Scvs2svn 700ba081e43SBrian Somers if (ipcp_SetIPaddress(fp->bundle, ipcp->my_ip, ipcp->peer_ip, 0) < 0) { 7011ae349f5Scvs2svn LogPrintf(LogERROR, "IpcpLayerUp: unable to set ip address\n"); 7021ae349f5Scvs2svn return; 7031ae349f5Scvs2svn } 704455aabc3SBrian Somers 7051ae349f5Scvs2svn #ifndef NOALIAS 70685602e52SBrian Somers if (AliasEnabled()) 7072764b86aSBrian Somers (*PacketAlias.SetAddress)(ipcp->my_ip); 7081ae349f5Scvs2svn #endif 709455aabc3SBrian Somers 710455aabc3SBrian Somers /* 711455aabc3SBrian Somers * XXX this stuff should really live in the FSM. Our config should 712455aabc3SBrian Somers * associate executable sections in files with events. 713455aabc3SBrian Somers */ 714e43ebac1SBrian Somers if (SelectSystem(fp->bundle, inet_ntoa(ipcp->my_ifip), LINKUPFILE, NULL) 715e43ebac1SBrian Somers < 0) { 71649052c95SBrian Somers if (bundle_GetLabel(fp->bundle)) { 71749052c95SBrian Somers if (SelectSystem(fp->bundle, bundle_GetLabel(fp->bundle), 71849052c95SBrian Somers LINKUPFILE, NULL) < 0) 719b6217683SBrian Somers SelectSystem(fp->bundle, "MYADDR", LINKUPFILE, NULL); 720455aabc3SBrian Somers } else 721b6217683SBrian Somers SelectSystem(fp->bundle, "MYADDR", LINKUPFILE, NULL); 722e43ebac1SBrian Somers } 723455aabc3SBrian Somers 7241342caedSBrian Somers throughput_start(&ipcp->throughput, "IPCP throughput", 7251342caedSBrian Somers Enabled(fp->bundle, OPT_THROUGHPUT)); 726b6217683SBrian Somers bundle_DisplayPrompt(fp->bundle); 7271ae349f5Scvs2svn } 7281ae349f5Scvs2svn 7291ae349f5Scvs2svn static int 7301ae349f5Scvs2svn AcceptableAddr(struct in_range *prange, struct in_addr ipaddr) 7311ae349f5Scvs2svn { 7327308ec68SBrian Somers /* Is the given IP in the given range ? */ 7331ae349f5Scvs2svn return (prange->ipaddr.s_addr & prange->mask.s_addr) == 7341ae349f5Scvs2svn (ipaddr.s_addr & prange->mask.s_addr) && ipaddr.s_addr; 7351ae349f5Scvs2svn } 7361ae349f5Scvs2svn 7371ae349f5Scvs2svn static void 73830c2f2ffSBrian Somers IpcpDecodeConfig(struct fsm *fp, u_char * cp, int plen, int mode_type, 73930c2f2ffSBrian Somers struct fsm_decode *dec) 7401ae349f5Scvs2svn { 7417308ec68SBrian Somers /* Deal with incoming PROTO_IPCP */ 742aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 7431ae349f5Scvs2svn int type, length; 744fe3125a0SBrian Somers u_int32_t compproto; 7451ae349f5Scvs2svn struct compreq *pcomp; 7463edeb0c6SBrian Somers struct in_addr ipaddr, dstipaddr, have_ip, dns[2], dnsnak[2]; 74730c2f2ffSBrian Somers char tbuff[100], tbuff2[100]; 7483edeb0c6SBrian Somers int gotdns, gotdnsnak; 7493edeb0c6SBrian Somers 7503edeb0c6SBrian Somers gotdns = 0; 7513edeb0c6SBrian Somers gotdnsnak = 0; 7523edeb0c6SBrian Somers dnsnak[0].s_addr = dnsnak[1].s_addr = INADDR_ANY; 7531ae349f5Scvs2svn 7541ae349f5Scvs2svn while (plen >= sizeof(struct fsmconfig)) { 7551ae349f5Scvs2svn type = *cp; 7561ae349f5Scvs2svn length = cp[1]; 757d47dceb8SBrian Somers 758d47dceb8SBrian Somers if (length == 0) { 759d47dceb8SBrian Somers LogPrintf(LogIPCP, "%s: IPCP size zero\n", fp->link->name); 760d47dceb8SBrian Somers break; 761d47dceb8SBrian Somers } 762d47dceb8SBrian Somers 7631ae349f5Scvs2svn if (type < NCFTYPES) 7641ae349f5Scvs2svn snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes[type], length); 7651ae349f5Scvs2svn else if (type > 128 && type < 128 + NCFTYPES128) 7661ae349f5Scvs2svn snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes128[type-128], length); 7671ae349f5Scvs2svn else 7681ae349f5Scvs2svn snprintf(tbuff, sizeof tbuff, " <%d>[%d] ", type, length); 7691ae349f5Scvs2svn 7701ae349f5Scvs2svn switch (type) { 7711ae349f5Scvs2svn case TY_IPADDR: /* RFC1332 */ 772fe3125a0SBrian Somers ipaddr.s_addr = *(u_int32_t *)(cp + 2); 7731ae349f5Scvs2svn LogPrintf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 7741ae349f5Scvs2svn 7751ae349f5Scvs2svn switch (mode_type) { 7761ae349f5Scvs2svn case MODE_REQ: 777503a7782SBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 7781ae349f5Scvs2svn if (ipaddr.s_addr == INADDR_ANY || 779503a7782SBrian Somers iplist_ip2pos(&ipcp->cfg.peer_list, ipaddr) < 0 || 78030c2f2ffSBrian Somers ipcp_SetIPaddress(fp->bundle, ipcp->cfg.my_range.ipaddr, 78130c2f2ffSBrian Somers ipaddr, 1)) { 7821ae349f5Scvs2svn LogPrintf(LogIPCP, "%s: Address invalid or already in use\n", 7831ae349f5Scvs2svn inet_ntoa(ipaddr)); 7848390b576SBrian Somers if (iplist_ip2pos(&ipcp->cfg.peer_list, ipcp->peer_ifip) >= 0) 7858390b576SBrian Somers /* 7868390b576SBrian Somers * If we've already got a valid address configured for the peer 787565e35e5SBrian Somers * (in DEMAND mode), try NAKing with that so that we don't 7888390b576SBrian Somers * have to upset things too much. 7898390b576SBrian Somers */ 7908390b576SBrian Somers ipcp->peer_ip = ipcp->peer_ifip; 7918390b576SBrian Somers else 7928390b576SBrian Somers /* Just pick an IP number from our list */ 793503a7782SBrian Somers ipcp->peer_ip = ChooseHisAddr 79430c2f2ffSBrian Somers (fp->bundle, ipcp->cfg.my_range.ipaddr); 7958390b576SBrian Somers 796503a7782SBrian Somers if (ipcp->peer_ip.s_addr == INADDR_ANY) { 79730c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 79830c2f2ffSBrian Somers dec->rejend += length; 7991ae349f5Scvs2svn } else { 80030c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 80130c2f2ffSBrian Somers memcpy(dec->nakend+2, &ipcp->peer_ip.s_addr, length - 2); 80230c2f2ffSBrian Somers dec->nakend += length; 8031ae349f5Scvs2svn } 8041ae349f5Scvs2svn break; 8051ae349f5Scvs2svn } 806503a7782SBrian Somers } else if (!AcceptableAddr(&ipcp->cfg.peer_range, ipaddr)) { 8071ae349f5Scvs2svn /* 8088390b576SBrian Somers * If destination address is not acceptable, NAK with what we 8091ae349f5Scvs2svn * want to use. 8101ae349f5Scvs2svn */ 81130c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 8128390b576SBrian Somers if ((ipcp->peer_ifip.s_addr & ipcp->cfg.peer_range.mask.s_addr) == 8138390b576SBrian Somers (ipcp->cfg.peer_range.ipaddr.s_addr & 8148390b576SBrian Somers ipcp->cfg.peer_range.mask.s_addr)) 8158390b576SBrian Somers /* We prefer the already-configured address */ 8168390b576SBrian Somers memcpy(dec->nakend+2, &ipcp->peer_ifip.s_addr, length - 2); 8178390b576SBrian Somers else 81830c2f2ffSBrian Somers memcpy(dec->nakend+2, &ipcp->peer_ip.s_addr, length - 2); 81930c2f2ffSBrian Somers dec->nakend += length; 8201ae349f5Scvs2svn break; 8211ae349f5Scvs2svn } 822503a7782SBrian Somers ipcp->peer_ip = ipaddr; 82330c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 82430c2f2ffSBrian Somers dec->ackend += length; 8251ae349f5Scvs2svn break; 8261ae349f5Scvs2svn case MODE_NAK: 827503a7782SBrian Somers if (AcceptableAddr(&ipcp->cfg.my_range, ipaddr)) { 8281ae349f5Scvs2svn /* Use address suggested by peer */ 8291ae349f5Scvs2svn snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s ", tbuff, 830503a7782SBrian Somers inet_ntoa(ipcp->my_ip)); 8311ae349f5Scvs2svn LogPrintf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 832503a7782SBrian Somers ipcp->my_ip = ipaddr; 8331ae349f5Scvs2svn } else { 8348390b576SBrian Somers LogPrintf(LogIsKept(LogIPCP) ? LogIPCP : LogPHASE, 8358390b576SBrian Somers "%s: Unacceptable address!\n", inet_ntoa(ipaddr)); 83683d1af55SBrian Somers FsmClose(&ipcp->fsm); 8371ae349f5Scvs2svn } 8381ae349f5Scvs2svn break; 8391ae349f5Scvs2svn case MODE_REJ: 840503a7782SBrian Somers ipcp->peer_reject |= (1 << type); 8411ae349f5Scvs2svn break; 8421ae349f5Scvs2svn } 8431ae349f5Scvs2svn break; 8441ae349f5Scvs2svn case TY_COMPPROTO: 845fe3125a0SBrian Somers compproto = htonl(*(u_int32_t *)(cp + 2)); 8461ae349f5Scvs2svn LogPrintf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto)); 8471ae349f5Scvs2svn 8481ae349f5Scvs2svn switch (mode_type) { 8491ae349f5Scvs2svn case MODE_REQ: 8501342caedSBrian Somers if (!IsAccepted(ipcp->cfg.vj.neg)) { 85130c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 85230c2f2ffSBrian Somers dec->rejend += length; 8531ae349f5Scvs2svn } else { 8541ae349f5Scvs2svn pcomp = (struct compreq *) (cp + 2); 8551ae349f5Scvs2svn switch (length) { 8561ae349f5Scvs2svn case 4: /* RFC1172 */ 8571ae349f5Scvs2svn if (ntohs(pcomp->proto) == PROTO_VJCOMP) { 8581ae349f5Scvs2svn LogPrintf(LogWARN, "Peer is speaking RFC1172 compression protocol !\n"); 85983d1af55SBrian Somers ipcp->heis1172 = 1; 860503a7782SBrian Somers ipcp->peer_compproto = compproto; 86130c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 86230c2f2ffSBrian Somers dec->ackend += length; 8631ae349f5Scvs2svn } else { 86430c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 8651ae349f5Scvs2svn pcomp->proto = htons(PROTO_VJCOMP); 86630c2f2ffSBrian Somers memcpy(dec->nakend+2, &pcomp, 2); 86730c2f2ffSBrian Somers dec->nakend += length; 8681ae349f5Scvs2svn } 8691ae349f5Scvs2svn break; 8701ae349f5Scvs2svn case 6: /* RFC1332 */ 8711ae349f5Scvs2svn if (ntohs(pcomp->proto) == PROTO_VJCOMP 872503a7782SBrian Somers && pcomp->slots <= MAX_VJ_STATES 873503a7782SBrian Somers && pcomp->slots >= MIN_VJ_STATES) { 874503a7782SBrian Somers ipcp->peer_compproto = compproto; 87583d1af55SBrian Somers ipcp->heis1172 = 0; 87630c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 87730c2f2ffSBrian Somers dec->ackend += length; 8781ae349f5Scvs2svn } else { 87930c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 8801ae349f5Scvs2svn pcomp->proto = htons(PROTO_VJCOMP); 881503a7782SBrian Somers pcomp->slots = DEF_VJ_STATES; 8821ae349f5Scvs2svn pcomp->compcid = 0; 88330c2f2ffSBrian Somers memcpy(dec->nakend+2, &pcomp, sizeof pcomp); 88430c2f2ffSBrian Somers dec->nakend += length; 8851ae349f5Scvs2svn } 8861ae349f5Scvs2svn break; 8871ae349f5Scvs2svn default: 88830c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 88930c2f2ffSBrian Somers dec->rejend += length; 8901ae349f5Scvs2svn break; 8911ae349f5Scvs2svn } 8921ae349f5Scvs2svn } 8931ae349f5Scvs2svn break; 8941ae349f5Scvs2svn case MODE_NAK: 8951ae349f5Scvs2svn LogPrintf(LogIPCP, "%s changing compproto: %08x --> %08x\n", 896503a7782SBrian Somers tbuff, ipcp->my_compproto, compproto); 897503a7782SBrian Somers ipcp->my_compproto = compproto; 8981ae349f5Scvs2svn break; 8991ae349f5Scvs2svn case MODE_REJ: 900503a7782SBrian Somers ipcp->peer_reject |= (1 << type); 9011ae349f5Scvs2svn break; 9021ae349f5Scvs2svn } 9031ae349f5Scvs2svn break; 9041ae349f5Scvs2svn case TY_IPADDRS: /* RFC1172 */ 905fe3125a0SBrian Somers ipaddr.s_addr = *(u_int32_t *)(cp + 2); 906fe3125a0SBrian Somers dstipaddr.s_addr = *(u_int32_t *)(cp + 6); 9071ae349f5Scvs2svn snprintf(tbuff2, sizeof tbuff2, "%s %s,", tbuff, inet_ntoa(ipaddr)); 9081ae349f5Scvs2svn LogPrintf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr)); 9091ae349f5Scvs2svn 9101ae349f5Scvs2svn switch (mode_type) { 9111ae349f5Scvs2svn case MODE_REQ: 912503a7782SBrian Somers ipcp->peer_ip = ipaddr; 913503a7782SBrian Somers ipcp->my_ip = dstipaddr; 91430c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 91530c2f2ffSBrian Somers dec->ackend += length; 9161ae349f5Scvs2svn break; 9171ae349f5Scvs2svn case MODE_NAK: 9181ae349f5Scvs2svn snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s", tbuff, 919503a7782SBrian Somers inet_ntoa(ipcp->my_ip)); 9201ae349f5Scvs2svn LogPrintf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 921503a7782SBrian Somers ipcp->my_ip = ipaddr; 922503a7782SBrian Somers ipcp->peer_ip = dstipaddr; 9231ae349f5Scvs2svn break; 9241ae349f5Scvs2svn case MODE_REJ: 925503a7782SBrian Somers ipcp->peer_reject |= (1 << type); 9261ae349f5Scvs2svn break; 9271ae349f5Scvs2svn } 9281ae349f5Scvs2svn break; 9291ae349f5Scvs2svn 9303edeb0c6SBrian Somers case TY_PRIMARY_DNS: /* DNS negotiation (rfc1877) */ 9311ae349f5Scvs2svn case TY_SECONDARY_DNS: 9323edeb0c6SBrian Somers ipaddr.s_addr = *(u_int32_t *)(cp + 2); 9333edeb0c6SBrian Somers LogPrintf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 9343edeb0c6SBrian Somers 93530c2f2ffSBrian Somers switch (mode_type) { 93630c2f2ffSBrian Somers case MODE_REQ: 9373edeb0c6SBrian Somers if (!IsAccepted(ipcp->cfg.ns.dns_neg)) { 9383edeb0c6SBrian Somers ipcp->my_reject |= (1 << (type - TY_ADJUST_NS)); 93930c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 94030c2f2ffSBrian Somers dec->rejend += length; 9411ae349f5Scvs2svn break; 9421ae349f5Scvs2svn } 9433edeb0c6SBrian Somers if (!gotdns) { 9443edeb0c6SBrian Somers dns[0] = ipcp->cfg.ns.dns[0]; 9453edeb0c6SBrian Somers dns[1] = ipcp->cfg.ns.dns[1]; 9463edeb0c6SBrian Somers if (dns[0].s_addr == INADDR_ANY && dns[1].s_addr == INADDR_ANY) 9473edeb0c6SBrian Somers getdns(ipcp, dns); 9483edeb0c6SBrian Somers gotdns = 1; 9493edeb0c6SBrian Somers } 9503edeb0c6SBrian Somers have_ip = dns[type == TY_PRIMARY_DNS ? 0 : 1]; 9511ae349f5Scvs2svn 9523edeb0c6SBrian Somers if (ipaddr.s_addr != have_ip.s_addr) { 9531ae349f5Scvs2svn /* 9543edeb0c6SBrian Somers * The client has got the DNS stuff wrong (first request) so 9551ae349f5Scvs2svn * we'll tell 'em how it is 9561ae349f5Scvs2svn */ 95730c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); /* copy first two (type/length) */ 9583edeb0c6SBrian Somers memcpy(dec->nakend + 2, &have_ip.s_addr, length - 2); 95930c2f2ffSBrian Somers dec->nakend += length; 9603edeb0c6SBrian Somers } else { 9611ae349f5Scvs2svn /* 9621ae349f5Scvs2svn * Otherwise they have it right (this time) so we send a ack packet 9631ae349f5Scvs2svn * back confirming it... end of story 9641ae349f5Scvs2svn */ 96530c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 96630c2f2ffSBrian Somers dec->ackend += length; 9673edeb0c6SBrian Somers } 9681ae349f5Scvs2svn break; 9691ae349f5Scvs2svn case MODE_NAK: /* what does this mean?? */ 9703edeb0c6SBrian Somers if (IsEnabled(ipcp->cfg.ns.dns_neg)) { 9713edeb0c6SBrian Somers gotdnsnak = 1; 9723edeb0c6SBrian Somers dnsnak[type == TY_PRIMARY_DNS ? 0 : 1].s_addr = 9733edeb0c6SBrian Somers *(u_int32_t *)(cp + 2); 9743edeb0c6SBrian Somers } 9751ae349f5Scvs2svn break; 9763edeb0c6SBrian Somers case MODE_REJ: /* Can't do much, stop asking */ 9773edeb0c6SBrian Somers ipcp->peer_reject |= (1 << (type - TY_ADJUST_NS)); 9781ae349f5Scvs2svn break; 9791ae349f5Scvs2svn } 9801ae349f5Scvs2svn break; 9811ae349f5Scvs2svn 9823edeb0c6SBrian Somers case TY_PRIMARY_NBNS: /* M$ NetBIOS nameserver hack (rfc1877) */ 9831ae349f5Scvs2svn case TY_SECONDARY_NBNS: 9843edeb0c6SBrian Somers ipaddr.s_addr = *(u_int32_t *)(cp + 2); 9853edeb0c6SBrian Somers LogPrintf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 9863edeb0c6SBrian Somers 98730c2f2ffSBrian Somers switch (mode_type) { 98830c2f2ffSBrian Somers case MODE_REQ: 9893edeb0c6SBrian Somers have_ip.s_addr = 9903edeb0c6SBrian Somers ipcp->cfg.ns.nbns[type == TY_PRIMARY_NBNS ? 0 : 1].s_addr; 9913edeb0c6SBrian Somers 9923edeb0c6SBrian Somers if (have_ip.s_addr == INADDR_ANY) { 9933edeb0c6SBrian Somers LogPrintf(LogIPCP, "NBNS REQ - rejected - nbns not set\n"); 9943edeb0c6SBrian Somers ipcp->my_reject |= (1 << (type - TY_ADJUST_NS)); 99530c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 99630c2f2ffSBrian Somers dec->rejend += length; 9971ae349f5Scvs2svn break; 9981ae349f5Scvs2svn } 9993edeb0c6SBrian Somers 10003edeb0c6SBrian Somers if (ipaddr.s_addr != have_ip.s_addr) { 100130c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 10023edeb0c6SBrian Somers memcpy(dec->nakend+2, &have_ip.s_addr, length); 100330c2f2ffSBrian Somers dec->nakend += length; 10043edeb0c6SBrian Somers } else { 100530c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 100630c2f2ffSBrian Somers dec->ackend += length; 10073edeb0c6SBrian Somers } 10081ae349f5Scvs2svn break; 10091ae349f5Scvs2svn case MODE_NAK: 10101ae349f5Scvs2svn LogPrintf(LogIPCP, "MS NBNS req %d - NAK??\n", type); 10111ae349f5Scvs2svn break; 10121ae349f5Scvs2svn case MODE_REJ: 10131ae349f5Scvs2svn LogPrintf(LogIPCP, "MS NBNS req %d - REJ??\n", type); 10141ae349f5Scvs2svn break; 10151ae349f5Scvs2svn } 10161ae349f5Scvs2svn break; 10171ae349f5Scvs2svn 10181ae349f5Scvs2svn default: 101930c2f2ffSBrian Somers if (mode_type != MODE_NOP) { 102083d1af55SBrian Somers ipcp->my_reject |= (1 << type); 102130c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 102230c2f2ffSBrian Somers dec->rejend += length; 102330c2f2ffSBrian Somers } 10241ae349f5Scvs2svn break; 10251ae349f5Scvs2svn } 10261ae349f5Scvs2svn plen -= length; 10271ae349f5Scvs2svn cp += length; 10281ae349f5Scvs2svn } 10291342caedSBrian Somers 10303edeb0c6SBrian Somers if (gotdnsnak) 10313edeb0c6SBrian Somers if (!setdns(ipcp, dnsnak)) { 10323edeb0c6SBrian Somers ipcp->peer_reject |= (1 << (TY_PRIMARY_DNS - TY_ADJUST_NS)); 10333edeb0c6SBrian Somers ipcp->peer_reject |= (1 << (TY_SECONDARY_DNS - TY_ADJUST_NS)); 10343edeb0c6SBrian Somers } 10353edeb0c6SBrian Somers 1036e43ebac1SBrian Somers if (mode_type != MODE_NOP) { 10371342caedSBrian Somers if (dec->rejend != dec->rej) { 10381342caedSBrian Somers /* rejects are preferred */ 10391342caedSBrian Somers dec->ackend = dec->ack; 10401342caedSBrian Somers dec->nakend = dec->nak; 10411342caedSBrian Somers } else if (dec->nakend != dec->nak) 10421342caedSBrian Somers /* then NAKs */ 10431342caedSBrian Somers dec->ackend = dec->ack; 10441ae349f5Scvs2svn } 1045e43ebac1SBrian Somers } 10461ae349f5Scvs2svn 10471ae349f5Scvs2svn void 10485828db6dSBrian Somers IpcpInput(struct ipcp *ipcp, struct mbuf * bp) 10491ae349f5Scvs2svn { 10507308ec68SBrian Somers /* Got PROTO_IPCP from link */ 10515828db6dSBrian Somers FsmInput(&ipcp->fsm, bp); 10521ae349f5Scvs2svn } 10531ae349f5Scvs2svn 10541ae349f5Scvs2svn int 10557a6f8720SBrian Somers UseHisaddr(struct bundle *bundle, const char *hisaddr, int setaddr) 10561ae349f5Scvs2svn { 10575828db6dSBrian Somers struct ipcp *ipcp = &bundle->ncp.ipcp; 10585828db6dSBrian Somers 10597308ec68SBrian Somers /* Use `hisaddr' for the peers address (set iface if `setaddr') */ 10605828db6dSBrian Somers memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 10615828db6dSBrian Somers iplist_reset(&ipcp->cfg.peer_list); 10621ae349f5Scvs2svn if (strpbrk(hisaddr, ",-")) { 10635828db6dSBrian Somers iplist_setsrc(&ipcp->cfg.peer_list, hisaddr); 10645828db6dSBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 10655828db6dSBrian Somers iplist_setrandpos(&ipcp->cfg.peer_list); 106630c2f2ffSBrian Somers ipcp->peer_ip = ChooseHisAddr(bundle, ipcp->my_ip); 10675828db6dSBrian Somers if (ipcp->peer_ip.s_addr == INADDR_ANY) { 1068d47dceb8SBrian Somers LogPrintf(LogWARN, "%s: None available !\n", ipcp->cfg.peer_list.src); 10691ae349f5Scvs2svn return(0); 10701ae349f5Scvs2svn } 10715828db6dSBrian Somers ipcp->cfg.peer_range.ipaddr.s_addr = ipcp->peer_ip.s_addr; 10725828db6dSBrian Somers ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 10735828db6dSBrian Somers ipcp->cfg.peer_range.width = 32; 10741ae349f5Scvs2svn } else { 10751ae349f5Scvs2svn LogPrintf(LogWARN, "%s: Invalid range !\n", hisaddr); 10761ae349f5Scvs2svn return 0; 10771ae349f5Scvs2svn } 10785828db6dSBrian Somers } else if (ParseAddr(ipcp, 1, &hisaddr, &ipcp->cfg.peer_range.ipaddr, 10795828db6dSBrian Somers &ipcp->cfg.peer_range.mask, 10805828db6dSBrian Somers &ipcp->cfg.peer_range.width) != 0) { 10815828db6dSBrian Somers ipcp->peer_ip.s_addr = ipcp->cfg.peer_range.ipaddr.s_addr; 10821ae349f5Scvs2svn 108330c2f2ffSBrian Somers if (setaddr && ipcp_SetIPaddress(bundle, ipcp->cfg.my_range.ipaddr, 108430c2f2ffSBrian Somers ipcp->cfg.peer_range.ipaddr, 0) < 0) { 10855828db6dSBrian Somers ipcp->cfg.my_range.ipaddr.s_addr = INADDR_ANY; 10865828db6dSBrian Somers ipcp->cfg.peer_range.ipaddr.s_addr = INADDR_ANY; 10871ae349f5Scvs2svn return 0; 10881ae349f5Scvs2svn } 10891ae349f5Scvs2svn } else 10901ae349f5Scvs2svn return 0; 10911ae349f5Scvs2svn 10921ae349f5Scvs2svn return 1; 10931ae349f5Scvs2svn } 1094