1af57ed9fSAtsushi Murai /* 2af57ed9fSAtsushi Murai * PPP IP Control Protocol (IPCP) Module 3af57ed9fSAtsushi Murai * 4af57ed9fSAtsushi Murai * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 5af57ed9fSAtsushi Murai * 6af57ed9fSAtsushi Murai * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 7af57ed9fSAtsushi Murai * 8af57ed9fSAtsushi Murai * Redistribution and use in source and binary forms are permitted 9af57ed9fSAtsushi Murai * provided that the above copyright notice and this paragraph are 10af57ed9fSAtsushi Murai * duplicated in all such forms and that any documentation, 11af57ed9fSAtsushi Murai * advertising materials, and other materials related to such 12af57ed9fSAtsushi Murai * distribution and use acknowledge that the software was developed 13af57ed9fSAtsushi Murai * by the Internet Initiative Japan, Inc. The name of the 14af57ed9fSAtsushi Murai * IIJ may not be used to endorse or promote products derived 15af57ed9fSAtsushi Murai * from this software without specific prior written permission. 16af57ed9fSAtsushi Murai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17af57ed9fSAtsushi Murai * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18af57ed9fSAtsushi Murai * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19af57ed9fSAtsushi Murai * 20897f9429SBrian Somers * $Id: ipcp.c,v 1.57 1998/06/16 19:40:38 brian Exp $ 21af57ed9fSAtsushi Murai * 22af57ed9fSAtsushi Murai * TODO: 23897f9429SBrian Somers * o More RFC1772 backward compatibility 24af57ed9fSAtsushi Murai */ 2575240ed1SBrian Somers #include <sys/param.h> 265b4c5b00SBrian Somers #include <netinet/in_systm.h> 275b4c5b00SBrian Somers #include <netinet/in.h> 285b4c5b00SBrian Somers #include <netinet/ip.h> 295b4c5b00SBrian Somers #include <arpa/inet.h> 305b4c5b00SBrian Somers #include <sys/socket.h> 3175240ed1SBrian Somers #include <netdb.h> 32455aabc3SBrian Somers #include <net/if.h> 33455aabc3SBrian Somers #include <sys/sockio.h> 341fa665f5SBrian Somers #include <sys/un.h> 3575240ed1SBrian Somers 363edeb0c6SBrian Somers #include <fcntl.h> 373edeb0c6SBrian Somers #include <resolv.h> 38d1a3ea47SBrian Somers #include <stdlib.h> 3975240ed1SBrian Somers #include <string.h> 40455aabc3SBrian Somers #include <sys/errno.h> 416140ba11SBrian Somers #include <termios.h> 4275240ed1SBrian Somers #include <unistd.h> 4375240ed1SBrian Somers 44c9e11a11SBrian Somers #include "defs.h" 45b6e82f33SBrian Somers #include "command.h" 4675240ed1SBrian Somers #include "mbuf.h" 4775240ed1SBrian Somers #include "log.h" 4875240ed1SBrian Somers #include "timer.h" 49af57ed9fSAtsushi Murai #include "fsm.h" 50af57ed9fSAtsushi Murai #include "lcpproto.h" 51af57ed9fSAtsushi Murai #include "lcp.h" 52bcc332bdSBrian Somers #include "iplist.h" 539a0b991fSBrian Somers #include "throughput.h" 541ae349f5Scvs2svn #include "slcompress.h" 55eaa4df37SBrian Somers #include "ipcp.h" 569c97abd8SBrian 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" 72610b185fSBrian Somers #include "route.h" 73af57ed9fSAtsushi Murai 74503a7782SBrian Somers #undef REJECTED 75503a7782SBrian Somers #define REJECTED(p, x) ((p)->peer_reject & (1<<(x))) 763edeb0c6SBrian Somers #define issep(ch) ((ch) == ' ' || (ch) == '\t') 773edeb0c6SBrian Somers #define isip(ch) (((ch) >= '0' && (ch) <= '9') || (ch) == '.') 78d8e55738SJordan K. Hubbard 7929e275ceSBrian Somers struct compreq { 8029e275ceSBrian Somers u_short proto; 8129e275ceSBrian Somers u_char slots; 8229e275ceSBrian Somers u_char compcid; 8329e275ceSBrian Somers }; 8475240ed1SBrian Somers 856f384573SBrian Somers static int IpcpLayerUp(struct fsm *); 861ae349f5Scvs2svn static void IpcpLayerDown(struct fsm *); 87927145beSBrian Somers static void IpcpLayerStart(struct fsm *); 88927145beSBrian Somers static void IpcpLayerFinish(struct fsm *); 89927145beSBrian Somers static void IpcpInitRestartCounter(struct fsm *); 907308ec68SBrian Somers static void IpcpSendConfigReq(struct fsm *); 912267893fSBrian Somers static void IpcpSentTerminateReq(struct fsm *); 922267893fSBrian Somers static void IpcpSendTerminateAck(struct fsm *, u_char); 9330c2f2ffSBrian Somers static void IpcpDecodeConfig(struct fsm *, u_char *, int, int, 9430c2f2ffSBrian Somers struct fsm_decode *); 95af57ed9fSAtsushi Murai 9683d1af55SBrian Somers static struct fsm_callbacks ipcp_Callbacks = { 97af57ed9fSAtsushi Murai IpcpLayerUp, 98af57ed9fSAtsushi Murai IpcpLayerDown, 99af57ed9fSAtsushi Murai IpcpLayerStart, 100af57ed9fSAtsushi Murai IpcpLayerFinish, 101af57ed9fSAtsushi Murai IpcpInitRestartCounter, 102af57ed9fSAtsushi Murai IpcpSendConfigReq, 1032267893fSBrian Somers IpcpSentTerminateReq, 104af57ed9fSAtsushi Murai IpcpSendTerminateAck, 105af57ed9fSAtsushi Murai IpcpDecodeConfig, 106dd7e2610SBrian Somers fsm_NullRecvResetReq, 107dd7e2610SBrian Somers fsm_NullRecvResetAck 108af57ed9fSAtsushi Murai }; 109af57ed9fSAtsushi Murai 110b6e82f33SBrian Somers static const char *cftypes[] = { 1119e836af5SBrian Somers /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */ 1129e836af5SBrian Somers "???", 1139e836af5SBrian Somers "IPADDRS", /* 1: IP-Addresses */ /* deprecated */ 1149e836af5SBrian Somers "COMPPROTO", /* 2: IP-Compression-Protocol */ 1159e836af5SBrian Somers "IPADDR", /* 3: IP-Address */ 116af57ed9fSAtsushi Murai }; 117af57ed9fSAtsushi Murai 11870ee81ffSBrian Somers #define NCFTYPES (sizeof cftypes/sizeof cftypes[0]) 1199e836af5SBrian Somers 120b6e82f33SBrian Somers static const char *cftypes128[] = { 1219e836af5SBrian Somers /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */ 1229e836af5SBrian Somers "???", 1239e836af5SBrian Somers "PRIDNS", /* 129: Primary DNS Server Address */ 1249e836af5SBrian Somers "PRINBNS", /* 130: Primary NBNS Server Address */ 1259e836af5SBrian Somers "SECDNS", /* 131: Secondary DNS Server Address */ 1269e836af5SBrian Somers "SECNBNS", /* 132: Secondary NBNS Server Address */ 1279e836af5SBrian Somers }; 1289e836af5SBrian Somers 12970ee81ffSBrian Somers #define NCFTYPES128 (sizeof cftypes128/sizeof cftypes128[0]) 1309e836af5SBrian Somers 1319a0b991fSBrian Somers void 1325828db6dSBrian Somers ipcp_AddInOctets(struct ipcp *ipcp, int n) 133af57ed9fSAtsushi Murai { 1345828db6dSBrian Somers throughput_addin(&ipcp->throughput, n); 135af57ed9fSAtsushi Murai } 136af57ed9fSAtsushi Murai 1379a0b991fSBrian Somers void 1385828db6dSBrian Somers ipcp_AddOutOctets(struct ipcp *ipcp, int n) 139af57ed9fSAtsushi Murai { 1405828db6dSBrian Somers throughput_addout(&ipcp->throughput, n); 1411ae349f5Scvs2svn } 1421ae349f5Scvs2svn 1433edeb0c6SBrian Somers static void 1443edeb0c6SBrian Somers getdns(struct ipcp *ipcp, struct in_addr addr[2]) 1453edeb0c6SBrian Somers { 1463edeb0c6SBrian Somers FILE *fp; 1473edeb0c6SBrian Somers 1483edeb0c6SBrian Somers addr[0].s_addr = addr[1].s_addr = INADDR_ANY; 1493edeb0c6SBrian Somers if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { 1503edeb0c6SBrian Somers char buf[LINE_LEN], *cp, *end; 1513edeb0c6SBrian Somers int n; 1523edeb0c6SBrian Somers 1533edeb0c6SBrian Somers n = 0; 1543edeb0c6SBrian Somers buf[sizeof buf - 1] = '\0'; 1553edeb0c6SBrian Somers while (fgets(buf, sizeof buf - 1, fp)) { 1563edeb0c6SBrian Somers if (!strncmp(buf, "nameserver", 10) && issep(buf[10])) { 1573edeb0c6SBrian Somers for (cp = buf + 11; issep(*cp); cp++) 1583edeb0c6SBrian Somers ; 1593edeb0c6SBrian Somers for (end = cp; isip(*end); end++) 1603edeb0c6SBrian Somers ; 1613edeb0c6SBrian Somers *end = '\0'; 1623edeb0c6SBrian Somers if (inet_aton(cp, addr+n) && ++n == 2) 1633edeb0c6SBrian Somers break; 1643edeb0c6SBrian Somers } 1653edeb0c6SBrian Somers } 1663edeb0c6SBrian Somers if (n == 1) 1673edeb0c6SBrian Somers addr[1] = addr[0]; 1683edeb0c6SBrian Somers fclose(fp); 1693edeb0c6SBrian Somers } 1703edeb0c6SBrian Somers } 1713edeb0c6SBrian Somers 1723edeb0c6SBrian Somers static int 1733edeb0c6SBrian Somers setdns(struct ipcp *ipcp, struct in_addr addr[2]) 1743edeb0c6SBrian Somers { 1753edeb0c6SBrian Somers FILE *fp; 1763edeb0c6SBrian Somers char wbuf[LINE_LEN + 54]; 1773edeb0c6SBrian Somers int wlen; 1783edeb0c6SBrian Somers 1793edeb0c6SBrian Somers if (addr[0].s_addr == INADDR_ANY || addr[1].s_addr == INADDR_ANY) { 1803edeb0c6SBrian Somers struct in_addr old[2]; 1813edeb0c6SBrian Somers 1823edeb0c6SBrian Somers getdns(ipcp, old); 1833edeb0c6SBrian Somers if (addr[0].s_addr == INADDR_ANY) 1843edeb0c6SBrian Somers addr[0] = old[0]; 1853edeb0c6SBrian Somers if (addr[1].s_addr == INADDR_ANY) 1863edeb0c6SBrian Somers addr[1] = old[1]; 1873edeb0c6SBrian Somers } 1883edeb0c6SBrian Somers 1893edeb0c6SBrian Somers if (addr[0].s_addr == INADDR_ANY && addr[1].s_addr == INADDR_ANY) { 190dd7e2610SBrian Somers log_Printf(LogWARN, "%s not modified: All nameservers NAKd\n", 1913edeb0c6SBrian Somers _PATH_RESCONF); 1923edeb0c6SBrian Somers return 0; 1933edeb0c6SBrian Somers } 1943edeb0c6SBrian Somers 1953edeb0c6SBrian Somers wlen = 0; 1963edeb0c6SBrian Somers if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { 1973edeb0c6SBrian Somers char buf[LINE_LEN]; 1983edeb0c6SBrian Somers int len; 1993edeb0c6SBrian Somers 2003edeb0c6SBrian Somers buf[sizeof buf - 1] = '\0'; 2013edeb0c6SBrian Somers while (fgets(buf, sizeof buf - 1, fp)) { 2023edeb0c6SBrian Somers if (strncmp(buf, "nameserver", 10) || !issep(buf[10])) { 2033edeb0c6SBrian Somers len = strlen(buf); 2043edeb0c6SBrian Somers if (len > sizeof wbuf - wlen) { 205dd7e2610SBrian Somers log_Printf(LogWARN, "%s: Can only cope with max file size %d\n", 2063edeb0c6SBrian Somers _PATH_RESCONF, LINE_LEN); 2073edeb0c6SBrian Somers fclose(fp); 2083edeb0c6SBrian Somers return 0; 2093edeb0c6SBrian Somers } 2103edeb0c6SBrian Somers memcpy(wbuf + wlen, buf, len); 2113edeb0c6SBrian Somers wlen += len; 2123edeb0c6SBrian Somers } 2133edeb0c6SBrian Somers } 2143edeb0c6SBrian Somers fclose(fp); 2153edeb0c6SBrian Somers } 2163edeb0c6SBrian Somers 2173edeb0c6SBrian Somers if (addr[0].s_addr != INADDR_ANY) { 2183edeb0c6SBrian Somers snprintf(wbuf + wlen, sizeof wbuf - wlen, "nameserver %s\n", 2193edeb0c6SBrian Somers inet_ntoa(addr[0])); 220dd7e2610SBrian Somers log_Printf(LogIPCP, "Primary nameserver set to %s", wbuf + wlen + 11); 2213edeb0c6SBrian Somers wlen += strlen(wbuf + wlen); 2223edeb0c6SBrian Somers } 2233edeb0c6SBrian Somers 2243edeb0c6SBrian Somers if (addr[1].s_addr != INADDR_ANY && addr[1].s_addr != addr[0].s_addr) { 2253edeb0c6SBrian Somers snprintf(wbuf + wlen, sizeof wbuf - wlen, "nameserver %s\n", 2263edeb0c6SBrian Somers inet_ntoa(addr[1])); 227dd7e2610SBrian Somers log_Printf(LogIPCP, "Secondary nameserver set to %s", wbuf + wlen + 11); 2283edeb0c6SBrian Somers wlen += strlen(wbuf + wlen); 2293edeb0c6SBrian Somers } 2303edeb0c6SBrian Somers 2313edeb0c6SBrian Somers if (wlen) { 2323edeb0c6SBrian Somers int fd; 2333edeb0c6SBrian Somers 2343edeb0c6SBrian Somers if ((fd = ID0open(_PATH_RESCONF, O_WRONLY|O_CREAT, 0644)) != -1) { 2353edeb0c6SBrian Somers if (write(fd, wbuf, wlen) != wlen) { 236dd7e2610SBrian Somers log_Printf(LogERROR, "setdns: write(): %s\n", strerror(errno)); 2373edeb0c6SBrian Somers close(fd); 2383edeb0c6SBrian Somers return 0; 2393edeb0c6SBrian Somers } 2403edeb0c6SBrian Somers if (ftruncate(fd, wlen) == -1) { 241dd7e2610SBrian Somers log_Printf(LogERROR, "setdns: truncate(): %s\n", strerror(errno)); 2423edeb0c6SBrian Somers close(fd); 2433edeb0c6SBrian Somers return 0; 2443edeb0c6SBrian Somers } 2453edeb0c6SBrian Somers close(fd); 2463edeb0c6SBrian Somers } else { 247dd7e2610SBrian Somers log_Printf(LogERROR, "setdns: open(): %s\n", strerror(errno)); 2483edeb0c6SBrian Somers return 0; 2493edeb0c6SBrian Somers } 2503edeb0c6SBrian Somers } 2513edeb0c6SBrian Somers 2523edeb0c6SBrian Somers return 1; 253af57ed9fSAtsushi Murai } 254af57ed9fSAtsushi Murai 255274e766cSBrian Somers int 256dd7e2610SBrian Somers ipcp_Show(struct cmdargs const *arg) 257af57ed9fSAtsushi Murai { 258610b185fSBrian Somers struct ipcp *ipcp = &arg->bundle->ncp.ipcp; 259af57ed9fSAtsushi Murai 260610b185fSBrian Somers prompt_Printf(arg->prompt, "%s [%s]\n", ipcp->fsm.name, 261610b185fSBrian Somers State2Nam(ipcp->fsm.state)); 262610b185fSBrian Somers if (ipcp->fsm.state == ST_OPENED) { 263b6217683SBrian Somers prompt_Printf(arg->prompt, " His side: %s, %s\n", 264610b185fSBrian Somers inet_ntoa(ipcp->peer_ip), vj2asc(ipcp->peer_compproto)); 265b6217683SBrian Somers prompt_Printf(arg->prompt, " My side: %s, %s\n", 266610b185fSBrian Somers inet_ntoa(ipcp->my_ip), vj2asc(ipcp->my_compproto)); 267d1a3ea47SBrian Somers } 2685b4c5b00SBrian Somers 269610b185fSBrian Somers if (ipcp->route) { 270610b185fSBrian Somers prompt_Printf(arg->prompt, "\n"); 271610b185fSBrian Somers route_ShowSticky(arg->prompt, ipcp->route); 2721ae349f5Scvs2svn } 273927145beSBrian Somers 274b6217683SBrian Somers prompt_Printf(arg->prompt, "\nDefaults:\n"); 27550abd4c8SBrian Somers prompt_Printf(arg->prompt, " My Address: %s/%d", 276610b185fSBrian Somers inet_ntoa(ipcp->cfg.my_range.ipaddr), ipcp->cfg.my_range.width); 27750abd4c8SBrian Somers 278610b185fSBrian Somers if (ipcp->cfg.HaveTriggerAddress) 27950abd4c8SBrian Somers prompt_Printf(arg->prompt, " (trigger with %s)", 280610b185fSBrian Somers inet_ntoa(ipcp->cfg.TriggerAddress)); 28150abd4c8SBrian Somers prompt_Printf(arg->prompt, "\n VJ compression: %s (%d slots %s slot " 282610b185fSBrian Somers "compression)\n", command_ShowNegval(ipcp->cfg.vj.neg), 283610b185fSBrian Somers ipcp->cfg.vj.slots, ipcp->cfg.vj.slotcomp ? "with" : "without"); 28450abd4c8SBrian Somers 285610b185fSBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) 286b6217683SBrian Somers prompt_Printf(arg->prompt, " His Address: %s\n", 287610b185fSBrian Somers ipcp->cfg.peer_list.src); 2881ae349f5Scvs2svn else 289b6217683SBrian Somers prompt_Printf(arg->prompt, " His Address: %s/%d\n", 290610b185fSBrian Somers inet_ntoa(ipcp->cfg.peer_range.ipaddr), 291610b185fSBrian Somers ipcp->cfg.peer_range.width); 29250abd4c8SBrian Somers 2933edeb0c6SBrian Somers prompt_Printf(arg->prompt, " DNS: %s, ", 294610b185fSBrian Somers inet_ntoa(ipcp->cfg.ns.dns[0])); 295610b185fSBrian Somers prompt_Printf(arg->prompt, "%s, %s\n", inet_ntoa(ipcp->cfg.ns.dns[1]), 296610b185fSBrian Somers command_ShowNegval(ipcp->cfg.ns.dns_neg)); 2973edeb0c6SBrian Somers prompt_Printf(arg->prompt, " NetBIOS NS: %s, ", 298610b185fSBrian Somers inet_ntoa(ipcp->cfg.ns.nbns[0])); 299610b185fSBrian Somers prompt_Printf(arg->prompt, "%s\n", inet_ntoa(ipcp->cfg.ns.nbns[1])); 3001342caedSBrian Somers 301b6217683SBrian Somers prompt_Printf(arg->prompt, "\n"); 302610b185fSBrian Somers throughput_disp(&ipcp->throughput, arg->prompt); 3039a0b991fSBrian Somers 304927145beSBrian Somers return 0; 305af57ed9fSAtsushi Murai } 306af57ed9fSAtsushi Murai 307d1a3ea47SBrian Somers int 308dd7e2610SBrian Somers ipcp_vjset(struct cmdargs const *arg) 309d1a3ea47SBrian Somers { 31025092092SBrian Somers if (arg->argc != arg->argn+2) 311d1a3ea47SBrian Somers return -1; 31225092092SBrian Somers if (!strcasecmp(arg->argv[arg->argn], "slots")) { 313d1a3ea47SBrian Somers int slots; 314d1a3ea47SBrian Somers 31525092092SBrian Somers slots = atoi(arg->argv[arg->argn+1]); 316d1a3ea47SBrian Somers if (slots < 4 || slots > 16) 317d1a3ea47SBrian Somers return 1; 3181342caedSBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slots = slots; 319d1a3ea47SBrian Somers return 0; 32025092092SBrian Somers } else if (!strcasecmp(arg->argv[arg->argn], "slotcomp")) { 32125092092SBrian Somers if (!strcasecmp(arg->argv[arg->argn+1], "on")) 3221342caedSBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 1; 32325092092SBrian Somers else if (!strcasecmp(arg->argv[arg->argn+1], "off")) 3241342caedSBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 0; 325d1a3ea47SBrian Somers else 326d1a3ea47SBrian Somers return 2; 327d1a3ea47SBrian Somers return 0; 328d1a3ea47SBrian Somers } 329d1a3ea47SBrian Somers return -1; 330d1a3ea47SBrian Somers } 331d1a3ea47SBrian Somers 3321ae349f5Scvs2svn void 3336d666775SBrian Somers ipcp_Init(struct ipcp *ipcp, struct bundle *bundle, struct link *l, 3346d666775SBrian Somers const struct fsm_parent *parent) 335d1a3ea47SBrian Somers { 336503a7782SBrian Somers struct hostent *hp; 337503a7782SBrian Somers char name[MAXHOSTNAMELEN]; 3383b0f8d2eSBrian Somers static const char *timer_names[] = 3393b0f8d2eSBrian Somers {"IPCP restart", "IPCP openmode", "IPCP stopped"}; 34029e275ceSBrian Somers 3413b0f8d2eSBrian Somers fsm_Init(&ipcp->fsm, "IPCP", PROTO_IPCP, 1, IPCP_MAXCODE, 10, LogIPCP, 3423b0f8d2eSBrian Somers bundle, l, parent, &ipcp_Callbacks, timer_names); 343503a7782SBrian Somers 344610b185fSBrian Somers ipcp->route = NULL; 3451342caedSBrian Somers ipcp->cfg.vj.slots = DEF_VJ_STATES; 3461342caedSBrian Somers ipcp->cfg.vj.slotcomp = 1; 347503a7782SBrian Somers memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range); 348503a7782SBrian Somers if (gethostname(name, sizeof name) == 0) { 349503a7782SBrian Somers hp = gethostbyname(name); 350503a7782SBrian Somers if (hp && hp->h_addrtype == AF_INET) { 351503a7782SBrian Somers memcpy(&ipcp->cfg.my_range.ipaddr.s_addr, hp->h_addr, hp->h_length); 352503a7782SBrian Somers ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 353503a7782SBrian Somers ipcp->cfg.peer_range.width = 32; 354d1a3ea47SBrian Somers } 355503a7782SBrian Somers } 35630c2f2ffSBrian Somers ipcp->cfg.netmask.s_addr = INADDR_ANY; 357503a7782SBrian Somers memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 358503a7782SBrian Somers iplist_setsrc(&ipcp->cfg.peer_list, ""); 359503a7782SBrian Somers ipcp->cfg.HaveTriggerAddress = 0; 360503a7782SBrian Somers 3613edeb0c6SBrian Somers ipcp->cfg.ns.dns[0].s_addr = INADDR_ANY; 3623edeb0c6SBrian Somers ipcp->cfg.ns.dns[1].s_addr = INADDR_ANY; 3633edeb0c6SBrian Somers ipcp->cfg.ns.dns_neg = 0; 3643edeb0c6SBrian Somers ipcp->cfg.ns.nbns[0].s_addr = INADDR_ANY; 3653edeb0c6SBrian Somers ipcp->cfg.ns.nbns[1].s_addr = INADDR_ANY; 366cd9647a1SBrian Somers 367cd9647a1SBrian Somers ipcp->cfg.fsmretry = DEF_FSMRETRY; 3681342caedSBrian Somers ipcp->cfg.vj.neg = NEG_ENABLED|NEG_ACCEPTED; 369503a7782SBrian Somers 370eaa4df37SBrian Somers memset(&ipcp->vj, '\0', sizeof ipcp->vj); 371eaa4df37SBrian Somers 372503a7782SBrian Somers ipcp->my_ifip.s_addr = INADDR_ANY; 373503a7782SBrian Somers ipcp->peer_ifip.s_addr = INADDR_ANY; 374503a7782SBrian Somers 375fdf61171SBrian Somers throughput_init(&ipcp->throughput); 376503a7782SBrian Somers ipcp_Setup(ipcp); 377d1a3ea47SBrian Somers } 378d1a3ea47SBrian Somers 379af57ed9fSAtsushi Murai void 380ce828a6eSBrian Somers ipcp_SetLink(struct ipcp *ipcp, struct link *l) 381af57ed9fSAtsushi Murai { 382ce828a6eSBrian Somers ipcp->fsm.link = l; 383af57ed9fSAtsushi Murai } 384549d663dSAtsushi Murai 385ce828a6eSBrian Somers void 386503a7782SBrian Somers ipcp_Setup(struct ipcp *ipcp) 387503a7782SBrian Somers { 388503a7782SBrian Somers int pos; 389503a7782SBrian Somers 390503a7782SBrian Somers ipcp->fsm.open_mode = 0; 3915454ccd9SBrian Somers ipcp->fsm.maxconfig = 10; 392503a7782SBrian Somers 393503a7782SBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 394503a7782SBrian Somers if (ipcp->my_ifip.s_addr != INADDR_ANY && 395503a7782SBrian Somers (pos = iplist_ip2pos(&ipcp->cfg.peer_list, ipcp->my_ifip)) != -1) 396503a7782SBrian Somers ipcp->cfg.peer_range.ipaddr = iplist_setcurpos(&ipcp->cfg.peer_list, pos); 397503a7782SBrian Somers else 398503a7782SBrian Somers ipcp->cfg.peer_range.ipaddr = iplist_setrandpos(&ipcp->cfg.peer_list); 399503a7782SBrian Somers ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 400503a7782SBrian Somers ipcp->cfg.peer_range.width = 32; 401503a7782SBrian Somers } 402503a7782SBrian Somers 403503a7782SBrian Somers ipcp->heis1172 = 0; 404503a7782SBrian Somers 405503a7782SBrian Somers ipcp->peer_ip = ipcp->cfg.peer_range.ipaddr; 406503a7782SBrian Somers ipcp->peer_compproto = 0; 4071ae349f5Scvs2svn 4088390b576SBrian Somers if (ipcp->cfg.HaveTriggerAddress) { 409549d663dSAtsushi Murai /* 4105b4c5b00SBrian Somers * Some implementations of PPP require that we send a 4115b4c5b00SBrian Somers * *special* value as our address, even though the rfc specifies 4125b4c5b00SBrian Somers * full negotiation (e.g. "0.0.0.0" or Not "0.0.0.0"). 413549d663dSAtsushi Murai */ 414503a7782SBrian Somers ipcp->my_ip = ipcp->cfg.TriggerAddress; 415dd7e2610SBrian Somers log_Printf(LogIPCP, "Using trigger address %s\n", 416503a7782SBrian Somers inet_ntoa(ipcp->cfg.TriggerAddress)); 4178390b576SBrian Somers } else if ((ipcp->my_ifip.s_addr & ipcp->cfg.my_range.mask.s_addr) == 4188390b576SBrian Somers (ipcp->cfg.my_range.ipaddr.s_addr & 4198390b576SBrian Somers ipcp->cfg.my_range.mask.s_addr)) 4208390b576SBrian Somers /* 4218390b576SBrian Somers * Otherwise, if we've been assigned an IP number before, we really 4228390b576SBrian Somers * want to keep the same IP number so that we can keep any existing 4238390b576SBrian Somers * connections that are bound to that IP. 4248390b576SBrian Somers */ 4258390b576SBrian Somers ipcp->my_ip = ipcp->my_ifip; 426af57ed9fSAtsushi Murai else 427503a7782SBrian Somers ipcp->my_ip = ipcp->cfg.my_range.ipaddr; 42829e275ceSBrian Somers 4291342caedSBrian Somers if (IsEnabled(ipcp->cfg.vj.neg)) 430503a7782SBrian Somers ipcp->my_compproto = (PROTO_VJCOMP << 16) + 4311342caedSBrian Somers ((ipcp->cfg.vj.slots - 1) << 8) + 4321342caedSBrian Somers ipcp->cfg.vj.slotcomp; 4331ae349f5Scvs2svn else 434503a7782SBrian Somers ipcp->my_compproto = 0; 4351342caedSBrian Somers sl_compress_init(&ipcp->vj.cslc, ipcp->cfg.vj.slots - 1); 43629e275ceSBrian Somers 437503a7782SBrian Somers ipcp->peer_reject = 0; 438503a7782SBrian Somers ipcp->my_reject = 0; 439503a7782SBrian Somers 440fdf61171SBrian Somers throughput_stop(&ipcp->throughput); 441503a7782SBrian Somers throughput_init(&ipcp->throughput); 4421ae349f5Scvs2svn } 4431ae349f5Scvs2svn 444455aabc3SBrian Somers static int 44530c2f2ffSBrian Somers ipcp_SetIPaddress(struct bundle *bundle, struct in_addr myaddr, 44630c2f2ffSBrian Somers struct in_addr hisaddr, int silent) 447455aabc3SBrian Somers { 448455aabc3SBrian Somers struct sockaddr_in *sock_in; 449455aabc3SBrian Somers int s; 450455aabc3SBrian Somers u_long mask, addr; 451455aabc3SBrian Somers struct ifaliasreq ifra; 452455aabc3SBrian Somers 453455aabc3SBrian Somers /* If given addresses are alreay set, then ignore this request */ 45430c2f2ffSBrian Somers if (bundle->ncp.ipcp.my_ifip.s_addr == myaddr.s_addr && 45530c2f2ffSBrian Somers bundle->ncp.ipcp.peer_ifip.s_addr == hisaddr.s_addr) 456455aabc3SBrian Somers return 0; 457455aabc3SBrian Somers 458dd7e2610SBrian Somers ipcp_CleanInterface(&bundle->ncp.ipcp); 45968a0f0ccSBrian Somers 460455aabc3SBrian Somers s = ID0socket(AF_INET, SOCK_DGRAM, 0); 461455aabc3SBrian Somers if (s < 0) { 462a33b2ef7SBrian Somers log_Printf(LogERROR, "SetIPaddress: socket(): %s\n", strerror(errno)); 463455aabc3SBrian Somers return (-1); 464455aabc3SBrian Somers } 465455aabc3SBrian Somers 466455aabc3SBrian Somers memset(&ifra, '\0', sizeof ifra); 467faefde08SBrian Somers strncpy(ifra.ifra_name, bundle->ifp.Name, sizeof ifra.ifra_name - 1); 468455aabc3SBrian Somers ifra.ifra_name[sizeof ifra.ifra_name - 1] = '\0'; 469455aabc3SBrian Somers 470455aabc3SBrian Somers /* Set interface address */ 471455aabc3SBrian Somers sock_in = (struct sockaddr_in *)&ifra.ifra_addr; 472455aabc3SBrian Somers sock_in->sin_family = AF_INET; 473455aabc3SBrian Somers sock_in->sin_addr = myaddr; 474455aabc3SBrian Somers sock_in->sin_len = sizeof *sock_in; 475455aabc3SBrian Somers 476455aabc3SBrian Somers /* Set destination address */ 477455aabc3SBrian Somers sock_in = (struct sockaddr_in *)&ifra.ifra_broadaddr; 478455aabc3SBrian Somers sock_in->sin_family = AF_INET; 479455aabc3SBrian Somers sock_in->sin_addr = hisaddr; 480455aabc3SBrian Somers sock_in->sin_len = sizeof *sock_in; 481455aabc3SBrian Somers 482455aabc3SBrian Somers addr = ntohl(myaddr.s_addr); 483455aabc3SBrian Somers if (IN_CLASSA(addr)) 484455aabc3SBrian Somers mask = IN_CLASSA_NET; 485455aabc3SBrian Somers else if (IN_CLASSB(addr)) 486455aabc3SBrian Somers mask = IN_CLASSB_NET; 487455aabc3SBrian Somers else 488455aabc3SBrian Somers mask = IN_CLASSC_NET; 489455aabc3SBrian Somers 490455aabc3SBrian Somers /* if subnet mask is given, use it instead of class mask */ 49130c2f2ffSBrian Somers if (bundle->ncp.ipcp.cfg.netmask.s_addr != INADDR_ANY && 49230c2f2ffSBrian Somers (ntohl(bundle->ncp.ipcp.cfg.netmask.s_addr) & mask) == mask) 49330c2f2ffSBrian Somers mask = ntohl(bundle->ncp.ipcp.cfg.netmask.s_addr); 494455aabc3SBrian Somers 495455aabc3SBrian Somers sock_in = (struct sockaddr_in *)&ifra.ifra_mask; 496455aabc3SBrian Somers sock_in->sin_family = AF_INET; 497455aabc3SBrian Somers sock_in->sin_addr.s_addr = htonl(mask); 498455aabc3SBrian Somers sock_in->sin_len = sizeof *sock_in; 499455aabc3SBrian Somers 500455aabc3SBrian Somers if (ID0ioctl(s, SIOCAIFADDR, &ifra) < 0) { 501455aabc3SBrian Somers if (!silent) 502a33b2ef7SBrian Somers log_Printf(LogERROR, "SetIPaddress: ioctl(SIOCAIFADDR): %s\n", 503455aabc3SBrian Somers strerror(errno)); 504455aabc3SBrian Somers close(s); 505455aabc3SBrian Somers return (-1); 506455aabc3SBrian Somers } 507455aabc3SBrian Somers 508610b185fSBrian Somers if (Enabled(bundle, OPT_SROUTES)) 509610b185fSBrian Somers route_Change(bundle, bundle->ncp.ipcp.route, myaddr, hisaddr); 510610b185fSBrian Somers 51130c2f2ffSBrian Somers bundle->ncp.ipcp.peer_ifip.s_addr = hisaddr.s_addr; 51230c2f2ffSBrian Somers bundle->ncp.ipcp.my_ifip.s_addr = myaddr.s_addr; 513455aabc3SBrian Somers 5141342caedSBrian Somers if (Enabled(bundle, OPT_PROXY)) 515dd7e2610SBrian Somers arp_SetProxy(bundle, bundle->ncp.ipcp.peer_ifip, s); 516455aabc3SBrian Somers 517455aabc3SBrian Somers close(s); 518455aabc3SBrian Somers return (0); 519455aabc3SBrian Somers } 520455aabc3SBrian Somers 521455aabc3SBrian Somers static struct in_addr 52230c2f2ffSBrian Somers ChooseHisAddr(struct bundle *bundle, const struct in_addr gw) 523455aabc3SBrian Somers { 524455aabc3SBrian Somers struct in_addr try; 525455aabc3SBrian Somers int f; 526455aabc3SBrian Somers 5275828db6dSBrian Somers for (f = 0; f < bundle->ncp.ipcp.cfg.peer_list.nItems; f++) { 5285828db6dSBrian Somers try = iplist_next(&bundle->ncp.ipcp.cfg.peer_list); 529dd7e2610SBrian Somers log_Printf(LogDEBUG, "ChooseHisAddr: Check item %d (%s)\n", 530455aabc3SBrian Somers f, inet_ntoa(try)); 53130c2f2ffSBrian Somers if (ipcp_SetIPaddress(bundle, gw, try, 1) == 0) { 532dd7e2610SBrian Somers log_Printf(LogIPCP, "Selected IP address %s\n", inet_ntoa(try)); 533455aabc3SBrian Somers break; 534455aabc3SBrian Somers } 535455aabc3SBrian Somers } 536455aabc3SBrian Somers 5375828db6dSBrian Somers if (f == bundle->ncp.ipcp.cfg.peer_list.nItems) { 538dd7e2610SBrian Somers log_Printf(LogDEBUG, "ChooseHisAddr: All addresses in use !\n"); 539455aabc3SBrian Somers try.s_addr = INADDR_ANY; 540455aabc3SBrian Somers } 541455aabc3SBrian Somers 542455aabc3SBrian Somers return try; 543af57ed9fSAtsushi Murai } 544af57ed9fSAtsushi Murai 545af57ed9fSAtsushi Murai static void 546944f7098SBrian Somers IpcpInitRestartCounter(struct fsm * fp) 547af57ed9fSAtsushi Murai { 5487308ec68SBrian Somers /* Set fsm timer load */ 549cd9647a1SBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 550cd9647a1SBrian Somers 551cd9647a1SBrian Somers fp->FsmTimer.load = ipcp->cfg.fsmretry * SECTICKS; 552af57ed9fSAtsushi Murai fp->restart = 5; 553af57ed9fSAtsushi Murai } 554af57ed9fSAtsushi Murai 555af57ed9fSAtsushi Murai static void 556944f7098SBrian Somers IpcpSendConfigReq(struct fsm *fp) 557af57ed9fSAtsushi Murai { 5587308ec68SBrian Somers /* Send config REQ please */ 5598c07a7b2SBrian Somers struct physical *p = link2physical(fp->link); 560aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 5613edeb0c6SBrian Somers u_char buff[24]; 5622267893fSBrian Somers struct lcp_opt *o; 563af57ed9fSAtsushi Murai 5642267893fSBrian Somers o = (struct lcp_opt *)buff; 56530c2f2ffSBrian Somers 566dd7e2610SBrian Somers if ((p && !physical_IsSync(p)) || !REJECTED(ipcp, TY_IPADDR)) { 5672267893fSBrian Somers *(u_int32_t *)o->data = ipcp->my_ip.s_addr; 5682267893fSBrian Somers INC_LCP_OPT(TY_IPADDR, 6, o); 5690053cc58SBrian Somers } 5700053cc58SBrian Somers 571e43ebac1SBrian Somers if (ipcp->my_compproto && !REJECTED(ipcp, TY_COMPPROTO)) { 57283d1af55SBrian Somers if (ipcp->heis1172) { 5732267893fSBrian Somers *(u_short *)o->data = htons(PROTO_VJCOMP); 5742267893fSBrian Somers INC_LCP_OPT(TY_COMPPROTO, 4, o); 5750053cc58SBrian Somers } else { 5762267893fSBrian Somers *(u_long *)o->data = htonl(ipcp->my_compproto); 5772267893fSBrian Somers INC_LCP_OPT(TY_COMPPROTO, 6, o); 5780053cc58SBrian Somers } 579af57ed9fSAtsushi Murai } 5802267893fSBrian Somers 5813edeb0c6SBrian Somers if (IsEnabled(ipcp->cfg.ns.dns_neg) && 5823edeb0c6SBrian Somers !REJECTED(ipcp, TY_PRIMARY_DNS - TY_ADJUST_NS) && 5833edeb0c6SBrian Somers !REJECTED(ipcp, TY_SECONDARY_DNS - TY_ADJUST_NS)) { 5843edeb0c6SBrian Somers struct in_addr dns[2]; 5853edeb0c6SBrian Somers getdns(ipcp, dns); 5863edeb0c6SBrian Somers *(u_int32_t *)o->data = dns[0].s_addr; 5873edeb0c6SBrian Somers INC_LCP_OPT(TY_PRIMARY_DNS, 6, o); 5883edeb0c6SBrian Somers *(u_int32_t *)o->data = dns[1].s_addr; 5893edeb0c6SBrian Somers INC_LCP_OPT(TY_SECONDARY_DNS, 6, o); 5903edeb0c6SBrian Somers } 5913edeb0c6SBrian Somers 592dd7e2610SBrian Somers fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff); 593af57ed9fSAtsushi Murai } 594af57ed9fSAtsushi Murai 595af57ed9fSAtsushi Murai static void 5962267893fSBrian Somers IpcpSentTerminateReq(struct fsm * fp) 597af57ed9fSAtsushi Murai { 5987308ec68SBrian Somers /* Term REQ just sent by FSM */ 599af57ed9fSAtsushi Murai } 600af57ed9fSAtsushi Murai 601af57ed9fSAtsushi Murai static void 6022267893fSBrian Somers IpcpSendTerminateAck(struct fsm *fp, u_char id) 603af57ed9fSAtsushi Murai { 6047308ec68SBrian Somers /* Send Term ACK please */ 605dd7e2610SBrian Somers fsm_Output(fp, CODE_TERMACK, id, NULL, 0); 606af57ed9fSAtsushi Murai } 607af57ed9fSAtsushi Murai 608af57ed9fSAtsushi Murai static void 609944f7098SBrian Somers IpcpLayerStart(struct fsm *fp) 610af57ed9fSAtsushi Murai { 6117308ec68SBrian Somers /* We're about to start up ! */ 612897f9429SBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 613897f9429SBrian Somers 614dd7e2610SBrian Somers log_Printf(LogIPCP, "%s: IpcpLayerStart.\n", fp->link->name); 615897f9429SBrian Somers throughput_start(&ipcp->throughput, "IPCP throughput", 616897f9429SBrian Somers Enabled(fp->bundle, OPT_THROUGHPUT)); 617455aabc3SBrian Somers 61881358fa3SBrian Somers /* This is where we should be setting up the interface in AUTO mode */ 619af57ed9fSAtsushi Murai } 620af57ed9fSAtsushi Murai 621af57ed9fSAtsushi Murai static void 622944f7098SBrian Somers IpcpLayerFinish(struct fsm *fp) 623af57ed9fSAtsushi Murai { 6247308ec68SBrian Somers /* We're now down */ 625897f9429SBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 626897f9429SBrian Somers 627dd7e2610SBrian Somers log_Printf(LogIPCP, "%s: IpcpLayerFinish.\n", fp->link->name); 628897f9429SBrian Somers throughput_stop(&ipcp->throughput); 629897f9429SBrian Somers throughput_log(&ipcp->throughput, LogIPCP, NULL); 6301ae349f5Scvs2svn } 6311ae349f5Scvs2svn 63268a0f0ccSBrian Somers void 633dd7e2610SBrian Somers ipcp_CleanInterface(struct ipcp *ipcp) 63468a0f0ccSBrian Somers { 63568a0f0ccSBrian Somers struct ifaliasreq ifra; 63668a0f0ccSBrian Somers struct sockaddr_in *me, *peer; 63768a0f0ccSBrian Somers int s; 63868a0f0ccSBrian Somers 63968a0f0ccSBrian Somers s = ID0socket(AF_INET, SOCK_DGRAM, 0); 64068a0f0ccSBrian Somers if (s < 0) { 641dd7e2610SBrian Somers log_Printf(LogERROR, "ipcp_CleanInterface: socket: %s\n", strerror(errno)); 64268a0f0ccSBrian Somers return; 64368a0f0ccSBrian Somers } 64468a0f0ccSBrian Somers 645610b185fSBrian Somers route_Clean(ipcp->fsm.bundle, ipcp->route); 646610b185fSBrian Somers 6471342caedSBrian Somers if (Enabled(ipcp->fsm.bundle, OPT_PROXY)) 648dd7e2610SBrian Somers arp_ClearProxy(ipcp->fsm.bundle, ipcp->peer_ifip, s); 64968a0f0ccSBrian Somers 650503a7782SBrian Somers if (ipcp->my_ifip.s_addr != INADDR_ANY || 651503a7782SBrian Somers ipcp->peer_ifip.s_addr != INADDR_ANY) { 65268a0f0ccSBrian Somers memset(&ifra, '\0', sizeof ifra); 653faefde08SBrian Somers strncpy(ifra.ifra_name, ipcp->fsm.bundle->ifp.Name, 654565e35e5SBrian Somers sizeof ifra.ifra_name - 1); 65568a0f0ccSBrian Somers ifra.ifra_name[sizeof ifra.ifra_name - 1] = '\0'; 65668a0f0ccSBrian Somers me = (struct sockaddr_in *)&ifra.ifra_addr; 65768a0f0ccSBrian Somers peer = (struct sockaddr_in *)&ifra.ifra_broadaddr; 65868a0f0ccSBrian Somers me->sin_family = peer->sin_family = AF_INET; 65968a0f0ccSBrian Somers me->sin_len = peer->sin_len = sizeof(struct sockaddr_in); 660503a7782SBrian Somers me->sin_addr = ipcp->my_ifip; 661503a7782SBrian Somers peer->sin_addr = ipcp->peer_ifip; 6620f8037a9SBrian Somers if (ID0ioctl(s, SIOCDIFADDR, &ifra) < 0) 663dd7e2610SBrian Somers log_Printf(LogERROR, "ipcp_CleanInterface: ioctl(SIOCDIFADDR): %s\n", 66468a0f0ccSBrian Somers strerror(errno)); 665503a7782SBrian Somers ipcp->my_ifip.s_addr = ipcp->peer_ifip.s_addr = INADDR_ANY; 66668a0f0ccSBrian Somers } 66768a0f0ccSBrian Somers 66868a0f0ccSBrian Somers close(s); 669af57ed9fSAtsushi Murai } 670af57ed9fSAtsushi Murai 671af57ed9fSAtsushi Murai static void 672944f7098SBrian Somers IpcpLayerDown(struct fsm *fp) 673af57ed9fSAtsushi Murai { 6747308ec68SBrian Somers /* About to come down */ 675aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 676455aabc3SBrian Somers const char *s; 677455aabc3SBrian Somers 678503a7782SBrian Somers s = inet_ntoa(ipcp->peer_ifip); 679dd7e2610SBrian Somers log_Printf(LogIPCP, "%s: IpcpLayerDown: %s\n", fp->link->name, s); 680455aabc3SBrian Somers 681455aabc3SBrian Somers /* 682455aabc3SBrian Somers * XXX this stuff should really live in the FSM. Our config should 683455aabc3SBrian Somers * associate executable sections in files with events. 684455aabc3SBrian Somers */ 68530291ffbSBrian Somers if (system_Select(fp->bundle, s, LINKDOWNFILE, NULL, NULL) < 0) { 68649052c95SBrian Somers if (bundle_GetLabel(fp->bundle)) { 687dd7e2610SBrian Somers if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle), 68830291ffbSBrian Somers LINKDOWNFILE, NULL, NULL) < 0) 68930291ffbSBrian Somers system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL); 690455aabc3SBrian Somers } else 69130291ffbSBrian Somers system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL); 692af57ed9fSAtsushi Murai } 693af57ed9fSAtsushi Murai 694ff0f9439SBrian Somers if (!(ipcp->fsm.bundle->phys_type.all & PHYS_AUTO)) 695dd7e2610SBrian Somers ipcp_CleanInterface(ipcp); 696897f9429SBrian Somers 697897f9429SBrian Somers ipcp_Setup(ipcp); 6981ae349f5Scvs2svn } 6991ae349f5Scvs2svn 700dd0645c5SBrian Somers int 701dd0645c5SBrian Somers ipcp_InterfaceUp(struct ipcp *ipcp) 702dd0645c5SBrian Somers { 703dd0645c5SBrian Somers if (ipcp_SetIPaddress(ipcp->fsm.bundle, ipcp->my_ip, ipcp->peer_ip, 0) < 0) { 704a33b2ef7SBrian Somers log_Printf(LogERROR, "ipcp_InterfaceUp: unable to set ip address\n"); 705dd0645c5SBrian Somers return 0; 706dd0645c5SBrian Somers } 707dd0645c5SBrian Somers 708dd0645c5SBrian Somers #ifndef NOALIAS 709dd0645c5SBrian Somers if (alias_IsEnabled()) 710dd0645c5SBrian Somers (*PacketAlias.SetAddress)(ipcp->my_ip); 711dd0645c5SBrian Somers #endif 712dd0645c5SBrian Somers 713dd0645c5SBrian Somers return 1; 714dd0645c5SBrian Somers } 715dd0645c5SBrian Somers 7166f384573SBrian Somers static int 717944f7098SBrian Somers IpcpLayerUp(struct fsm *fp) 718af57ed9fSAtsushi Murai { 7197308ec68SBrian Somers /* We're now up */ 720aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 721af57ed9fSAtsushi Murai char tbuff[100]; 722af57ed9fSAtsushi Murai 723dd7e2610SBrian Somers log_Printf(LogIPCP, "%s: IpcpLayerUp.\n", fp->link->name); 724503a7782SBrian Somers snprintf(tbuff, sizeof tbuff, "myaddr = %s ", inet_ntoa(ipcp->my_ip)); 725dd7e2610SBrian Somers log_Printf(LogIPCP, " %s hisaddr = %s\n", tbuff, inet_ntoa(ipcp->peer_ip)); 72603604f35SBrian Somers 727503a7782SBrian Somers if (ipcp->peer_compproto >> 16 == PROTO_VJCOMP) 728eaa4df37SBrian Somers sl_compress_init(&ipcp->vj.cslc, (ipcp->peer_compproto >> 8) & 255); 72903604f35SBrian Somers 730dd0645c5SBrian Somers if (!ipcp_InterfaceUp(ipcp)) 7316f384573SBrian Somers return 0; 732455aabc3SBrian Somers 733455aabc3SBrian Somers /* 734455aabc3SBrian Somers * XXX this stuff should really live in the FSM. Our config should 735455aabc3SBrian Somers * associate executable sections in files with events. 736455aabc3SBrian Somers */ 73730291ffbSBrian Somers if (system_Select(fp->bundle, inet_ntoa(ipcp->my_ifip), LINKUPFILE, 73830291ffbSBrian Somers NULL, NULL) < 0) { 73949052c95SBrian Somers if (bundle_GetLabel(fp->bundle)) { 740dd7e2610SBrian Somers if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle), 74130291ffbSBrian Somers LINKUPFILE, NULL, NULL) < 0) 74230291ffbSBrian Somers system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL); 743455aabc3SBrian Somers } else 74430291ffbSBrian Somers system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL); 745af57ed9fSAtsushi Murai } 746af57ed9fSAtsushi Murai 7470f2f3eb3SBrian Somers log_DisplayPrompts(); 7486f384573SBrian Somers return 1; 749af57ed9fSAtsushi Murai } 750af57ed9fSAtsushi Murai 751af57ed9fSAtsushi Murai static int 752944f7098SBrian Somers AcceptableAddr(struct in_range *prange, struct in_addr ipaddr) 753af57ed9fSAtsushi Murai { 7547308ec68SBrian Somers /* Is the given IP in the given range ? */ 755057df964SBrian Somers return (prange->ipaddr.s_addr & prange->mask.s_addr) == 756057df964SBrian Somers (ipaddr.s_addr & prange->mask.s_addr) && ipaddr.s_addr; 757af57ed9fSAtsushi Murai } 758af57ed9fSAtsushi Murai 759af57ed9fSAtsushi Murai static void 76030c2f2ffSBrian Somers IpcpDecodeConfig(struct fsm *fp, u_char * cp, int plen, int mode_type, 76130c2f2ffSBrian Somers struct fsm_decode *dec) 762af57ed9fSAtsushi Murai { 7637308ec68SBrian Somers /* Deal with incoming PROTO_IPCP */ 764aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 76553c9f6c0SAtsushi Murai int type, length; 766fe3125a0SBrian Somers u_int32_t compproto; 767af57ed9fSAtsushi Murai struct compreq *pcomp; 7683edeb0c6SBrian Somers struct in_addr ipaddr, dstipaddr, have_ip, dns[2], dnsnak[2]; 76930c2f2ffSBrian Somers char tbuff[100], tbuff2[100]; 7703edeb0c6SBrian Somers int gotdns, gotdnsnak; 771af57ed9fSAtsushi Murai 7723edeb0c6SBrian Somers gotdns = 0; 7733edeb0c6SBrian Somers gotdnsnak = 0; 7743edeb0c6SBrian Somers dnsnak[0].s_addr = dnsnak[1].s_addr = INADDR_ANY; 775af57ed9fSAtsushi Murai 776af57ed9fSAtsushi Murai while (plen >= sizeof(struct fsmconfig)) { 777af57ed9fSAtsushi Murai type = *cp; 778af57ed9fSAtsushi Murai length = cp[1]; 779d47dceb8SBrian Somers 780d47dceb8SBrian Somers if (length == 0) { 781dd7e2610SBrian Somers log_Printf(LogIPCP, "%s: IPCP size zero\n", fp->link->name); 782d47dceb8SBrian Somers break; 783d47dceb8SBrian Somers } 784d47dceb8SBrian Somers 7859e836af5SBrian Somers if (type < NCFTYPES) 78670ee81ffSBrian Somers snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes[type], length); 7879e836af5SBrian Somers else if (type > 128 && type < 128 + NCFTYPES128) 78870ee81ffSBrian Somers snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes128[type-128], length); 789af57ed9fSAtsushi Murai else 79070ee81ffSBrian Somers snprintf(tbuff, sizeof tbuff, " <%d>[%d] ", type, length); 791af57ed9fSAtsushi Murai 792af57ed9fSAtsushi Murai switch (type) { 793af57ed9fSAtsushi Murai case TY_IPADDR: /* RFC1332 */ 794fe3125a0SBrian Somers ipaddr.s_addr = *(u_int32_t *)(cp + 2); 795dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 796af57ed9fSAtsushi Murai 7979780ef31SBrian Somers switch (mode_type) { 798af57ed9fSAtsushi Murai case MODE_REQ: 799503a7782SBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 800f5fb6bd0SBrian Somers if (ipaddr.s_addr == INADDR_ANY || 801503a7782SBrian Somers iplist_ip2pos(&ipcp->cfg.peer_list, ipaddr) < 0 || 80230c2f2ffSBrian Somers ipcp_SetIPaddress(fp->bundle, ipcp->cfg.my_range.ipaddr, 80330c2f2ffSBrian Somers ipaddr, 1)) { 804dd7e2610SBrian Somers log_Printf(LogIPCP, "%s: Address invalid or already in use\n", 805bcc332bdSBrian Somers inet_ntoa(ipaddr)); 8068390b576SBrian Somers if (iplist_ip2pos(&ipcp->cfg.peer_list, ipcp->peer_ifip) >= 0) 8078390b576SBrian Somers /* 8088390b576SBrian Somers * If we've already got a valid address configured for the peer 80981358fa3SBrian Somers * (in AUTO mode), try NAKing with that so that we don't 8108390b576SBrian Somers * have to upset things too much. 8118390b576SBrian Somers */ 8128390b576SBrian Somers ipcp->peer_ip = ipcp->peer_ifip; 8138390b576SBrian Somers else 8148390b576SBrian Somers /* Just pick an IP number from our list */ 815503a7782SBrian Somers ipcp->peer_ip = ChooseHisAddr 81630c2f2ffSBrian Somers (fp->bundle, ipcp->cfg.my_range.ipaddr); 8178390b576SBrian Somers 818503a7782SBrian Somers if (ipcp->peer_ip.s_addr == INADDR_ANY) { 81930c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 82030c2f2ffSBrian Somers dec->rejend += length; 821bcc332bdSBrian Somers } else { 82230c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 82330c2f2ffSBrian Somers memcpy(dec->nakend+2, &ipcp->peer_ip.s_addr, length - 2); 82430c2f2ffSBrian Somers dec->nakend += length; 825bcc332bdSBrian Somers } 826bcc332bdSBrian Somers break; 827bcc332bdSBrian Somers } 828503a7782SBrian Somers } else if (!AcceptableAddr(&ipcp->cfg.peer_range, ipaddr)) { 829af57ed9fSAtsushi Murai /* 8308390b576SBrian Somers * If destination address is not acceptable, NAK with what we 831944f7098SBrian Somers * want to use. 832af57ed9fSAtsushi Murai */ 83330c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 8348390b576SBrian Somers if ((ipcp->peer_ifip.s_addr & ipcp->cfg.peer_range.mask.s_addr) == 8358390b576SBrian Somers (ipcp->cfg.peer_range.ipaddr.s_addr & 8368390b576SBrian Somers ipcp->cfg.peer_range.mask.s_addr)) 8378390b576SBrian Somers /* We prefer the already-configured address */ 8388390b576SBrian Somers memcpy(dec->nakend+2, &ipcp->peer_ifip.s_addr, length - 2); 8398390b576SBrian Somers else 84030c2f2ffSBrian Somers memcpy(dec->nakend+2, &ipcp->peer_ip.s_addr, length - 2); 84130c2f2ffSBrian Somers dec->nakend += length; 842af57ed9fSAtsushi Murai break; 843af57ed9fSAtsushi Murai } 844503a7782SBrian Somers ipcp->peer_ip = ipaddr; 84530c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 84630c2f2ffSBrian Somers dec->ackend += length; 847af57ed9fSAtsushi Murai break; 848af57ed9fSAtsushi Murai case MODE_NAK: 849503a7782SBrian Somers if (AcceptableAddr(&ipcp->cfg.my_range, ipaddr)) { 850bcc332bdSBrian Somers /* Use address suggested by peer */ 85170ee81ffSBrian Somers snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s ", tbuff, 852503a7782SBrian Somers inet_ntoa(ipcp->my_ip)); 853dd7e2610SBrian Somers log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 854503a7782SBrian Somers ipcp->my_ip = ipaddr; 855bcc332bdSBrian Somers } else { 856dd7e2610SBrian Somers log_Printf(log_IsKept(LogIPCP) ? LogIPCP : LogPHASE, 8578390b576SBrian Somers "%s: Unacceptable address!\n", inet_ntoa(ipaddr)); 858dd7e2610SBrian Somers fsm_Close(&ipcp->fsm); 859af57ed9fSAtsushi Murai } 860af57ed9fSAtsushi Murai break; 861af57ed9fSAtsushi Murai case MODE_REJ: 862503a7782SBrian Somers ipcp->peer_reject |= (1 << type); 863af57ed9fSAtsushi Murai break; 864af57ed9fSAtsushi Murai } 865af57ed9fSAtsushi Murai break; 866af57ed9fSAtsushi Murai case TY_COMPPROTO: 867fe3125a0SBrian Somers compproto = htonl(*(u_int32_t *)(cp + 2)); 868dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto)); 869af57ed9fSAtsushi Murai 8709780ef31SBrian Somers switch (mode_type) { 871af57ed9fSAtsushi Murai case MODE_REQ: 8721342caedSBrian Somers if (!IsAccepted(ipcp->cfg.vj.neg)) { 87330c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 87430c2f2ffSBrian Somers dec->rejend += length; 875af57ed9fSAtsushi Murai } else { 876af57ed9fSAtsushi Murai pcomp = (struct compreq *) (cp + 2); 877af57ed9fSAtsushi Murai switch (length) { 878af57ed9fSAtsushi Murai case 4: /* RFC1172 */ 879af57ed9fSAtsushi Murai if (ntohs(pcomp->proto) == PROTO_VJCOMP) { 880dd7e2610SBrian Somers log_Printf(LogWARN, "Peer is speaking RFC1172 compression protocol !\n"); 88183d1af55SBrian Somers ipcp->heis1172 = 1; 882503a7782SBrian Somers ipcp->peer_compproto = compproto; 88330c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 88430c2f2ffSBrian Somers dec->ackend += length; 885af57ed9fSAtsushi Murai } else { 88630c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 887af57ed9fSAtsushi Murai pcomp->proto = htons(PROTO_VJCOMP); 88830c2f2ffSBrian Somers memcpy(dec->nakend+2, &pcomp, 2); 88930c2f2ffSBrian Somers dec->nakend += length; 890af57ed9fSAtsushi Murai } 891af57ed9fSAtsushi Murai break; 892af57ed9fSAtsushi Murai case 6: /* RFC1332 */ 893af57ed9fSAtsushi Murai if (ntohs(pcomp->proto) == PROTO_VJCOMP 894503a7782SBrian Somers && pcomp->slots <= MAX_VJ_STATES 895503a7782SBrian Somers && pcomp->slots >= MIN_VJ_STATES) { 896503a7782SBrian Somers ipcp->peer_compproto = compproto; 89783d1af55SBrian Somers ipcp->heis1172 = 0; 89830c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 89930c2f2ffSBrian Somers dec->ackend += length; 900af57ed9fSAtsushi Murai } else { 90130c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 902af57ed9fSAtsushi Murai pcomp->proto = htons(PROTO_VJCOMP); 903503a7782SBrian Somers pcomp->slots = DEF_VJ_STATES; 904af57ed9fSAtsushi Murai pcomp->compcid = 0; 90530c2f2ffSBrian Somers memcpy(dec->nakend+2, &pcomp, sizeof pcomp); 90630c2f2ffSBrian Somers dec->nakend += length; 907af57ed9fSAtsushi Murai } 908af57ed9fSAtsushi Murai break; 909af57ed9fSAtsushi Murai default: 91030c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 91130c2f2ffSBrian Somers dec->rejend += length; 912af57ed9fSAtsushi Murai break; 913af57ed9fSAtsushi Murai } 914af57ed9fSAtsushi Murai } 915af57ed9fSAtsushi Murai break; 916af57ed9fSAtsushi Murai case MODE_NAK: 917dd7e2610SBrian Somers log_Printf(LogIPCP, "%s changing compproto: %08x --> %08x\n", 918503a7782SBrian Somers tbuff, ipcp->my_compproto, compproto); 919503a7782SBrian Somers ipcp->my_compproto = compproto; 920af57ed9fSAtsushi Murai break; 921af57ed9fSAtsushi Murai case MODE_REJ: 922503a7782SBrian Somers ipcp->peer_reject |= (1 << type); 923af57ed9fSAtsushi Murai break; 924af57ed9fSAtsushi Murai } 925af57ed9fSAtsushi Murai break; 926af57ed9fSAtsushi Murai case TY_IPADDRS: /* RFC1172 */ 927fe3125a0SBrian Somers ipaddr.s_addr = *(u_int32_t *)(cp + 2); 928fe3125a0SBrian Somers dstipaddr.s_addr = *(u_int32_t *)(cp + 6); 92970ee81ffSBrian Somers snprintf(tbuff2, sizeof tbuff2, "%s %s,", tbuff, inet_ntoa(ipaddr)); 930dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr)); 931af57ed9fSAtsushi Murai 9329780ef31SBrian Somers switch (mode_type) { 933af57ed9fSAtsushi Murai case MODE_REQ: 934503a7782SBrian Somers ipcp->peer_ip = ipaddr; 935503a7782SBrian Somers ipcp->my_ip = dstipaddr; 93630c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 93730c2f2ffSBrian Somers dec->ackend += length; 938af57ed9fSAtsushi Murai break; 939af57ed9fSAtsushi Murai case MODE_NAK: 94070ee81ffSBrian Somers snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s", tbuff, 941503a7782SBrian Somers inet_ntoa(ipcp->my_ip)); 942dd7e2610SBrian Somers log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 943503a7782SBrian Somers ipcp->my_ip = ipaddr; 944503a7782SBrian Somers ipcp->peer_ip = dstipaddr; 945af57ed9fSAtsushi Murai break; 946af57ed9fSAtsushi Murai case MODE_REJ: 947503a7782SBrian Somers ipcp->peer_reject |= (1 << type); 948af57ed9fSAtsushi Murai break; 949af57ed9fSAtsushi Murai } 950af57ed9fSAtsushi Murai break; 951d8e55738SJordan K. Hubbard 9523edeb0c6SBrian Somers case TY_PRIMARY_DNS: /* DNS negotiation (rfc1877) */ 953d8e55738SJordan K. Hubbard case TY_SECONDARY_DNS: 9543edeb0c6SBrian Somers ipaddr.s_addr = *(u_int32_t *)(cp + 2); 955dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 9563edeb0c6SBrian Somers 9579780ef31SBrian Somers switch (mode_type) { 958d8e55738SJordan K. Hubbard case MODE_REQ: 9593edeb0c6SBrian Somers if (!IsAccepted(ipcp->cfg.ns.dns_neg)) { 9603edeb0c6SBrian Somers ipcp->my_reject |= (1 << (type - TY_ADJUST_NS)); 96130c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 96230c2f2ffSBrian Somers dec->rejend += length; 963d8e55738SJordan K. Hubbard break; 964d8e55738SJordan K. Hubbard } 9653edeb0c6SBrian Somers if (!gotdns) { 9663edeb0c6SBrian Somers dns[0] = ipcp->cfg.ns.dns[0]; 9673edeb0c6SBrian Somers dns[1] = ipcp->cfg.ns.dns[1]; 9683edeb0c6SBrian Somers if (dns[0].s_addr == INADDR_ANY && dns[1].s_addr == INADDR_ANY) 9693edeb0c6SBrian Somers getdns(ipcp, dns); 9703edeb0c6SBrian Somers gotdns = 1; 9713edeb0c6SBrian Somers } 9723edeb0c6SBrian Somers have_ip = dns[type == TY_PRIMARY_DNS ? 0 : 1]; 973944f7098SBrian Somers 9743edeb0c6SBrian Somers if (ipaddr.s_addr != have_ip.s_addr) { 9751ae349f5Scvs2svn /* 9763edeb0c6SBrian Somers * The client has got the DNS stuff wrong (first request) so 9771ae349f5Scvs2svn * we'll tell 'em how it is 9781ae349f5Scvs2svn */ 97930c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); /* copy first two (type/length) */ 9803edeb0c6SBrian Somers memcpy(dec->nakend + 2, &have_ip.s_addr, length - 2); 98130c2f2ffSBrian Somers dec->nakend += length; 9823edeb0c6SBrian Somers } else { 983d8e55738SJordan K. Hubbard /* 984944f7098SBrian Somers * Otherwise they have it right (this time) so we send a ack packet 985944f7098SBrian Somers * back confirming it... end of story 986d8e55738SJordan K. Hubbard */ 98730c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 98830c2f2ffSBrian Somers dec->ackend += length; 9893edeb0c6SBrian Somers } 990d8e55738SJordan K. Hubbard break; 991d8e55738SJordan K. Hubbard case MODE_NAK: /* what does this mean?? */ 9923edeb0c6SBrian Somers if (IsEnabled(ipcp->cfg.ns.dns_neg)) { 9933edeb0c6SBrian Somers gotdnsnak = 1; 9943edeb0c6SBrian Somers dnsnak[type == TY_PRIMARY_DNS ? 0 : 1].s_addr = 9953edeb0c6SBrian Somers *(u_int32_t *)(cp + 2); 9963edeb0c6SBrian Somers } 997d8e55738SJordan K. Hubbard break; 9983edeb0c6SBrian Somers case MODE_REJ: /* Can't do much, stop asking */ 9993edeb0c6SBrian Somers ipcp->peer_reject |= (1 << (type - TY_ADJUST_NS)); 1000d8e55738SJordan K. Hubbard break; 1001d8e55738SJordan K. Hubbard } 1002d8e55738SJordan K. Hubbard break; 1003d8e55738SJordan K. Hubbard 10043edeb0c6SBrian Somers case TY_PRIMARY_NBNS: /* M$ NetBIOS nameserver hack (rfc1877) */ 1005d8e55738SJordan K. Hubbard case TY_SECONDARY_NBNS: 10063edeb0c6SBrian Somers ipaddr.s_addr = *(u_int32_t *)(cp + 2); 1007dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 10083edeb0c6SBrian Somers 10099780ef31SBrian Somers switch (mode_type) { 1010d8e55738SJordan K. Hubbard case MODE_REQ: 10113edeb0c6SBrian Somers have_ip.s_addr = 10123edeb0c6SBrian Somers ipcp->cfg.ns.nbns[type == TY_PRIMARY_NBNS ? 0 : 1].s_addr; 10133edeb0c6SBrian Somers 10143edeb0c6SBrian Somers if (have_ip.s_addr == INADDR_ANY) { 1015dd7e2610SBrian Somers log_Printf(LogIPCP, "NBNS REQ - rejected - nbns not set\n"); 10163edeb0c6SBrian Somers ipcp->my_reject |= (1 << (type - TY_ADJUST_NS)); 101730c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 101830c2f2ffSBrian Somers dec->rejend += length; 1019d8e55738SJordan K. Hubbard break; 1020d8e55738SJordan K. Hubbard } 10213edeb0c6SBrian Somers 10223edeb0c6SBrian Somers if (ipaddr.s_addr != have_ip.s_addr) { 102330c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 10243edeb0c6SBrian Somers memcpy(dec->nakend+2, &have_ip.s_addr, length); 102530c2f2ffSBrian Somers dec->nakend += length; 10263edeb0c6SBrian Somers } else { 102730c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 102830c2f2ffSBrian Somers dec->ackend += length; 10293edeb0c6SBrian Somers } 1030d8e55738SJordan K. Hubbard break; 1031d8e55738SJordan K. Hubbard case MODE_NAK: 1032dd7e2610SBrian Somers log_Printf(LogIPCP, "MS NBNS req %d - NAK??\n", type); 1033d8e55738SJordan K. Hubbard break; 1034d8e55738SJordan K. Hubbard case MODE_REJ: 1035dd7e2610SBrian Somers log_Printf(LogIPCP, "MS NBNS req %d - REJ??\n", type); 1036d8e55738SJordan K. Hubbard break; 1037d8e55738SJordan K. Hubbard } 1038d8e55738SJordan K. Hubbard break; 1039d8e55738SJordan K. Hubbard 1040af57ed9fSAtsushi Murai default: 104130c2f2ffSBrian Somers if (mode_type != MODE_NOP) { 104283d1af55SBrian Somers ipcp->my_reject |= (1 << type); 104330c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 104430c2f2ffSBrian Somers dec->rejend += length; 104530c2f2ffSBrian Somers } 1046af57ed9fSAtsushi Murai break; 1047af57ed9fSAtsushi Murai } 1048af57ed9fSAtsushi Murai plen -= length; 1049af57ed9fSAtsushi Murai cp += length; 1050af57ed9fSAtsushi Murai } 10511342caedSBrian Somers 10523edeb0c6SBrian Somers if (gotdnsnak) 10533edeb0c6SBrian Somers if (!setdns(ipcp, dnsnak)) { 10543edeb0c6SBrian Somers ipcp->peer_reject |= (1 << (TY_PRIMARY_DNS - TY_ADJUST_NS)); 10553edeb0c6SBrian Somers ipcp->peer_reject |= (1 << (TY_SECONDARY_DNS - TY_ADJUST_NS)); 10563edeb0c6SBrian Somers } 10573edeb0c6SBrian Somers 1058e43ebac1SBrian Somers if (mode_type != MODE_NOP) { 10591342caedSBrian Somers if (dec->rejend != dec->rej) { 10601342caedSBrian Somers /* rejects are preferred */ 10611342caedSBrian Somers dec->ackend = dec->ack; 10621342caedSBrian Somers dec->nakend = dec->nak; 10631342caedSBrian Somers } else if (dec->nakend != dec->nak) 10641342caedSBrian Somers /* then NAKs */ 10651342caedSBrian Somers dec->ackend = dec->ack; 10661ae349f5Scvs2svn } 1067af57ed9fSAtsushi Murai } 1068af57ed9fSAtsushi Murai 1069af57ed9fSAtsushi Murai void 1070641684cdSBrian Somers ipcp_Input(struct ipcp *ipcp, struct bundle *bundle, struct mbuf *bp) 1071af57ed9fSAtsushi Murai { 10727308ec68SBrian Somers /* Got PROTO_IPCP from link */ 1073641684cdSBrian Somers if (bundle_Phase(bundle) == PHASE_NETWORK) 1074dd7e2610SBrian Somers fsm_Input(&ipcp->fsm, bp); 1075641684cdSBrian Somers else { 1076641684cdSBrian Somers if (bundle_Phase(bundle) < PHASE_NETWORK) 1077641684cdSBrian Somers log_Printf(LogIPCP, "%s: Error: Unexpected IPCP in phase %s (ignored)\n", 1078641684cdSBrian Somers ipcp->fsm.link->name, bundle_PhaseName(bundle)); 1079641684cdSBrian Somers mbuf_Free(bp); 1080641684cdSBrian Somers } 1081af57ed9fSAtsushi Murai } 10829c97abd8SBrian Somers 10839c97abd8SBrian Somers int 1084dd7e2610SBrian Somers ipcp_UseHisaddr(struct bundle *bundle, const char *hisaddr, int setaddr) 10859c97abd8SBrian Somers { 10865828db6dSBrian Somers struct ipcp *ipcp = &bundle->ncp.ipcp; 10875828db6dSBrian Somers 10887308ec68SBrian Somers /* Use `hisaddr' for the peers address (set iface if `setaddr') */ 10895828db6dSBrian Somers memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 10905828db6dSBrian Somers iplist_reset(&ipcp->cfg.peer_list); 10919c97abd8SBrian Somers if (strpbrk(hisaddr, ",-")) { 10925828db6dSBrian Somers iplist_setsrc(&ipcp->cfg.peer_list, hisaddr); 10935828db6dSBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 10945828db6dSBrian Somers iplist_setrandpos(&ipcp->cfg.peer_list); 109530c2f2ffSBrian Somers ipcp->peer_ip = ChooseHisAddr(bundle, ipcp->my_ip); 10965828db6dSBrian Somers if (ipcp->peer_ip.s_addr == INADDR_ANY) { 1097dd7e2610SBrian Somers log_Printf(LogWARN, "%s: None available !\n", ipcp->cfg.peer_list.src); 10989c97abd8SBrian Somers return(0); 10999c97abd8SBrian Somers } 11005828db6dSBrian Somers ipcp->cfg.peer_range.ipaddr.s_addr = ipcp->peer_ip.s_addr; 11015828db6dSBrian Somers ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 11025828db6dSBrian Somers ipcp->cfg.peer_range.width = 32; 11039c97abd8SBrian Somers } else { 1104dd7e2610SBrian Somers log_Printf(LogWARN, "%s: Invalid range !\n", hisaddr); 11059c97abd8SBrian Somers return 0; 11069c97abd8SBrian Somers } 11075828db6dSBrian Somers } else if (ParseAddr(ipcp, 1, &hisaddr, &ipcp->cfg.peer_range.ipaddr, 11085828db6dSBrian Somers &ipcp->cfg.peer_range.mask, 11095828db6dSBrian Somers &ipcp->cfg.peer_range.width) != 0) { 11105828db6dSBrian Somers ipcp->peer_ip.s_addr = ipcp->cfg.peer_range.ipaddr.s_addr; 11119c97abd8SBrian Somers 111230c2f2ffSBrian Somers if (setaddr && ipcp_SetIPaddress(bundle, ipcp->cfg.my_range.ipaddr, 111330c2f2ffSBrian Somers ipcp->cfg.peer_range.ipaddr, 0) < 0) { 11145828db6dSBrian Somers ipcp->cfg.my_range.ipaddr.s_addr = INADDR_ANY; 11155828db6dSBrian Somers ipcp->cfg.peer_range.ipaddr.s_addr = INADDR_ANY; 11169c97abd8SBrian Somers return 0; 11179c97abd8SBrian Somers } 11189c97abd8SBrian Somers } else 11199c97abd8SBrian Somers return 0; 11209c97abd8SBrian Somers 11219c97abd8SBrian Somers return 1; 11229c97abd8SBrian Somers } 1123