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 * 201fa665f5SBrian Somers * $Id: ipcp.c,v 1.50.2.46 1998/04/25 10:49:09 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 841ae349f5Scvs2svn static void 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 6871ae349f5Scvs2svn static void 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"); 7031ae349f5Scvs2svn return; 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); 7281ae349f5Scvs2svn } 7291ae349f5Scvs2svn 7301ae349f5Scvs2svn static int 7311ae349f5Scvs2svn AcceptableAddr(struct in_range *prange, struct in_addr ipaddr) 7321ae349f5Scvs2svn { 7337308ec68SBrian Somers /* Is the given IP in the given range ? */ 7341ae349f5Scvs2svn return (prange->ipaddr.s_addr & prange->mask.s_addr) == 7351ae349f5Scvs2svn (ipaddr.s_addr & prange->mask.s_addr) && ipaddr.s_addr; 7361ae349f5Scvs2svn } 7371ae349f5Scvs2svn 7381ae349f5Scvs2svn static void 73930c2f2ffSBrian Somers IpcpDecodeConfig(struct fsm *fp, u_char * cp, int plen, int mode_type, 74030c2f2ffSBrian Somers struct fsm_decode *dec) 7411ae349f5Scvs2svn { 7427308ec68SBrian Somers /* Deal with incoming PROTO_IPCP */ 743aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 7441ae349f5Scvs2svn int type, length; 745fe3125a0SBrian Somers u_int32_t compproto; 7461ae349f5Scvs2svn struct compreq *pcomp; 7473edeb0c6SBrian Somers struct in_addr ipaddr, dstipaddr, have_ip, dns[2], dnsnak[2]; 74830c2f2ffSBrian Somers char tbuff[100], tbuff2[100]; 7493edeb0c6SBrian Somers int gotdns, gotdnsnak; 7503edeb0c6SBrian Somers 7513edeb0c6SBrian Somers gotdns = 0; 7523edeb0c6SBrian Somers gotdnsnak = 0; 7533edeb0c6SBrian Somers dnsnak[0].s_addr = dnsnak[1].s_addr = INADDR_ANY; 7541ae349f5Scvs2svn 7551ae349f5Scvs2svn while (plen >= sizeof(struct fsmconfig)) { 7561ae349f5Scvs2svn type = *cp; 7571ae349f5Scvs2svn length = cp[1]; 758d47dceb8SBrian Somers 759d47dceb8SBrian Somers if (length == 0) { 760d47dceb8SBrian Somers LogPrintf(LogIPCP, "%s: IPCP size zero\n", fp->link->name); 761d47dceb8SBrian Somers break; 762d47dceb8SBrian Somers } 763d47dceb8SBrian Somers 7641ae349f5Scvs2svn if (type < NCFTYPES) 7651ae349f5Scvs2svn snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes[type], length); 7661ae349f5Scvs2svn else if (type > 128 && type < 128 + NCFTYPES128) 7671ae349f5Scvs2svn snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes128[type-128], length); 7681ae349f5Scvs2svn else 7691ae349f5Scvs2svn snprintf(tbuff, sizeof tbuff, " <%d>[%d] ", type, length); 7701ae349f5Scvs2svn 7711ae349f5Scvs2svn switch (type) { 7721ae349f5Scvs2svn case TY_IPADDR: /* RFC1332 */ 773fe3125a0SBrian Somers ipaddr.s_addr = *(u_int32_t *)(cp + 2); 7741ae349f5Scvs2svn LogPrintf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 7751ae349f5Scvs2svn 7761ae349f5Scvs2svn switch (mode_type) { 7771ae349f5Scvs2svn case MODE_REQ: 778503a7782SBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 7791ae349f5Scvs2svn if (ipaddr.s_addr == INADDR_ANY || 780503a7782SBrian Somers iplist_ip2pos(&ipcp->cfg.peer_list, ipaddr) < 0 || 78130c2f2ffSBrian Somers ipcp_SetIPaddress(fp->bundle, ipcp->cfg.my_range.ipaddr, 78230c2f2ffSBrian Somers ipaddr, 1)) { 7831ae349f5Scvs2svn LogPrintf(LogIPCP, "%s: Address invalid or already in use\n", 7841ae349f5Scvs2svn inet_ntoa(ipaddr)); 7858390b576SBrian Somers if (iplist_ip2pos(&ipcp->cfg.peer_list, ipcp->peer_ifip) >= 0) 7868390b576SBrian Somers /* 7878390b576SBrian Somers * If we've already got a valid address configured for the peer 788565e35e5SBrian Somers * (in DEMAND mode), try NAKing with that so that we don't 7898390b576SBrian Somers * have to upset things too much. 7908390b576SBrian Somers */ 7918390b576SBrian Somers ipcp->peer_ip = ipcp->peer_ifip; 7928390b576SBrian Somers else 7938390b576SBrian Somers /* Just pick an IP number from our list */ 794503a7782SBrian Somers ipcp->peer_ip = ChooseHisAddr 79530c2f2ffSBrian Somers (fp->bundle, ipcp->cfg.my_range.ipaddr); 7968390b576SBrian Somers 797503a7782SBrian Somers if (ipcp->peer_ip.s_addr == INADDR_ANY) { 79830c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 79930c2f2ffSBrian Somers dec->rejend += length; 8001ae349f5Scvs2svn } else { 80130c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 80230c2f2ffSBrian Somers memcpy(dec->nakend+2, &ipcp->peer_ip.s_addr, length - 2); 80330c2f2ffSBrian Somers dec->nakend += length; 8041ae349f5Scvs2svn } 8051ae349f5Scvs2svn break; 8061ae349f5Scvs2svn } 807503a7782SBrian Somers } else if (!AcceptableAddr(&ipcp->cfg.peer_range, ipaddr)) { 8081ae349f5Scvs2svn /* 8098390b576SBrian Somers * If destination address is not acceptable, NAK with what we 8101ae349f5Scvs2svn * want to use. 8111ae349f5Scvs2svn */ 81230c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 8138390b576SBrian Somers if ((ipcp->peer_ifip.s_addr & ipcp->cfg.peer_range.mask.s_addr) == 8148390b576SBrian Somers (ipcp->cfg.peer_range.ipaddr.s_addr & 8158390b576SBrian Somers ipcp->cfg.peer_range.mask.s_addr)) 8168390b576SBrian Somers /* We prefer the already-configured address */ 8178390b576SBrian Somers memcpy(dec->nakend+2, &ipcp->peer_ifip.s_addr, length - 2); 8188390b576SBrian Somers else 81930c2f2ffSBrian Somers memcpy(dec->nakend+2, &ipcp->peer_ip.s_addr, length - 2); 82030c2f2ffSBrian Somers dec->nakend += length; 8211ae349f5Scvs2svn break; 8221ae349f5Scvs2svn } 823503a7782SBrian Somers ipcp->peer_ip = ipaddr; 82430c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 82530c2f2ffSBrian Somers dec->ackend += length; 8261ae349f5Scvs2svn break; 8271ae349f5Scvs2svn case MODE_NAK: 828503a7782SBrian Somers if (AcceptableAddr(&ipcp->cfg.my_range, ipaddr)) { 8291ae349f5Scvs2svn /* Use address suggested by peer */ 8301ae349f5Scvs2svn snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s ", tbuff, 831503a7782SBrian Somers inet_ntoa(ipcp->my_ip)); 8321ae349f5Scvs2svn LogPrintf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 833503a7782SBrian Somers ipcp->my_ip = ipaddr; 8341ae349f5Scvs2svn } else { 8358390b576SBrian Somers LogPrintf(LogIsKept(LogIPCP) ? LogIPCP : LogPHASE, 8368390b576SBrian Somers "%s: Unacceptable address!\n", inet_ntoa(ipaddr)); 83783d1af55SBrian Somers FsmClose(&ipcp->fsm); 8381ae349f5Scvs2svn } 8391ae349f5Scvs2svn break; 8401ae349f5Scvs2svn case MODE_REJ: 841503a7782SBrian Somers ipcp->peer_reject |= (1 << type); 8421ae349f5Scvs2svn break; 8431ae349f5Scvs2svn } 8441ae349f5Scvs2svn break; 8451ae349f5Scvs2svn case TY_COMPPROTO: 846fe3125a0SBrian Somers compproto = htonl(*(u_int32_t *)(cp + 2)); 8471ae349f5Scvs2svn LogPrintf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto)); 8481ae349f5Scvs2svn 8491ae349f5Scvs2svn switch (mode_type) { 8501ae349f5Scvs2svn case MODE_REQ: 8511342caedSBrian Somers if (!IsAccepted(ipcp->cfg.vj.neg)) { 85230c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 85330c2f2ffSBrian Somers dec->rejend += length; 8541ae349f5Scvs2svn } else { 8551ae349f5Scvs2svn pcomp = (struct compreq *) (cp + 2); 8561ae349f5Scvs2svn switch (length) { 8571ae349f5Scvs2svn case 4: /* RFC1172 */ 8581ae349f5Scvs2svn if (ntohs(pcomp->proto) == PROTO_VJCOMP) { 8591ae349f5Scvs2svn LogPrintf(LogWARN, "Peer is speaking RFC1172 compression protocol !\n"); 86083d1af55SBrian Somers ipcp->heis1172 = 1; 861503a7782SBrian Somers ipcp->peer_compproto = compproto; 86230c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 86330c2f2ffSBrian Somers dec->ackend += length; 8641ae349f5Scvs2svn } else { 86530c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 8661ae349f5Scvs2svn pcomp->proto = htons(PROTO_VJCOMP); 86730c2f2ffSBrian Somers memcpy(dec->nakend+2, &pcomp, 2); 86830c2f2ffSBrian Somers dec->nakend += length; 8691ae349f5Scvs2svn } 8701ae349f5Scvs2svn break; 8711ae349f5Scvs2svn case 6: /* RFC1332 */ 8721ae349f5Scvs2svn if (ntohs(pcomp->proto) == PROTO_VJCOMP 873503a7782SBrian Somers && pcomp->slots <= MAX_VJ_STATES 874503a7782SBrian Somers && pcomp->slots >= MIN_VJ_STATES) { 875503a7782SBrian Somers ipcp->peer_compproto = compproto; 87683d1af55SBrian Somers ipcp->heis1172 = 0; 87730c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 87830c2f2ffSBrian Somers dec->ackend += length; 8791ae349f5Scvs2svn } else { 88030c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 8811ae349f5Scvs2svn pcomp->proto = htons(PROTO_VJCOMP); 882503a7782SBrian Somers pcomp->slots = DEF_VJ_STATES; 8831ae349f5Scvs2svn pcomp->compcid = 0; 88430c2f2ffSBrian Somers memcpy(dec->nakend+2, &pcomp, sizeof pcomp); 88530c2f2ffSBrian Somers dec->nakend += length; 8861ae349f5Scvs2svn } 8871ae349f5Scvs2svn break; 8881ae349f5Scvs2svn default: 88930c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 89030c2f2ffSBrian Somers dec->rejend += length; 8911ae349f5Scvs2svn break; 8921ae349f5Scvs2svn } 8931ae349f5Scvs2svn } 8941ae349f5Scvs2svn break; 8951ae349f5Scvs2svn case MODE_NAK: 8961ae349f5Scvs2svn LogPrintf(LogIPCP, "%s changing compproto: %08x --> %08x\n", 897503a7782SBrian Somers tbuff, ipcp->my_compproto, compproto); 898503a7782SBrian Somers ipcp->my_compproto = compproto; 8991ae349f5Scvs2svn break; 9001ae349f5Scvs2svn case MODE_REJ: 901503a7782SBrian Somers ipcp->peer_reject |= (1 << type); 9021ae349f5Scvs2svn break; 9031ae349f5Scvs2svn } 9041ae349f5Scvs2svn break; 9051ae349f5Scvs2svn case TY_IPADDRS: /* RFC1172 */ 906fe3125a0SBrian Somers ipaddr.s_addr = *(u_int32_t *)(cp + 2); 907fe3125a0SBrian Somers dstipaddr.s_addr = *(u_int32_t *)(cp + 6); 9081ae349f5Scvs2svn snprintf(tbuff2, sizeof tbuff2, "%s %s,", tbuff, inet_ntoa(ipaddr)); 9091ae349f5Scvs2svn LogPrintf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr)); 9101ae349f5Scvs2svn 9111ae349f5Scvs2svn switch (mode_type) { 9121ae349f5Scvs2svn case MODE_REQ: 913503a7782SBrian Somers ipcp->peer_ip = ipaddr; 914503a7782SBrian Somers ipcp->my_ip = dstipaddr; 91530c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 91630c2f2ffSBrian Somers dec->ackend += length; 9171ae349f5Scvs2svn break; 9181ae349f5Scvs2svn case MODE_NAK: 9191ae349f5Scvs2svn snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s", tbuff, 920503a7782SBrian Somers inet_ntoa(ipcp->my_ip)); 9211ae349f5Scvs2svn LogPrintf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 922503a7782SBrian Somers ipcp->my_ip = ipaddr; 923503a7782SBrian Somers ipcp->peer_ip = dstipaddr; 9241ae349f5Scvs2svn break; 9251ae349f5Scvs2svn case MODE_REJ: 926503a7782SBrian Somers ipcp->peer_reject |= (1 << type); 9271ae349f5Scvs2svn break; 9281ae349f5Scvs2svn } 9291ae349f5Scvs2svn break; 9301ae349f5Scvs2svn 9313edeb0c6SBrian Somers case TY_PRIMARY_DNS: /* DNS negotiation (rfc1877) */ 9321ae349f5Scvs2svn case TY_SECONDARY_DNS: 9333edeb0c6SBrian Somers ipaddr.s_addr = *(u_int32_t *)(cp + 2); 9343edeb0c6SBrian Somers LogPrintf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 9353edeb0c6SBrian Somers 93630c2f2ffSBrian Somers switch (mode_type) { 93730c2f2ffSBrian Somers case MODE_REQ: 9383edeb0c6SBrian Somers if (!IsAccepted(ipcp->cfg.ns.dns_neg)) { 9393edeb0c6SBrian Somers ipcp->my_reject |= (1 << (type - TY_ADJUST_NS)); 94030c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 94130c2f2ffSBrian Somers dec->rejend += length; 9421ae349f5Scvs2svn break; 9431ae349f5Scvs2svn } 9443edeb0c6SBrian Somers if (!gotdns) { 9453edeb0c6SBrian Somers dns[0] = ipcp->cfg.ns.dns[0]; 9463edeb0c6SBrian Somers dns[1] = ipcp->cfg.ns.dns[1]; 9473edeb0c6SBrian Somers if (dns[0].s_addr == INADDR_ANY && dns[1].s_addr == INADDR_ANY) 9483edeb0c6SBrian Somers getdns(ipcp, dns); 9493edeb0c6SBrian Somers gotdns = 1; 9503edeb0c6SBrian Somers } 9513edeb0c6SBrian Somers have_ip = dns[type == TY_PRIMARY_DNS ? 0 : 1]; 9521ae349f5Scvs2svn 9533edeb0c6SBrian Somers if (ipaddr.s_addr != have_ip.s_addr) { 9541ae349f5Scvs2svn /* 9553edeb0c6SBrian Somers * The client has got the DNS stuff wrong (first request) so 9561ae349f5Scvs2svn * we'll tell 'em how it is 9571ae349f5Scvs2svn */ 95830c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); /* copy first two (type/length) */ 9593edeb0c6SBrian Somers memcpy(dec->nakend + 2, &have_ip.s_addr, length - 2); 96030c2f2ffSBrian Somers dec->nakend += length; 9613edeb0c6SBrian Somers } else { 9621ae349f5Scvs2svn /* 9631ae349f5Scvs2svn * Otherwise they have it right (this time) so we send a ack packet 9641ae349f5Scvs2svn * back confirming it... end of story 9651ae349f5Scvs2svn */ 96630c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 96730c2f2ffSBrian Somers dec->ackend += length; 9683edeb0c6SBrian Somers } 9691ae349f5Scvs2svn break; 9701ae349f5Scvs2svn case MODE_NAK: /* what does this mean?? */ 9713edeb0c6SBrian Somers if (IsEnabled(ipcp->cfg.ns.dns_neg)) { 9723edeb0c6SBrian Somers gotdnsnak = 1; 9733edeb0c6SBrian Somers dnsnak[type == TY_PRIMARY_DNS ? 0 : 1].s_addr = 9743edeb0c6SBrian Somers *(u_int32_t *)(cp + 2); 9753edeb0c6SBrian Somers } 9761ae349f5Scvs2svn break; 9773edeb0c6SBrian Somers case MODE_REJ: /* Can't do much, stop asking */ 9783edeb0c6SBrian Somers ipcp->peer_reject |= (1 << (type - TY_ADJUST_NS)); 9791ae349f5Scvs2svn break; 9801ae349f5Scvs2svn } 9811ae349f5Scvs2svn break; 9821ae349f5Scvs2svn 9833edeb0c6SBrian Somers case TY_PRIMARY_NBNS: /* M$ NetBIOS nameserver hack (rfc1877) */ 9841ae349f5Scvs2svn case TY_SECONDARY_NBNS: 9853edeb0c6SBrian Somers ipaddr.s_addr = *(u_int32_t *)(cp + 2); 9863edeb0c6SBrian Somers LogPrintf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 9873edeb0c6SBrian Somers 98830c2f2ffSBrian Somers switch (mode_type) { 98930c2f2ffSBrian Somers case MODE_REQ: 9903edeb0c6SBrian Somers have_ip.s_addr = 9913edeb0c6SBrian Somers ipcp->cfg.ns.nbns[type == TY_PRIMARY_NBNS ? 0 : 1].s_addr; 9923edeb0c6SBrian Somers 9933edeb0c6SBrian Somers if (have_ip.s_addr == INADDR_ANY) { 9943edeb0c6SBrian Somers LogPrintf(LogIPCP, "NBNS REQ - rejected - nbns not set\n"); 9953edeb0c6SBrian Somers ipcp->my_reject |= (1 << (type - TY_ADJUST_NS)); 99630c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 99730c2f2ffSBrian Somers dec->rejend += length; 9981ae349f5Scvs2svn break; 9991ae349f5Scvs2svn } 10003edeb0c6SBrian Somers 10013edeb0c6SBrian Somers if (ipaddr.s_addr != have_ip.s_addr) { 100230c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 10033edeb0c6SBrian Somers memcpy(dec->nakend+2, &have_ip.s_addr, length); 100430c2f2ffSBrian Somers dec->nakend += length; 10053edeb0c6SBrian Somers } else { 100630c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 100730c2f2ffSBrian Somers dec->ackend += length; 10083edeb0c6SBrian Somers } 10091ae349f5Scvs2svn break; 10101ae349f5Scvs2svn case MODE_NAK: 10111ae349f5Scvs2svn LogPrintf(LogIPCP, "MS NBNS req %d - NAK??\n", type); 10121ae349f5Scvs2svn break; 10131ae349f5Scvs2svn case MODE_REJ: 10141ae349f5Scvs2svn LogPrintf(LogIPCP, "MS NBNS req %d - REJ??\n", type); 10151ae349f5Scvs2svn break; 10161ae349f5Scvs2svn } 10171ae349f5Scvs2svn break; 10181ae349f5Scvs2svn 10191ae349f5Scvs2svn default: 102030c2f2ffSBrian Somers if (mode_type != MODE_NOP) { 102183d1af55SBrian Somers ipcp->my_reject |= (1 << type); 102230c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 102330c2f2ffSBrian Somers dec->rejend += length; 102430c2f2ffSBrian Somers } 10251ae349f5Scvs2svn break; 10261ae349f5Scvs2svn } 10271ae349f5Scvs2svn plen -= length; 10281ae349f5Scvs2svn cp += length; 10291ae349f5Scvs2svn } 10301342caedSBrian Somers 10313edeb0c6SBrian Somers if (gotdnsnak) 10323edeb0c6SBrian Somers if (!setdns(ipcp, dnsnak)) { 10333edeb0c6SBrian Somers ipcp->peer_reject |= (1 << (TY_PRIMARY_DNS - TY_ADJUST_NS)); 10343edeb0c6SBrian Somers ipcp->peer_reject |= (1 << (TY_SECONDARY_DNS - TY_ADJUST_NS)); 10353edeb0c6SBrian Somers } 10363edeb0c6SBrian Somers 1037e43ebac1SBrian Somers if (mode_type != MODE_NOP) { 10381342caedSBrian Somers if (dec->rejend != dec->rej) { 10391342caedSBrian Somers /* rejects are preferred */ 10401342caedSBrian Somers dec->ackend = dec->ack; 10411342caedSBrian Somers dec->nakend = dec->nak; 10421342caedSBrian Somers } else if (dec->nakend != dec->nak) 10431342caedSBrian Somers /* then NAKs */ 10441342caedSBrian Somers dec->ackend = dec->ack; 10451ae349f5Scvs2svn } 1046e43ebac1SBrian Somers } 10471ae349f5Scvs2svn 10481ae349f5Scvs2svn void 10495828db6dSBrian Somers IpcpInput(struct ipcp *ipcp, struct mbuf * bp) 10501ae349f5Scvs2svn { 10517308ec68SBrian Somers /* Got PROTO_IPCP from link */ 10525828db6dSBrian Somers FsmInput(&ipcp->fsm, bp); 10531ae349f5Scvs2svn } 10541ae349f5Scvs2svn 10551ae349f5Scvs2svn int 10567a6f8720SBrian Somers UseHisaddr(struct bundle *bundle, const char *hisaddr, int setaddr) 10571ae349f5Scvs2svn { 10585828db6dSBrian Somers struct ipcp *ipcp = &bundle->ncp.ipcp; 10595828db6dSBrian Somers 10607308ec68SBrian Somers /* Use `hisaddr' for the peers address (set iface if `setaddr') */ 10615828db6dSBrian Somers memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 10625828db6dSBrian Somers iplist_reset(&ipcp->cfg.peer_list); 10631ae349f5Scvs2svn if (strpbrk(hisaddr, ",-")) { 10645828db6dSBrian Somers iplist_setsrc(&ipcp->cfg.peer_list, hisaddr); 10655828db6dSBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 10665828db6dSBrian Somers iplist_setrandpos(&ipcp->cfg.peer_list); 106730c2f2ffSBrian Somers ipcp->peer_ip = ChooseHisAddr(bundle, ipcp->my_ip); 10685828db6dSBrian Somers if (ipcp->peer_ip.s_addr == INADDR_ANY) { 1069d47dceb8SBrian Somers LogPrintf(LogWARN, "%s: None available !\n", ipcp->cfg.peer_list.src); 10701ae349f5Scvs2svn return(0); 10711ae349f5Scvs2svn } 10725828db6dSBrian Somers ipcp->cfg.peer_range.ipaddr.s_addr = ipcp->peer_ip.s_addr; 10735828db6dSBrian Somers ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 10745828db6dSBrian Somers ipcp->cfg.peer_range.width = 32; 10751ae349f5Scvs2svn } else { 10761ae349f5Scvs2svn LogPrintf(LogWARN, "%s: Invalid range !\n", hisaddr); 10771ae349f5Scvs2svn return 0; 10781ae349f5Scvs2svn } 10795828db6dSBrian Somers } else if (ParseAddr(ipcp, 1, &hisaddr, &ipcp->cfg.peer_range.ipaddr, 10805828db6dSBrian Somers &ipcp->cfg.peer_range.mask, 10815828db6dSBrian Somers &ipcp->cfg.peer_range.width) != 0) { 10825828db6dSBrian Somers ipcp->peer_ip.s_addr = ipcp->cfg.peer_range.ipaddr.s_addr; 10831ae349f5Scvs2svn 108430c2f2ffSBrian Somers if (setaddr && ipcp_SetIPaddress(bundle, ipcp->cfg.my_range.ipaddr, 108530c2f2ffSBrian Somers ipcp->cfg.peer_range.ipaddr, 0) < 0) { 10865828db6dSBrian Somers ipcp->cfg.my_range.ipaddr.s_addr = INADDR_ANY; 10875828db6dSBrian Somers ipcp->cfg.peer_range.ipaddr.s_addr = INADDR_ANY; 10881ae349f5Scvs2svn return 0; 10891ae349f5Scvs2svn } 10901ae349f5Scvs2svn } else 10911ae349f5Scvs2svn return 0; 10921ae349f5Scvs2svn 10931ae349f5Scvs2svn return 1; 10941ae349f5Scvs2svn } 1095