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 * 20dd7e2610SBrian Somers * $Id: ipcp.c,v 1.50.2.48 1998/04/30 23:53:40 brian Exp $ 211ae349f5Scvs2svn * 221ae349f5Scvs2svn * TODO: 231ae349f5Scvs2svn * o More RFC1772 backwoard compatibility 241ae349f5Scvs2svn */ 251ae349f5Scvs2svn #include <sys/param.h> 261ae349f5Scvs2svn #include <netinet/in_systm.h> 271ae349f5Scvs2svn #include <netinet/in.h> 281ae349f5Scvs2svn #include <netinet/ip.h> 291ae349f5Scvs2svn #include <arpa/inet.h> 301ae349f5Scvs2svn #include <sys/socket.h> 311ae349f5Scvs2svn #include <netdb.h> 32455aabc3SBrian Somers #include <net/if.h> 33455aabc3SBrian Somers #include <sys/sockio.h> 341fa665f5SBrian Somers #include <sys/un.h> 351ae349f5Scvs2svn 363edeb0c6SBrian Somers #include <fcntl.h> 373edeb0c6SBrian Somers #include <resolv.h> 381ae349f5Scvs2svn #include <stdlib.h> 391ae349f5Scvs2svn #include <string.h> 40455aabc3SBrian Somers #include <sys/errno.h> 416140ba11SBrian Somers #include <termios.h> 421ae349f5Scvs2svn #include <unistd.h> 431ae349f5Scvs2svn 441ae349f5Scvs2svn #include "command.h" 451ae349f5Scvs2svn #include "mbuf.h" 461ae349f5Scvs2svn #include "log.h" 471ae349f5Scvs2svn #include "defs.h" 481ae349f5Scvs2svn #include "timer.h" 491ae349f5Scvs2svn #include "fsm.h" 501ae349f5Scvs2svn #include "lcpproto.h" 511ae349f5Scvs2svn #include "lcp.h" 521ae349f5Scvs2svn #include "iplist.h" 5329e275ceSBrian Somers #include "throughput.h" 541ae349f5Scvs2svn #include "slcompress.h" 55eaa4df37SBrian Somers #include "ipcp.h" 565ca5389aSBrian Somers #include "filter.h" 572f786681SBrian Somers #include "descriptor.h" 581ae349f5Scvs2svn #include "loadalias.h" 591ae349f5Scvs2svn #include "vjcomp.h" 60879ed6faSBrian Somers #include "lqr.h" 618c07a7b2SBrian Somers #include "hdlc.h" 626140ba11SBrian Somers #include "async.h" 633b0f8d2eSBrian Somers #include "ccp.h" 648c07a7b2SBrian Somers #include "link.h" 6563b73463SBrian Somers #include "physical.h" 663b0f8d2eSBrian Somers #include "mp.h" 673b0f8d2eSBrian Somers #include "bundle.h" 68455aabc3SBrian Somers #include "id.h" 69455aabc3SBrian Somers #include "arp.h" 70455aabc3SBrian Somers #include "systems.h" 7185b542cfSBrian Somers #include "prompt.h" 721ae349f5Scvs2svn 73503a7782SBrian Somers #undef REJECTED 74503a7782SBrian Somers #define REJECTED(p, x) ((p)->peer_reject & (1<<(x))) 753edeb0c6SBrian Somers #define issep(ch) ((ch) == ' ' || (ch) == '\t') 763edeb0c6SBrian Somers #define isip(ch) (((ch) >= '0' && (ch) <= '9') || (ch) == '.') 77503a7782SBrian Somers 7829e275ceSBrian Somers struct compreq { 7929e275ceSBrian Somers u_short proto; 8029e275ceSBrian Somers u_char slots; 8129e275ceSBrian Somers u_char compcid; 8229e275ceSBrian Somers }; 831ae349f5Scvs2svn 846f384573SBrian Somers static int IpcpLayerUp(struct fsm *); 851ae349f5Scvs2svn static void IpcpLayerDown(struct fsm *); 867308ec68SBrian Somers static void IpcpLayerStart(struct fsm *); 877308ec68SBrian Somers static void IpcpLayerFinish(struct fsm *); 881ae349f5Scvs2svn static void IpcpInitRestartCounter(struct fsm *); 897308ec68SBrian Somers static void IpcpSendConfigReq(struct fsm *); 902267893fSBrian Somers static void IpcpSentTerminateReq(struct fsm *); 912267893fSBrian Somers static void IpcpSendTerminateAck(struct fsm *, u_char); 9230c2f2ffSBrian Somers static void IpcpDecodeConfig(struct fsm *, u_char *, int, int, 9330c2f2ffSBrian Somers struct fsm_decode *); 9483d1af55SBrian Somers 9583d1af55SBrian Somers static struct fsm_callbacks ipcp_Callbacks = { 9683d1af55SBrian Somers IpcpLayerUp, 9783d1af55SBrian Somers IpcpLayerDown, 9883d1af55SBrian Somers IpcpLayerStart, 996d666775SBrian Somers IpcpLayerFinish, 10083d1af55SBrian Somers IpcpInitRestartCounter, 10183d1af55SBrian Somers IpcpSendConfigReq, 1022267893fSBrian Somers IpcpSentTerminateReq, 10383d1af55SBrian Somers IpcpSendTerminateAck, 10483d1af55SBrian Somers IpcpDecodeConfig, 105dd7e2610SBrian Somers fsm_NullRecvResetReq, 106dd7e2610SBrian Somers fsm_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) { 189dd7e2610SBrian Somers log_Printf(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) { 204dd7e2610SBrian Somers log_Printf(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])); 219dd7e2610SBrian Somers log_Printf(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])); 226dd7e2610SBrian Somers log_Printf(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) { 235dd7e2610SBrian Somers log_Printf(LogERROR, "setdns: write(): %s\n", strerror(errno)); 2363edeb0c6SBrian Somers close(fd); 2373edeb0c6SBrian Somers return 0; 2383edeb0c6SBrian Somers } 2393edeb0c6SBrian Somers if (ftruncate(fd, wlen) == -1) { 240dd7e2610SBrian Somers log_Printf(LogERROR, "setdns: truncate(): %s\n", strerror(errno)); 2413edeb0c6SBrian Somers close(fd); 2423edeb0c6SBrian Somers return 0; 2433edeb0c6SBrian Somers } 2443edeb0c6SBrian Somers close(fd); 2453edeb0c6SBrian Somers } else { 246dd7e2610SBrian Somers log_Printf(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 255dd7e2610SBrian Somers ipcp_Show(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 307dd7e2610SBrian Somers ipcp_vjset(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; 413dd7e2610SBrian Somers log_Printf(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 456dd7e2610SBrian Somers ipcp_CleanInterface(&bundle->ncp.ipcp); 45768a0f0ccSBrian Somers 458455aabc3SBrian Somers s = ID0socket(AF_INET, SOCK_DGRAM, 0); 459455aabc3SBrian Somers if (s < 0) { 460dd7e2610SBrian Somers log_Printf(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) 500dd7e2610SBrian Somers log_Printf(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)) 510dd7e2610SBrian Somers arp_SetProxy(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); 524dd7e2610SBrian Somers log_Printf(LogDEBUG, "ChooseHisAddr: Check item %d (%s)\n", 525455aabc3SBrian Somers f, inet_ntoa(try)); 52630c2f2ffSBrian Somers if (ipcp_SetIPaddress(bundle, gw, try, 1) == 0) { 527dd7e2610SBrian Somers log_Printf(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) { 533dd7e2610SBrian Somers log_Printf(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 561dd7e2610SBrian 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 587dd7e2610SBrian Somers fsm_Output(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 */ 600dd7e2610SBrian Somers fsm_Output(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 ! */ 607dd7e2610SBrian Somers log_Printf(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 */ 616dd7e2610SBrian Somers log_Printf(LogIPCP, "%s: IpcpLayerFinish.\n", fp->link->name); 6171ae349f5Scvs2svn } 6181ae349f5Scvs2svn 61968a0f0ccSBrian Somers void 620dd7e2610SBrian Somers ipcp_CleanInterface(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) { 628dd7e2610SBrian Somers log_Printf(LogERROR, "ipcp_CleanInterface: socket: %s\n", strerror(errno)); 62968a0f0ccSBrian Somers return; 63068a0f0ccSBrian Somers } 63168a0f0ccSBrian Somers 6321342caedSBrian Somers if (Enabled(ipcp->fsm.bundle, OPT_PROXY)) 633dd7e2610SBrian Somers arp_ClearProxy(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) { 648dd7e2610SBrian Somers log_Printf(LogERROR, "ipcp_CleanInterface: 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); 666dd7e2610SBrian Somers log_Printf(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 */ 674dd7e2610SBrian Somers if (system_Select(fp->bundle, s, LINKDOWNFILE, NULL) < 0) { 67549052c95SBrian Somers if (bundle_GetLabel(fp->bundle)) { 676dd7e2610SBrian Somers if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle), 67749052c95SBrian Somers LINKDOWNFILE, NULL) < 0) 678dd7e2610SBrian Somers system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL); 679455aabc3SBrian Somers } else 680dd7e2610SBrian Somers system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL); 681e43ebac1SBrian Somers } 682455aabc3SBrian Somers 683ba081e43SBrian Somers if (!(ipcp->fsm.bundle->phys_type & PHYS_DEMAND)) 684dd7e2610SBrian Somers ipcp_CleanInterface(ipcp); 6851ae349f5Scvs2svn } 6861ae349f5Scvs2svn 6876f384573SBrian Somers static int 6881ae349f5Scvs2svn IpcpLayerUp(struct fsm *fp) 6891ae349f5Scvs2svn { 6907308ec68SBrian Somers /* We're now up */ 691aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 6921ae349f5Scvs2svn char tbuff[100]; 6931ae349f5Scvs2svn 694dd7e2610SBrian Somers log_Printf(LogIPCP, "%s: IpcpLayerUp.\n", fp->link->name); 695503a7782SBrian Somers snprintf(tbuff, sizeof tbuff, "myaddr = %s ", inet_ntoa(ipcp->my_ip)); 696dd7e2610SBrian Somers log_Printf(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) { 702dd7e2610SBrian Somers log_Printf(LogERROR, "IpcpLayerUp: unable to set ip address\n"); 7036f384573SBrian Somers return 0; 7041ae349f5Scvs2svn } 705455aabc3SBrian Somers 7061ae349f5Scvs2svn #ifndef NOALIAS 707dd7e2610SBrian Somers if (alias_IsEnabled()) 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 */ 715dd7e2610SBrian Somers if (system_Select(fp->bundle, inet_ntoa(ipcp->my_ifip), LINKUPFILE, NULL) 716e43ebac1SBrian Somers < 0) { 71749052c95SBrian Somers if (bundle_GetLabel(fp->bundle)) { 718dd7e2610SBrian Somers if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle), 71949052c95SBrian Somers LINKUPFILE, NULL) < 0) 720dd7e2610SBrian Somers system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL); 721455aabc3SBrian Somers } else 722dd7e2610SBrian Somers system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL); 723e43ebac1SBrian Somers } 724455aabc3SBrian Somers 7251342caedSBrian Somers throughput_start(&ipcp->throughput, "IPCP throughput", 7261342caedSBrian Somers Enabled(fp->bundle, OPT_THROUGHPUT)); 727b6217683SBrian Somers bundle_DisplayPrompt(fp->bundle); 7286f384573SBrian Somers return 1; 7291ae349f5Scvs2svn } 7301ae349f5Scvs2svn 7311ae349f5Scvs2svn static int 7321ae349f5Scvs2svn AcceptableAddr(struct in_range *prange, struct in_addr ipaddr) 7331ae349f5Scvs2svn { 7347308ec68SBrian Somers /* Is the given IP in the given range ? */ 7351ae349f5Scvs2svn return (prange->ipaddr.s_addr & prange->mask.s_addr) == 7361ae349f5Scvs2svn (ipaddr.s_addr & prange->mask.s_addr) && ipaddr.s_addr; 7371ae349f5Scvs2svn } 7381ae349f5Scvs2svn 7391ae349f5Scvs2svn static void 74030c2f2ffSBrian Somers IpcpDecodeConfig(struct fsm *fp, u_char * cp, int plen, int mode_type, 74130c2f2ffSBrian Somers struct fsm_decode *dec) 7421ae349f5Scvs2svn { 7437308ec68SBrian Somers /* Deal with incoming PROTO_IPCP */ 744aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 7451ae349f5Scvs2svn int type, length; 746fe3125a0SBrian Somers u_int32_t compproto; 7471ae349f5Scvs2svn struct compreq *pcomp; 7483edeb0c6SBrian Somers struct in_addr ipaddr, dstipaddr, have_ip, dns[2], dnsnak[2]; 74930c2f2ffSBrian Somers char tbuff[100], tbuff2[100]; 7503edeb0c6SBrian Somers int gotdns, gotdnsnak; 7513edeb0c6SBrian Somers 7523edeb0c6SBrian Somers gotdns = 0; 7533edeb0c6SBrian Somers gotdnsnak = 0; 7543edeb0c6SBrian Somers dnsnak[0].s_addr = dnsnak[1].s_addr = INADDR_ANY; 7551ae349f5Scvs2svn 7561ae349f5Scvs2svn while (plen >= sizeof(struct fsmconfig)) { 7571ae349f5Scvs2svn type = *cp; 7581ae349f5Scvs2svn length = cp[1]; 759d47dceb8SBrian Somers 760d47dceb8SBrian Somers if (length == 0) { 761dd7e2610SBrian Somers log_Printf(LogIPCP, "%s: IPCP size zero\n", fp->link->name); 762d47dceb8SBrian Somers break; 763d47dceb8SBrian Somers } 764d47dceb8SBrian Somers 7651ae349f5Scvs2svn if (type < NCFTYPES) 7661ae349f5Scvs2svn snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes[type], length); 7671ae349f5Scvs2svn else if (type > 128 && type < 128 + NCFTYPES128) 7681ae349f5Scvs2svn snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes128[type-128], length); 7691ae349f5Scvs2svn else 7701ae349f5Scvs2svn snprintf(tbuff, sizeof tbuff, " <%d>[%d] ", type, length); 7711ae349f5Scvs2svn 7721ae349f5Scvs2svn switch (type) { 7731ae349f5Scvs2svn case TY_IPADDR: /* RFC1332 */ 774fe3125a0SBrian Somers ipaddr.s_addr = *(u_int32_t *)(cp + 2); 775dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 7761ae349f5Scvs2svn 7771ae349f5Scvs2svn switch (mode_type) { 7781ae349f5Scvs2svn case MODE_REQ: 779503a7782SBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 7801ae349f5Scvs2svn if (ipaddr.s_addr == INADDR_ANY || 781503a7782SBrian Somers iplist_ip2pos(&ipcp->cfg.peer_list, ipaddr) < 0 || 78230c2f2ffSBrian Somers ipcp_SetIPaddress(fp->bundle, ipcp->cfg.my_range.ipaddr, 78330c2f2ffSBrian Somers ipaddr, 1)) { 784dd7e2610SBrian Somers log_Printf(LogIPCP, "%s: Address invalid or already in use\n", 7851ae349f5Scvs2svn inet_ntoa(ipaddr)); 7868390b576SBrian Somers if (iplist_ip2pos(&ipcp->cfg.peer_list, ipcp->peer_ifip) >= 0) 7878390b576SBrian Somers /* 7888390b576SBrian Somers * If we've already got a valid address configured for the peer 789565e35e5SBrian Somers * (in DEMAND mode), try NAKing with that so that we don't 7908390b576SBrian Somers * have to upset things too much. 7918390b576SBrian Somers */ 7928390b576SBrian Somers ipcp->peer_ip = ipcp->peer_ifip; 7938390b576SBrian Somers else 7948390b576SBrian Somers /* Just pick an IP number from our list */ 795503a7782SBrian Somers ipcp->peer_ip = ChooseHisAddr 79630c2f2ffSBrian Somers (fp->bundle, ipcp->cfg.my_range.ipaddr); 7978390b576SBrian Somers 798503a7782SBrian Somers if (ipcp->peer_ip.s_addr == INADDR_ANY) { 79930c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 80030c2f2ffSBrian Somers dec->rejend += length; 8011ae349f5Scvs2svn } else { 80230c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 80330c2f2ffSBrian Somers memcpy(dec->nakend+2, &ipcp->peer_ip.s_addr, length - 2); 80430c2f2ffSBrian Somers dec->nakend += length; 8051ae349f5Scvs2svn } 8061ae349f5Scvs2svn break; 8071ae349f5Scvs2svn } 808503a7782SBrian Somers } else if (!AcceptableAddr(&ipcp->cfg.peer_range, ipaddr)) { 8091ae349f5Scvs2svn /* 8108390b576SBrian Somers * If destination address is not acceptable, NAK with what we 8111ae349f5Scvs2svn * want to use. 8121ae349f5Scvs2svn */ 81330c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 8148390b576SBrian Somers if ((ipcp->peer_ifip.s_addr & ipcp->cfg.peer_range.mask.s_addr) == 8158390b576SBrian Somers (ipcp->cfg.peer_range.ipaddr.s_addr & 8168390b576SBrian Somers ipcp->cfg.peer_range.mask.s_addr)) 8178390b576SBrian Somers /* We prefer the already-configured address */ 8188390b576SBrian Somers memcpy(dec->nakend+2, &ipcp->peer_ifip.s_addr, length - 2); 8198390b576SBrian Somers else 82030c2f2ffSBrian Somers memcpy(dec->nakend+2, &ipcp->peer_ip.s_addr, length - 2); 82130c2f2ffSBrian Somers dec->nakend += length; 8221ae349f5Scvs2svn break; 8231ae349f5Scvs2svn } 824503a7782SBrian Somers ipcp->peer_ip = ipaddr; 82530c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 82630c2f2ffSBrian Somers dec->ackend += length; 8271ae349f5Scvs2svn break; 8281ae349f5Scvs2svn case MODE_NAK: 829503a7782SBrian Somers if (AcceptableAddr(&ipcp->cfg.my_range, ipaddr)) { 8301ae349f5Scvs2svn /* Use address suggested by peer */ 8311ae349f5Scvs2svn snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s ", tbuff, 832503a7782SBrian Somers inet_ntoa(ipcp->my_ip)); 833dd7e2610SBrian Somers log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 834503a7782SBrian Somers ipcp->my_ip = ipaddr; 8351ae349f5Scvs2svn } else { 836dd7e2610SBrian Somers log_Printf(log_IsKept(LogIPCP) ? LogIPCP : LogPHASE, 8378390b576SBrian Somers "%s: Unacceptable address!\n", inet_ntoa(ipaddr)); 838dd7e2610SBrian Somers fsm_Close(&ipcp->fsm); 8391ae349f5Scvs2svn } 8401ae349f5Scvs2svn break; 8411ae349f5Scvs2svn case MODE_REJ: 842503a7782SBrian Somers ipcp->peer_reject |= (1 << type); 8431ae349f5Scvs2svn break; 8441ae349f5Scvs2svn } 8451ae349f5Scvs2svn break; 8461ae349f5Scvs2svn case TY_COMPPROTO: 847fe3125a0SBrian Somers compproto = htonl(*(u_int32_t *)(cp + 2)); 848dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto)); 8491ae349f5Scvs2svn 8501ae349f5Scvs2svn switch (mode_type) { 8511ae349f5Scvs2svn case MODE_REQ: 8521342caedSBrian Somers if (!IsAccepted(ipcp->cfg.vj.neg)) { 85330c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 85430c2f2ffSBrian Somers dec->rejend += length; 8551ae349f5Scvs2svn } else { 8561ae349f5Scvs2svn pcomp = (struct compreq *) (cp + 2); 8571ae349f5Scvs2svn switch (length) { 8581ae349f5Scvs2svn case 4: /* RFC1172 */ 8591ae349f5Scvs2svn if (ntohs(pcomp->proto) == PROTO_VJCOMP) { 860dd7e2610SBrian Somers log_Printf(LogWARN, "Peer is speaking RFC1172 compression protocol !\n"); 86183d1af55SBrian Somers ipcp->heis1172 = 1; 862503a7782SBrian Somers ipcp->peer_compproto = compproto; 86330c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 86430c2f2ffSBrian Somers dec->ackend += length; 8651ae349f5Scvs2svn } else { 86630c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 8671ae349f5Scvs2svn pcomp->proto = htons(PROTO_VJCOMP); 86830c2f2ffSBrian Somers memcpy(dec->nakend+2, &pcomp, 2); 86930c2f2ffSBrian Somers dec->nakend += length; 8701ae349f5Scvs2svn } 8711ae349f5Scvs2svn break; 8721ae349f5Scvs2svn case 6: /* RFC1332 */ 8731ae349f5Scvs2svn if (ntohs(pcomp->proto) == PROTO_VJCOMP 874503a7782SBrian Somers && pcomp->slots <= MAX_VJ_STATES 875503a7782SBrian Somers && pcomp->slots >= MIN_VJ_STATES) { 876503a7782SBrian Somers ipcp->peer_compproto = compproto; 87783d1af55SBrian Somers ipcp->heis1172 = 0; 87830c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 87930c2f2ffSBrian Somers dec->ackend += length; 8801ae349f5Scvs2svn } else { 88130c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 8821ae349f5Scvs2svn pcomp->proto = htons(PROTO_VJCOMP); 883503a7782SBrian Somers pcomp->slots = DEF_VJ_STATES; 8841ae349f5Scvs2svn pcomp->compcid = 0; 88530c2f2ffSBrian Somers memcpy(dec->nakend+2, &pcomp, sizeof pcomp); 88630c2f2ffSBrian Somers dec->nakend += length; 8871ae349f5Scvs2svn } 8881ae349f5Scvs2svn break; 8891ae349f5Scvs2svn default: 89030c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 89130c2f2ffSBrian Somers dec->rejend += length; 8921ae349f5Scvs2svn break; 8931ae349f5Scvs2svn } 8941ae349f5Scvs2svn } 8951ae349f5Scvs2svn break; 8961ae349f5Scvs2svn case MODE_NAK: 897dd7e2610SBrian Somers log_Printf(LogIPCP, "%s changing compproto: %08x --> %08x\n", 898503a7782SBrian Somers tbuff, ipcp->my_compproto, compproto); 899503a7782SBrian Somers ipcp->my_compproto = compproto; 9001ae349f5Scvs2svn break; 9011ae349f5Scvs2svn case MODE_REJ: 902503a7782SBrian Somers ipcp->peer_reject |= (1 << type); 9031ae349f5Scvs2svn break; 9041ae349f5Scvs2svn } 9051ae349f5Scvs2svn break; 9061ae349f5Scvs2svn case TY_IPADDRS: /* RFC1172 */ 907fe3125a0SBrian Somers ipaddr.s_addr = *(u_int32_t *)(cp + 2); 908fe3125a0SBrian Somers dstipaddr.s_addr = *(u_int32_t *)(cp + 6); 9091ae349f5Scvs2svn snprintf(tbuff2, sizeof tbuff2, "%s %s,", tbuff, inet_ntoa(ipaddr)); 910dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr)); 9111ae349f5Scvs2svn 9121ae349f5Scvs2svn switch (mode_type) { 9131ae349f5Scvs2svn case MODE_REQ: 914503a7782SBrian Somers ipcp->peer_ip = ipaddr; 915503a7782SBrian Somers ipcp->my_ip = dstipaddr; 91630c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 91730c2f2ffSBrian Somers dec->ackend += length; 9181ae349f5Scvs2svn break; 9191ae349f5Scvs2svn case MODE_NAK: 9201ae349f5Scvs2svn snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s", tbuff, 921503a7782SBrian Somers inet_ntoa(ipcp->my_ip)); 922dd7e2610SBrian Somers log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 923503a7782SBrian Somers ipcp->my_ip = ipaddr; 924503a7782SBrian Somers ipcp->peer_ip = dstipaddr; 9251ae349f5Scvs2svn break; 9261ae349f5Scvs2svn case MODE_REJ: 927503a7782SBrian Somers ipcp->peer_reject |= (1 << type); 9281ae349f5Scvs2svn break; 9291ae349f5Scvs2svn } 9301ae349f5Scvs2svn break; 9311ae349f5Scvs2svn 9323edeb0c6SBrian Somers case TY_PRIMARY_DNS: /* DNS negotiation (rfc1877) */ 9331ae349f5Scvs2svn case TY_SECONDARY_DNS: 9343edeb0c6SBrian Somers ipaddr.s_addr = *(u_int32_t *)(cp + 2); 935dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 9363edeb0c6SBrian Somers 93730c2f2ffSBrian Somers switch (mode_type) { 93830c2f2ffSBrian Somers case MODE_REQ: 9393edeb0c6SBrian Somers if (!IsAccepted(ipcp->cfg.ns.dns_neg)) { 9403edeb0c6SBrian Somers ipcp->my_reject |= (1 << (type - TY_ADJUST_NS)); 94130c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 94230c2f2ffSBrian Somers dec->rejend += length; 9431ae349f5Scvs2svn break; 9441ae349f5Scvs2svn } 9453edeb0c6SBrian Somers if (!gotdns) { 9463edeb0c6SBrian Somers dns[0] = ipcp->cfg.ns.dns[0]; 9473edeb0c6SBrian Somers dns[1] = ipcp->cfg.ns.dns[1]; 9483edeb0c6SBrian Somers if (dns[0].s_addr == INADDR_ANY && dns[1].s_addr == INADDR_ANY) 9493edeb0c6SBrian Somers getdns(ipcp, dns); 9503edeb0c6SBrian Somers gotdns = 1; 9513edeb0c6SBrian Somers } 9523edeb0c6SBrian Somers have_ip = dns[type == TY_PRIMARY_DNS ? 0 : 1]; 9531ae349f5Scvs2svn 9543edeb0c6SBrian Somers if (ipaddr.s_addr != have_ip.s_addr) { 9551ae349f5Scvs2svn /* 9563edeb0c6SBrian Somers * The client has got the DNS stuff wrong (first request) so 9571ae349f5Scvs2svn * we'll tell 'em how it is 9581ae349f5Scvs2svn */ 95930c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); /* copy first two (type/length) */ 9603edeb0c6SBrian Somers memcpy(dec->nakend + 2, &have_ip.s_addr, length - 2); 96130c2f2ffSBrian Somers dec->nakend += length; 9623edeb0c6SBrian Somers } else { 9631ae349f5Scvs2svn /* 9641ae349f5Scvs2svn * Otherwise they have it right (this time) so we send a ack packet 9651ae349f5Scvs2svn * back confirming it... end of story 9661ae349f5Scvs2svn */ 96730c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 96830c2f2ffSBrian Somers dec->ackend += length; 9693edeb0c6SBrian Somers } 9701ae349f5Scvs2svn break; 9711ae349f5Scvs2svn case MODE_NAK: /* what does this mean?? */ 9723edeb0c6SBrian Somers if (IsEnabled(ipcp->cfg.ns.dns_neg)) { 9733edeb0c6SBrian Somers gotdnsnak = 1; 9743edeb0c6SBrian Somers dnsnak[type == TY_PRIMARY_DNS ? 0 : 1].s_addr = 9753edeb0c6SBrian Somers *(u_int32_t *)(cp + 2); 9763edeb0c6SBrian Somers } 9771ae349f5Scvs2svn break; 9783edeb0c6SBrian Somers case MODE_REJ: /* Can't do much, stop asking */ 9793edeb0c6SBrian Somers ipcp->peer_reject |= (1 << (type - TY_ADJUST_NS)); 9801ae349f5Scvs2svn break; 9811ae349f5Scvs2svn } 9821ae349f5Scvs2svn break; 9831ae349f5Scvs2svn 9843edeb0c6SBrian Somers case TY_PRIMARY_NBNS: /* M$ NetBIOS nameserver hack (rfc1877) */ 9851ae349f5Scvs2svn case TY_SECONDARY_NBNS: 9863edeb0c6SBrian Somers ipaddr.s_addr = *(u_int32_t *)(cp + 2); 987dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 9883edeb0c6SBrian Somers 98930c2f2ffSBrian Somers switch (mode_type) { 99030c2f2ffSBrian Somers case MODE_REQ: 9913edeb0c6SBrian Somers have_ip.s_addr = 9923edeb0c6SBrian Somers ipcp->cfg.ns.nbns[type == TY_PRIMARY_NBNS ? 0 : 1].s_addr; 9933edeb0c6SBrian Somers 9943edeb0c6SBrian Somers if (have_ip.s_addr == INADDR_ANY) { 995dd7e2610SBrian Somers log_Printf(LogIPCP, "NBNS REQ - rejected - nbns not set\n"); 9963edeb0c6SBrian Somers ipcp->my_reject |= (1 << (type - TY_ADJUST_NS)); 99730c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 99830c2f2ffSBrian Somers dec->rejend += length; 9991ae349f5Scvs2svn break; 10001ae349f5Scvs2svn } 10013edeb0c6SBrian Somers 10023edeb0c6SBrian Somers if (ipaddr.s_addr != have_ip.s_addr) { 100330c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 10043edeb0c6SBrian Somers memcpy(dec->nakend+2, &have_ip.s_addr, length); 100530c2f2ffSBrian Somers dec->nakend += length; 10063edeb0c6SBrian Somers } else { 100730c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 100830c2f2ffSBrian Somers dec->ackend += length; 10093edeb0c6SBrian Somers } 10101ae349f5Scvs2svn break; 10111ae349f5Scvs2svn case MODE_NAK: 1012dd7e2610SBrian Somers log_Printf(LogIPCP, "MS NBNS req %d - NAK??\n", type); 10131ae349f5Scvs2svn break; 10141ae349f5Scvs2svn case MODE_REJ: 1015dd7e2610SBrian Somers log_Printf(LogIPCP, "MS NBNS req %d - REJ??\n", type); 10161ae349f5Scvs2svn break; 10171ae349f5Scvs2svn } 10181ae349f5Scvs2svn break; 10191ae349f5Scvs2svn 10201ae349f5Scvs2svn default: 102130c2f2ffSBrian Somers if (mode_type != MODE_NOP) { 102283d1af55SBrian Somers ipcp->my_reject |= (1 << type); 102330c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 102430c2f2ffSBrian Somers dec->rejend += length; 102530c2f2ffSBrian Somers } 10261ae349f5Scvs2svn break; 10271ae349f5Scvs2svn } 10281ae349f5Scvs2svn plen -= length; 10291ae349f5Scvs2svn cp += length; 10301ae349f5Scvs2svn } 10311342caedSBrian Somers 10323edeb0c6SBrian Somers if (gotdnsnak) 10333edeb0c6SBrian Somers if (!setdns(ipcp, dnsnak)) { 10343edeb0c6SBrian Somers ipcp->peer_reject |= (1 << (TY_PRIMARY_DNS - TY_ADJUST_NS)); 10353edeb0c6SBrian Somers ipcp->peer_reject |= (1 << (TY_SECONDARY_DNS - TY_ADJUST_NS)); 10363edeb0c6SBrian Somers } 10373edeb0c6SBrian Somers 1038e43ebac1SBrian Somers if (mode_type != MODE_NOP) { 10391342caedSBrian Somers if (dec->rejend != dec->rej) { 10401342caedSBrian Somers /* rejects are preferred */ 10411342caedSBrian Somers dec->ackend = dec->ack; 10421342caedSBrian Somers dec->nakend = dec->nak; 10431342caedSBrian Somers } else if (dec->nakend != dec->nak) 10441342caedSBrian Somers /* then NAKs */ 10451342caedSBrian Somers dec->ackend = dec->ack; 10461ae349f5Scvs2svn } 1047e43ebac1SBrian Somers } 10481ae349f5Scvs2svn 10491ae349f5Scvs2svn void 1050dd7e2610SBrian Somers ipcp_Input(struct ipcp *ipcp, struct mbuf * bp) 10511ae349f5Scvs2svn { 10527308ec68SBrian Somers /* Got PROTO_IPCP from link */ 1053dd7e2610SBrian Somers fsm_Input(&ipcp->fsm, bp); 10541ae349f5Scvs2svn } 10551ae349f5Scvs2svn 10561ae349f5Scvs2svn int 1057dd7e2610SBrian Somers ipcp_UseHisaddr(struct bundle *bundle, const char *hisaddr, int setaddr) 10581ae349f5Scvs2svn { 10595828db6dSBrian Somers struct ipcp *ipcp = &bundle->ncp.ipcp; 10605828db6dSBrian Somers 10617308ec68SBrian Somers /* Use `hisaddr' for the peers address (set iface if `setaddr') */ 10625828db6dSBrian Somers memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 10635828db6dSBrian Somers iplist_reset(&ipcp->cfg.peer_list); 10641ae349f5Scvs2svn if (strpbrk(hisaddr, ",-")) { 10655828db6dSBrian Somers iplist_setsrc(&ipcp->cfg.peer_list, hisaddr); 10665828db6dSBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 10675828db6dSBrian Somers iplist_setrandpos(&ipcp->cfg.peer_list); 106830c2f2ffSBrian Somers ipcp->peer_ip = ChooseHisAddr(bundle, ipcp->my_ip); 10695828db6dSBrian Somers if (ipcp->peer_ip.s_addr == INADDR_ANY) { 1070dd7e2610SBrian Somers log_Printf(LogWARN, "%s: None available !\n", ipcp->cfg.peer_list.src); 10711ae349f5Scvs2svn return(0); 10721ae349f5Scvs2svn } 10735828db6dSBrian Somers ipcp->cfg.peer_range.ipaddr.s_addr = ipcp->peer_ip.s_addr; 10745828db6dSBrian Somers ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 10755828db6dSBrian Somers ipcp->cfg.peer_range.width = 32; 10761ae349f5Scvs2svn } else { 1077dd7e2610SBrian Somers log_Printf(LogWARN, "%s: Invalid range !\n", hisaddr); 10781ae349f5Scvs2svn return 0; 10791ae349f5Scvs2svn } 10805828db6dSBrian Somers } else if (ParseAddr(ipcp, 1, &hisaddr, &ipcp->cfg.peer_range.ipaddr, 10815828db6dSBrian Somers &ipcp->cfg.peer_range.mask, 10825828db6dSBrian Somers &ipcp->cfg.peer_range.width) != 0) { 10835828db6dSBrian Somers ipcp->peer_ip.s_addr = ipcp->cfg.peer_range.ipaddr.s_addr; 10841ae349f5Scvs2svn 108530c2f2ffSBrian Somers if (setaddr && ipcp_SetIPaddress(bundle, ipcp->cfg.my_range.ipaddr, 108630c2f2ffSBrian Somers ipcp->cfg.peer_range.ipaddr, 0) < 0) { 10875828db6dSBrian Somers ipcp->cfg.my_range.ipaddr.s_addr = INADDR_ANY; 10885828db6dSBrian Somers ipcp->cfg.peer_range.ipaddr.s_addr = INADDR_ANY; 10891ae349f5Scvs2svn return 0; 10901ae349f5Scvs2svn } 10911ae349f5Scvs2svn } else 10921ae349f5Scvs2svn return 0; 10931ae349f5Scvs2svn 10941ae349f5Scvs2svn return 1; 10951ae349f5Scvs2svn } 1096