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 * 20119386a3SBrian Somers * $Id: ipcp.c,v 1.73 1999/03/03 23:00:40 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> 313afe5ccbSBrian Somers #include <net/route.h> 3275240ed1SBrian Somers #include <netdb.h> 331fa665f5SBrian Somers #include <sys/un.h> 3475240ed1SBrian Somers 35119386a3SBrian Somers #include <errno.h> 363edeb0c6SBrian Somers #include <fcntl.h> 373edeb0c6SBrian Somers #include <resolv.h> 38d1a3ea47SBrian Somers #include <stdlib.h> 3975240ed1SBrian Somers #include <string.h> 406140ba11SBrian Somers #include <termios.h> 4175240ed1SBrian Somers #include <unistd.h> 4275240ed1SBrian Somers 431595bacdSBrian Somers #ifndef NOALIAS 441595bacdSBrian Somers #ifdef __OpenBSD__ 451595bacdSBrian Somers #include "alias.h" 461595bacdSBrian Somers #else 471595bacdSBrian Somers #include <alias.h> 481595bacdSBrian Somers #endif 491595bacdSBrian Somers #endif 509e8ec64bSBrian Somers #include "ua.h" 51c9e11a11SBrian Somers #include "defs.h" 52b6e82f33SBrian Somers #include "command.h" 5375240ed1SBrian Somers #include "mbuf.h" 5475240ed1SBrian Somers #include "log.h" 5575240ed1SBrian Somers #include "timer.h" 56af57ed9fSAtsushi Murai #include "fsm.h" 57af57ed9fSAtsushi Murai #include "lcpproto.h" 58af57ed9fSAtsushi Murai #include "lcp.h" 59bcc332bdSBrian Somers #include "iplist.h" 609a0b991fSBrian Somers #include "throughput.h" 611ae349f5Scvs2svn #include "slcompress.h" 625a72b6edSBrian Somers #include "lqr.h" 635a72b6edSBrian Somers #include "hdlc.h" 64eaa4df37SBrian Somers #include "ipcp.h" 659c97abd8SBrian Somers #include "filter.h" 662f786681SBrian Somers #include "descriptor.h" 671ae349f5Scvs2svn #include "vjcomp.h" 686140ba11SBrian Somers #include "async.h" 693b0f8d2eSBrian Somers #include "ccp.h" 708c07a7b2SBrian Somers #include "link.h" 7163b73463SBrian Somers #include "physical.h" 723b0f8d2eSBrian Somers #include "mp.h" 73972a1bcfSBrian Somers #ifndef NORADIUS 74972a1bcfSBrian Somers #include "radius.h" 75972a1bcfSBrian Somers #endif 763b0f8d2eSBrian Somers #include "bundle.h" 77455aabc3SBrian Somers #include "id.h" 78455aabc3SBrian Somers #include "arp.h" 79455aabc3SBrian Somers #include "systems.h" 8085b542cfSBrian Somers #include "prompt.h" 81610b185fSBrian Somers #include "route.h" 828fa6ebe4SBrian Somers #include "iface.h" 83af57ed9fSAtsushi Murai 84503a7782SBrian Somers #undef REJECTED 85503a7782SBrian Somers #define REJECTED(p, x) ((p)->peer_reject & (1<<(x))) 863edeb0c6SBrian Somers #define issep(ch) ((ch) == ' ' || (ch) == '\t') 873edeb0c6SBrian Somers #define isip(ch) (((ch) >= '0' && (ch) <= '9') || (ch) == '.') 88d8e55738SJordan K. Hubbard 8929e275ceSBrian Somers struct compreq { 9029e275ceSBrian Somers u_short proto; 9129e275ceSBrian Somers u_char slots; 9229e275ceSBrian Somers u_char compcid; 9329e275ceSBrian Somers }; 9475240ed1SBrian Somers 956f384573SBrian Somers static int IpcpLayerUp(struct fsm *); 961ae349f5Scvs2svn static void IpcpLayerDown(struct fsm *); 97927145beSBrian Somers static void IpcpLayerStart(struct fsm *); 98927145beSBrian Somers static void IpcpLayerFinish(struct fsm *); 99479508cfSBrian Somers static void IpcpInitRestartCounter(struct fsm *, int); 1007308ec68SBrian Somers static void IpcpSendConfigReq(struct fsm *); 1012267893fSBrian Somers static void IpcpSentTerminateReq(struct fsm *); 1022267893fSBrian Somers static void IpcpSendTerminateAck(struct fsm *, u_char); 10330c2f2ffSBrian Somers static void IpcpDecodeConfig(struct fsm *, u_char *, int, int, 10430c2f2ffSBrian Somers struct fsm_decode *); 105af57ed9fSAtsushi Murai 10683d1af55SBrian Somers static struct fsm_callbacks ipcp_Callbacks = { 107af57ed9fSAtsushi Murai IpcpLayerUp, 108af57ed9fSAtsushi Murai IpcpLayerDown, 109af57ed9fSAtsushi Murai IpcpLayerStart, 110af57ed9fSAtsushi Murai IpcpLayerFinish, 111af57ed9fSAtsushi Murai IpcpInitRestartCounter, 112af57ed9fSAtsushi Murai IpcpSendConfigReq, 1132267893fSBrian Somers IpcpSentTerminateReq, 114af57ed9fSAtsushi Murai IpcpSendTerminateAck, 115af57ed9fSAtsushi Murai IpcpDecodeConfig, 116dd7e2610SBrian Somers fsm_NullRecvResetReq, 117dd7e2610SBrian Somers fsm_NullRecvResetAck 118af57ed9fSAtsushi Murai }; 119af57ed9fSAtsushi Murai 120b6e82f33SBrian Somers static const char *cftypes[] = { 1219e836af5SBrian Somers /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */ 1229e836af5SBrian Somers "???", 1239e836af5SBrian Somers "IPADDRS", /* 1: IP-Addresses */ /* deprecated */ 1249e836af5SBrian Somers "COMPPROTO", /* 2: IP-Compression-Protocol */ 1259e836af5SBrian Somers "IPADDR", /* 3: IP-Address */ 126af57ed9fSAtsushi Murai }; 127af57ed9fSAtsushi Murai 12870ee81ffSBrian Somers #define NCFTYPES (sizeof cftypes/sizeof cftypes[0]) 1299e836af5SBrian Somers 130b6e82f33SBrian Somers static const char *cftypes128[] = { 1319e836af5SBrian Somers /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */ 1329e836af5SBrian Somers "???", 1339e836af5SBrian Somers "PRIDNS", /* 129: Primary DNS Server Address */ 1349e836af5SBrian Somers "PRINBNS", /* 130: Primary NBNS Server Address */ 1359e836af5SBrian Somers "SECDNS", /* 131: Secondary DNS Server Address */ 1369e836af5SBrian Somers "SECNBNS", /* 132: Secondary NBNS Server Address */ 1379e836af5SBrian Somers }; 1389e836af5SBrian Somers 13970ee81ffSBrian Somers #define NCFTYPES128 (sizeof cftypes128/sizeof cftypes128[0]) 1409e836af5SBrian Somers 1419a0b991fSBrian Somers void 1425828db6dSBrian Somers ipcp_AddInOctets(struct ipcp *ipcp, int n) 143af57ed9fSAtsushi Murai { 1445828db6dSBrian Somers throughput_addin(&ipcp->throughput, n); 145af57ed9fSAtsushi Murai } 146af57ed9fSAtsushi Murai 1479a0b991fSBrian Somers void 1485828db6dSBrian Somers ipcp_AddOutOctets(struct ipcp *ipcp, int n) 149af57ed9fSAtsushi Murai { 1505828db6dSBrian Somers throughput_addout(&ipcp->throughput, n); 1511ae349f5Scvs2svn } 1521ae349f5Scvs2svn 1533edeb0c6SBrian Somers static void 1543edeb0c6SBrian Somers getdns(struct ipcp *ipcp, struct in_addr addr[2]) 1553edeb0c6SBrian Somers { 1563edeb0c6SBrian Somers FILE *fp; 1573edeb0c6SBrian Somers 1583edeb0c6SBrian Somers addr[0].s_addr = addr[1].s_addr = INADDR_ANY; 1593edeb0c6SBrian Somers if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { 1603edeb0c6SBrian Somers char buf[LINE_LEN], *cp, *end; 1613edeb0c6SBrian Somers int n; 1623edeb0c6SBrian Somers 1633edeb0c6SBrian Somers n = 0; 1643edeb0c6SBrian Somers buf[sizeof buf - 1] = '\0'; 1653edeb0c6SBrian Somers while (fgets(buf, sizeof buf - 1, fp)) { 1663edeb0c6SBrian Somers if (!strncmp(buf, "nameserver", 10) && issep(buf[10])) { 1673edeb0c6SBrian Somers for (cp = buf + 11; issep(*cp); cp++) 1683edeb0c6SBrian Somers ; 1693edeb0c6SBrian Somers for (end = cp; isip(*end); end++) 1703edeb0c6SBrian Somers ; 1713edeb0c6SBrian Somers *end = '\0'; 1723edeb0c6SBrian Somers if (inet_aton(cp, addr+n) && ++n == 2) 1733edeb0c6SBrian Somers break; 1743edeb0c6SBrian Somers } 1753edeb0c6SBrian Somers } 1763edeb0c6SBrian Somers if (n == 1) 1773edeb0c6SBrian Somers addr[1] = addr[0]; 1783edeb0c6SBrian Somers fclose(fp); 1793edeb0c6SBrian Somers } 1803edeb0c6SBrian Somers } 1813edeb0c6SBrian Somers 1823edeb0c6SBrian Somers static int 1833edeb0c6SBrian Somers setdns(struct ipcp *ipcp, struct in_addr addr[2]) 1843edeb0c6SBrian Somers { 1853edeb0c6SBrian Somers FILE *fp; 1863edeb0c6SBrian Somers char wbuf[LINE_LEN + 54]; 1873edeb0c6SBrian Somers int wlen; 1883edeb0c6SBrian Somers 1893edeb0c6SBrian Somers if (addr[0].s_addr == INADDR_ANY || addr[1].s_addr == INADDR_ANY) { 1903edeb0c6SBrian Somers struct in_addr old[2]; 1913edeb0c6SBrian Somers 1923edeb0c6SBrian Somers getdns(ipcp, old); 1933edeb0c6SBrian Somers if (addr[0].s_addr == INADDR_ANY) 1943edeb0c6SBrian Somers addr[0] = old[0]; 1953edeb0c6SBrian Somers if (addr[1].s_addr == INADDR_ANY) 1963edeb0c6SBrian Somers addr[1] = old[1]; 1973edeb0c6SBrian Somers } 1983edeb0c6SBrian Somers 1993edeb0c6SBrian Somers if (addr[0].s_addr == INADDR_ANY && addr[1].s_addr == INADDR_ANY) { 200dd7e2610SBrian Somers log_Printf(LogWARN, "%s not modified: All nameservers NAKd\n", 2013edeb0c6SBrian Somers _PATH_RESCONF); 2023edeb0c6SBrian Somers return 0; 2033edeb0c6SBrian Somers } 2043edeb0c6SBrian Somers 2053edeb0c6SBrian Somers wlen = 0; 2063edeb0c6SBrian Somers if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { 2073edeb0c6SBrian Somers char buf[LINE_LEN]; 2083edeb0c6SBrian Somers int len; 2093edeb0c6SBrian Somers 2103edeb0c6SBrian Somers buf[sizeof buf - 1] = '\0'; 2113edeb0c6SBrian Somers while (fgets(buf, sizeof buf - 1, fp)) { 2123edeb0c6SBrian Somers if (strncmp(buf, "nameserver", 10) || !issep(buf[10])) { 2133edeb0c6SBrian Somers len = strlen(buf); 2143edeb0c6SBrian Somers if (len > sizeof wbuf - wlen) { 215dd7e2610SBrian Somers log_Printf(LogWARN, "%s: Can only cope with max file size %d\n", 2163edeb0c6SBrian Somers _PATH_RESCONF, LINE_LEN); 2173edeb0c6SBrian Somers fclose(fp); 2183edeb0c6SBrian Somers return 0; 2193edeb0c6SBrian Somers } 2203edeb0c6SBrian Somers memcpy(wbuf + wlen, buf, len); 2213edeb0c6SBrian Somers wlen += len; 2223edeb0c6SBrian Somers } 2233edeb0c6SBrian Somers } 2243edeb0c6SBrian Somers fclose(fp); 2253edeb0c6SBrian Somers } 2263edeb0c6SBrian Somers 2273edeb0c6SBrian Somers if (addr[0].s_addr != INADDR_ANY) { 2283edeb0c6SBrian Somers snprintf(wbuf + wlen, sizeof wbuf - wlen, "nameserver %s\n", 2293edeb0c6SBrian Somers inet_ntoa(addr[0])); 230dd7e2610SBrian Somers log_Printf(LogIPCP, "Primary nameserver set to %s", wbuf + wlen + 11); 2313edeb0c6SBrian Somers wlen += strlen(wbuf + wlen); 2323edeb0c6SBrian Somers } 2333edeb0c6SBrian Somers 2343edeb0c6SBrian Somers if (addr[1].s_addr != INADDR_ANY && addr[1].s_addr != addr[0].s_addr) { 2353edeb0c6SBrian Somers snprintf(wbuf + wlen, sizeof wbuf - wlen, "nameserver %s\n", 2363edeb0c6SBrian Somers inet_ntoa(addr[1])); 237dd7e2610SBrian Somers log_Printf(LogIPCP, "Secondary nameserver set to %s", wbuf + wlen + 11); 2383edeb0c6SBrian Somers wlen += strlen(wbuf + wlen); 2393edeb0c6SBrian Somers } 2403edeb0c6SBrian Somers 2413edeb0c6SBrian Somers if (wlen) { 2423edeb0c6SBrian Somers int fd; 2433edeb0c6SBrian Somers 2443edeb0c6SBrian Somers if ((fd = ID0open(_PATH_RESCONF, O_WRONLY|O_CREAT, 0644)) != -1) { 2453edeb0c6SBrian Somers if (write(fd, wbuf, wlen) != wlen) { 246dd7e2610SBrian Somers log_Printf(LogERROR, "setdns: write(): %s\n", strerror(errno)); 2473edeb0c6SBrian Somers close(fd); 2483edeb0c6SBrian Somers return 0; 2493edeb0c6SBrian Somers } 2503edeb0c6SBrian Somers if (ftruncate(fd, wlen) == -1) { 251dd7e2610SBrian Somers log_Printf(LogERROR, "setdns: truncate(): %s\n", strerror(errno)); 2523edeb0c6SBrian Somers close(fd); 2533edeb0c6SBrian Somers return 0; 2543edeb0c6SBrian Somers } 2553edeb0c6SBrian Somers close(fd); 2563edeb0c6SBrian Somers } else { 257dd7e2610SBrian Somers log_Printf(LogERROR, "setdns: open(): %s\n", strerror(errno)); 2583edeb0c6SBrian Somers return 0; 2593edeb0c6SBrian Somers } 2603edeb0c6SBrian Somers } 2613edeb0c6SBrian Somers 2623edeb0c6SBrian Somers return 1; 263af57ed9fSAtsushi Murai } 264af57ed9fSAtsushi Murai 265274e766cSBrian Somers int 266dd7e2610SBrian Somers ipcp_Show(struct cmdargs const *arg) 267af57ed9fSAtsushi Murai { 268610b185fSBrian Somers struct ipcp *ipcp = &arg->bundle->ncp.ipcp; 269af57ed9fSAtsushi Murai 270610b185fSBrian Somers prompt_Printf(arg->prompt, "%s [%s]\n", ipcp->fsm.name, 271610b185fSBrian Somers State2Nam(ipcp->fsm.state)); 272610b185fSBrian Somers if (ipcp->fsm.state == ST_OPENED) { 273b6217683SBrian Somers prompt_Printf(arg->prompt, " His side: %s, %s\n", 274610b185fSBrian Somers inet_ntoa(ipcp->peer_ip), vj2asc(ipcp->peer_compproto)); 275b6217683SBrian Somers prompt_Printf(arg->prompt, " My side: %s, %s\n", 276610b185fSBrian Somers inet_ntoa(ipcp->my_ip), vj2asc(ipcp->my_compproto)); 277d1a3ea47SBrian Somers } 2785b4c5b00SBrian Somers 279610b185fSBrian Somers if (ipcp->route) { 280610b185fSBrian Somers prompt_Printf(arg->prompt, "\n"); 281972a1bcfSBrian Somers route_ShowSticky(arg->prompt, ipcp->route, "Sticky routes", 1); 2821ae349f5Scvs2svn } 283927145beSBrian Somers 284b6217683SBrian Somers prompt_Printf(arg->prompt, "\nDefaults:\n"); 285479508cfSBrian Somers prompt_Printf(arg->prompt, " FSM retry = %us, max %u Config" 286479508cfSBrian Somers " REQ%s, %u Term REQ%s\n", ipcp->cfg.fsm.timeout, 287479508cfSBrian Somers ipcp->cfg.fsm.maxreq, ipcp->cfg.fsm.maxreq == 1 ? "" : "s", 288479508cfSBrian Somers ipcp->cfg.fsm.maxtrm, ipcp->cfg.fsm.maxtrm == 1 ? "" : "s"); 28950abd4c8SBrian Somers prompt_Printf(arg->prompt, " My Address: %s/%d", 290610b185fSBrian Somers inet_ntoa(ipcp->cfg.my_range.ipaddr), ipcp->cfg.my_range.width); 291bc76350eSBrian Somers prompt_Printf(arg->prompt, ", netmask %s\n", inet_ntoa(ipcp->cfg.netmask)); 292610b185fSBrian Somers if (ipcp->cfg.HaveTriggerAddress) 293bc76350eSBrian Somers prompt_Printf(arg->prompt, " Trigger address: %s\n", 294610b185fSBrian Somers inet_ntoa(ipcp->cfg.TriggerAddress)); 295bc76350eSBrian Somers 296bc76350eSBrian Somers prompt_Printf(arg->prompt, " VJ compression: %s (%d slots %s slot " 297610b185fSBrian Somers "compression)\n", command_ShowNegval(ipcp->cfg.vj.neg), 298610b185fSBrian Somers ipcp->cfg.vj.slots, ipcp->cfg.vj.slotcomp ? "with" : "without"); 29950abd4c8SBrian Somers 300610b185fSBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) 301b6217683SBrian Somers prompt_Printf(arg->prompt, " His Address: %s\n", 302610b185fSBrian Somers ipcp->cfg.peer_list.src); 3031ae349f5Scvs2svn else 304b6217683SBrian Somers prompt_Printf(arg->prompt, " His Address: %s/%d\n", 305610b185fSBrian Somers inet_ntoa(ipcp->cfg.peer_range.ipaddr), 306610b185fSBrian Somers ipcp->cfg.peer_range.width); 30750abd4c8SBrian Somers 3083edeb0c6SBrian Somers prompt_Printf(arg->prompt, " DNS: %s, ", 309610b185fSBrian Somers inet_ntoa(ipcp->cfg.ns.dns[0])); 310610b185fSBrian Somers prompt_Printf(arg->prompt, "%s, %s\n", inet_ntoa(ipcp->cfg.ns.dns[1]), 311610b185fSBrian Somers command_ShowNegval(ipcp->cfg.ns.dns_neg)); 3123edeb0c6SBrian Somers prompt_Printf(arg->prompt, " NetBIOS NS: %s, ", 313610b185fSBrian Somers inet_ntoa(ipcp->cfg.ns.nbns[0])); 314610b185fSBrian Somers prompt_Printf(arg->prompt, "%s\n", inet_ntoa(ipcp->cfg.ns.nbns[1])); 3151342caedSBrian Somers 316b6217683SBrian Somers prompt_Printf(arg->prompt, "\n"); 317610b185fSBrian Somers throughput_disp(&ipcp->throughput, arg->prompt); 3189a0b991fSBrian Somers 319927145beSBrian Somers return 0; 320af57ed9fSAtsushi Murai } 321af57ed9fSAtsushi Murai 322d1a3ea47SBrian Somers int 323dd7e2610SBrian Somers ipcp_vjset(struct cmdargs const *arg) 324d1a3ea47SBrian Somers { 32525092092SBrian Somers if (arg->argc != arg->argn+2) 326d1a3ea47SBrian Somers return -1; 32725092092SBrian Somers if (!strcasecmp(arg->argv[arg->argn], "slots")) { 328d1a3ea47SBrian Somers int slots; 329d1a3ea47SBrian Somers 33025092092SBrian Somers slots = atoi(arg->argv[arg->argn+1]); 331d1a3ea47SBrian Somers if (slots < 4 || slots > 16) 332d1a3ea47SBrian Somers return 1; 3331342caedSBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slots = slots; 334d1a3ea47SBrian Somers return 0; 33525092092SBrian Somers } else if (!strcasecmp(arg->argv[arg->argn], "slotcomp")) { 33625092092SBrian Somers if (!strcasecmp(arg->argv[arg->argn+1], "on")) 3371342caedSBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 1; 33825092092SBrian Somers else if (!strcasecmp(arg->argv[arg->argn+1], "off")) 3391342caedSBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 0; 340d1a3ea47SBrian Somers else 341d1a3ea47SBrian Somers return 2; 342d1a3ea47SBrian Somers return 0; 343d1a3ea47SBrian Somers } 344d1a3ea47SBrian Somers return -1; 345d1a3ea47SBrian Somers } 346d1a3ea47SBrian Somers 3471ae349f5Scvs2svn void 3486d666775SBrian Somers ipcp_Init(struct ipcp *ipcp, struct bundle *bundle, struct link *l, 3496d666775SBrian Somers const struct fsm_parent *parent) 350d1a3ea47SBrian Somers { 351503a7782SBrian Somers struct hostent *hp; 352503a7782SBrian Somers char name[MAXHOSTNAMELEN]; 3533b0f8d2eSBrian Somers static const char *timer_names[] = 3543b0f8d2eSBrian Somers {"IPCP restart", "IPCP openmode", "IPCP stopped"}; 35529e275ceSBrian Somers 356479508cfSBrian Somers fsm_Init(&ipcp->fsm, "IPCP", PROTO_IPCP, 1, IPCP_MAXCODE, LogIPCP, 3573b0f8d2eSBrian Somers bundle, l, parent, &ipcp_Callbacks, timer_names); 358503a7782SBrian Somers 359610b185fSBrian Somers ipcp->route = NULL; 3601342caedSBrian Somers ipcp->cfg.vj.slots = DEF_VJ_STATES; 3611342caedSBrian Somers ipcp->cfg.vj.slotcomp = 1; 362503a7782SBrian Somers memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range); 363503a7782SBrian Somers if (gethostname(name, sizeof name) == 0) { 364503a7782SBrian Somers hp = gethostbyname(name); 3658fa6ebe4SBrian Somers if (hp && hp->h_addrtype == AF_INET) 366503a7782SBrian Somers memcpy(&ipcp->cfg.my_range.ipaddr.s_addr, hp->h_addr, hp->h_length); 367503a7782SBrian Somers } 36830c2f2ffSBrian Somers ipcp->cfg.netmask.s_addr = INADDR_ANY; 369503a7782SBrian Somers memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 370503a7782SBrian Somers iplist_setsrc(&ipcp->cfg.peer_list, ""); 371503a7782SBrian Somers ipcp->cfg.HaveTriggerAddress = 0; 372503a7782SBrian Somers 3733edeb0c6SBrian Somers ipcp->cfg.ns.dns[0].s_addr = INADDR_ANY; 3743edeb0c6SBrian Somers ipcp->cfg.ns.dns[1].s_addr = INADDR_ANY; 3753edeb0c6SBrian Somers ipcp->cfg.ns.dns_neg = 0; 3763edeb0c6SBrian Somers ipcp->cfg.ns.nbns[0].s_addr = INADDR_ANY; 3773edeb0c6SBrian Somers ipcp->cfg.ns.nbns[1].s_addr = INADDR_ANY; 378cd9647a1SBrian Somers 379479508cfSBrian Somers ipcp->cfg.fsm.timeout = DEF_FSMRETRY; 380479508cfSBrian Somers ipcp->cfg.fsm.maxreq = DEF_FSMTRIES; 381479508cfSBrian Somers ipcp->cfg.fsm.maxtrm = DEF_FSMTRIES; 3821342caedSBrian Somers ipcp->cfg.vj.neg = NEG_ENABLED|NEG_ACCEPTED; 383503a7782SBrian Somers 384eaa4df37SBrian Somers memset(&ipcp->vj, '\0', sizeof ipcp->vj); 385eaa4df37SBrian Somers 386fdf61171SBrian Somers throughput_init(&ipcp->throughput); 3875a72b6edSBrian Somers memset(ipcp->Queue, '\0', sizeof ipcp->Queue); 388972a1bcfSBrian Somers ipcp_Setup(ipcp, INADDR_NONE); 389d1a3ea47SBrian Somers } 390d1a3ea47SBrian Somers 391af57ed9fSAtsushi Murai void 392ce828a6eSBrian Somers ipcp_SetLink(struct ipcp *ipcp, struct link *l) 393af57ed9fSAtsushi Murai { 394ce828a6eSBrian Somers ipcp->fsm.link = l; 395af57ed9fSAtsushi Murai } 396549d663dSAtsushi Murai 397ce828a6eSBrian Somers void 398972a1bcfSBrian Somers ipcp_Setup(struct ipcp *ipcp, u_int32_t mask) 399503a7782SBrian Somers { 4008fa6ebe4SBrian Somers struct iface *iface = ipcp->fsm.bundle->iface; 4018fa6ebe4SBrian Somers int pos, n; 402503a7782SBrian Somers 403503a7782SBrian Somers ipcp->fsm.open_mode = 0; 404972a1bcfSBrian Somers ipcp->ifmask.s_addr = mask == INADDR_NONE ? ipcp->cfg.netmask.s_addr : mask; 405503a7782SBrian Somers 406503a7782SBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 4078fa6ebe4SBrian Somers /* Try to give the peer a previously configured IP address */ 4088fa6ebe4SBrian Somers for (n = 0; n < iface->in_addrs; n++) { 4098fa6ebe4SBrian Somers pos = iplist_ip2pos(&ipcp->cfg.peer_list, iface->in_addr[n].brd); 4108fa6ebe4SBrian Somers if (pos != -1) { 4118fa6ebe4SBrian Somers ipcp->cfg.peer_range.ipaddr = 4128fa6ebe4SBrian Somers iplist_setcurpos(&ipcp->cfg.peer_list, pos); 4138fa6ebe4SBrian Somers break; 4148fa6ebe4SBrian Somers } 4158fa6ebe4SBrian Somers } 4168fa6ebe4SBrian Somers if (n == iface->in_addrs) 4178fa6ebe4SBrian Somers /* Ok, so none of 'em fit.... pick a random one */ 418503a7782SBrian Somers ipcp->cfg.peer_range.ipaddr = iplist_setrandpos(&ipcp->cfg.peer_list); 4198fa6ebe4SBrian Somers 420503a7782SBrian Somers ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 421503a7782SBrian Somers ipcp->cfg.peer_range.width = 32; 422503a7782SBrian Somers } 423503a7782SBrian Somers 424503a7782SBrian Somers ipcp->heis1172 = 0; 425503a7782SBrian Somers 426503a7782SBrian Somers ipcp->peer_ip = ipcp->cfg.peer_range.ipaddr; 427503a7782SBrian Somers ipcp->peer_compproto = 0; 4281ae349f5Scvs2svn 4298390b576SBrian Somers if (ipcp->cfg.HaveTriggerAddress) { 430549d663dSAtsushi Murai /* 4315b4c5b00SBrian Somers * Some implementations of PPP require that we send a 4325b4c5b00SBrian Somers * *special* value as our address, even though the rfc specifies 4335b4c5b00SBrian Somers * full negotiation (e.g. "0.0.0.0" or Not "0.0.0.0"). 434549d663dSAtsushi Murai */ 435503a7782SBrian Somers ipcp->my_ip = ipcp->cfg.TriggerAddress; 436dd7e2610SBrian Somers log_Printf(LogIPCP, "Using trigger address %s\n", 437503a7782SBrian Somers inet_ntoa(ipcp->cfg.TriggerAddress)); 4388fa6ebe4SBrian Somers } else { 4398390b576SBrian Somers /* 4408fa6ebe4SBrian Somers * Otherwise, if we've used an IP number before and it's still within 4418fa6ebe4SBrian Somers * the network specified on the ``set ifaddr'' line, we really 4428fa6ebe4SBrian Somers * want to keep that IP number so that we can keep any existing 4438fa6ebe4SBrian Somers * connections that are bound to that IP (assuming we're not 4448fa6ebe4SBrian Somers * ``iface-alias''ing). 4458390b576SBrian Somers */ 4468fa6ebe4SBrian Somers for (n = 0; n < iface->in_addrs; n++) 4478fa6ebe4SBrian Somers if ((iface->in_addr[n].ifa.s_addr & ipcp->cfg.my_range.mask.s_addr) == 4488fa6ebe4SBrian Somers (ipcp->cfg.my_range.ipaddr.s_addr & ipcp->cfg.my_range.mask.s_addr)) { 4498fa6ebe4SBrian Somers ipcp->my_ip = iface->in_addr[n].ifa; 4508fa6ebe4SBrian Somers break; 4518fa6ebe4SBrian Somers } 4528fa6ebe4SBrian Somers if (n == iface->in_addrs) 453503a7782SBrian Somers ipcp->my_ip = ipcp->cfg.my_range.ipaddr; 4548fa6ebe4SBrian Somers } 45529e275ceSBrian Somers 456972a1bcfSBrian Somers if (IsEnabled(ipcp->cfg.vj.neg) 457972a1bcfSBrian Somers #ifndef NORADIUS 458972a1bcfSBrian Somers || (ipcp->fsm.bundle->radius.valid && ipcp->fsm.bundle->radius.vj) 459972a1bcfSBrian Somers #endif 460972a1bcfSBrian Somers ) 461503a7782SBrian Somers ipcp->my_compproto = (PROTO_VJCOMP << 16) + 4621342caedSBrian Somers ((ipcp->cfg.vj.slots - 1) << 8) + 4631342caedSBrian Somers ipcp->cfg.vj.slotcomp; 4641ae349f5Scvs2svn else 465503a7782SBrian Somers ipcp->my_compproto = 0; 4661342caedSBrian Somers sl_compress_init(&ipcp->vj.cslc, ipcp->cfg.vj.slots - 1); 46729e275ceSBrian Somers 468503a7782SBrian Somers ipcp->peer_reject = 0; 469503a7782SBrian Somers ipcp->my_reject = 0; 4701ae349f5Scvs2svn } 4711ae349f5Scvs2svn 472455aabc3SBrian Somers static int 4733afe5ccbSBrian Somers ipcp_doproxyall(struct bundle *bundle, 4743afe5ccbSBrian Somers int (*proxyfun)(struct bundle *, struct in_addr, int), int s) 4753afe5ccbSBrian Somers { 4763afe5ccbSBrian Somers int n, ret; 4773afe5ccbSBrian Somers struct sticky_route *rp; 4783afe5ccbSBrian Somers struct in_addr addr; 4793afe5ccbSBrian Somers struct ipcp *ipcp; 4803afe5ccbSBrian Somers 4813afe5ccbSBrian Somers ipcp = &bundle->ncp.ipcp; 4823afe5ccbSBrian Somers for (rp = ipcp->route; rp != NULL; rp = rp->next) { 483bc76350eSBrian Somers if (rp->mask.s_addr == INADDR_BROADCAST) 4843afe5ccbSBrian Somers continue; 485bc76350eSBrian Somers n = ntohl(INADDR_BROADCAST) - ntohl(rp->mask.s_addr) - 1; 4863afe5ccbSBrian Somers if (n > 0 && n <= 254 && rp->dst.s_addr != INADDR_ANY) { 4873afe5ccbSBrian Somers addr = rp->dst; 4883afe5ccbSBrian Somers while (n--) { 4893afe5ccbSBrian Somers addr.s_addr = htonl(ntohl(addr.s_addr) + 1); 4903afe5ccbSBrian Somers log_Printf(LogDEBUG, "ipcp_doproxyall: %s\n", inet_ntoa(addr)); 4913afe5ccbSBrian Somers ret = (*proxyfun)(bundle, addr, s); 4923afe5ccbSBrian Somers if (!ret) 4933afe5ccbSBrian Somers return ret; 4943afe5ccbSBrian Somers } 4953afe5ccbSBrian Somers } 4963afe5ccbSBrian Somers } 4973afe5ccbSBrian Somers 4983afe5ccbSBrian Somers return 0; 4993afe5ccbSBrian Somers } 5003afe5ccbSBrian Somers 5013afe5ccbSBrian Somers static int 50230c2f2ffSBrian Somers ipcp_SetIPaddress(struct bundle *bundle, struct in_addr myaddr, 50330c2f2ffSBrian Somers struct in_addr hisaddr, int silent) 504455aabc3SBrian Somers { 5053afe5ccbSBrian Somers static struct in_addr none = { INADDR_ANY }; 5068fa6ebe4SBrian Somers struct in_addr mask, oaddr; 507455aabc3SBrian Somers 508bc76350eSBrian Somers mask = addr2mask(myaddr); 509455aabc3SBrian Somers 510972a1bcfSBrian Somers if (bundle->ncp.ipcp.ifmask.s_addr != INADDR_ANY && 511bc76350eSBrian Somers (bundle->ncp.ipcp.ifmask.s_addr & mask.s_addr) == mask.s_addr) 512bc76350eSBrian Somers mask.s_addr = bundle->ncp.ipcp.ifmask.s_addr; 513455aabc3SBrian Somers 5148fa6ebe4SBrian Somers oaddr.s_addr = bundle->iface->in_addrs ? 5158fa6ebe4SBrian Somers bundle->iface->in_addr[0].ifa.s_addr : INADDR_ANY; 5168fa6ebe4SBrian Somers if (!iface_inAdd(bundle->iface, myaddr, mask, hisaddr, 5178fa6ebe4SBrian Somers IFACE_ADD_FIRST|IFACE_FORCE_ADD)) 5188fa6ebe4SBrian Somers return -1; 519455aabc3SBrian Somers 5208fa6ebe4SBrian Somers if (!Enabled(bundle, OPT_IFACEALIAS) && bundle->iface->in_addrs > 1 5218fa6ebe4SBrian Somers && myaddr.s_addr != oaddr.s_addr) 5228fa6ebe4SBrian Somers /* Nuke the old one */ 5238fa6ebe4SBrian Somers iface_inDelete(bundle->iface, oaddr); 524455aabc3SBrian Somers 5253afe5ccbSBrian Somers if (bundle->ncp.ipcp.cfg.sendpipe > 0 || bundle->ncp.ipcp.cfg.recvpipe > 0) 5263afe5ccbSBrian Somers bundle_SetRoute(bundle, RTM_CHANGE, hisaddr, myaddr, none, 0, 0); 5273afe5ccbSBrian Somers 528610b185fSBrian Somers if (Enabled(bundle, OPT_SROUTES)) 529610b185fSBrian Somers route_Change(bundle, bundle->ncp.ipcp.route, myaddr, hisaddr); 530610b185fSBrian Somers 531972a1bcfSBrian Somers #ifndef NORADIUS 532972a1bcfSBrian Somers if (bundle->radius.valid) 533972a1bcfSBrian Somers route_Change(bundle, bundle->radius.routes, myaddr, hisaddr); 534972a1bcfSBrian Somers #endif 535972a1bcfSBrian Somers 5363afe5ccbSBrian Somers if (Enabled(bundle, OPT_PROXY) || Enabled(bundle, OPT_PROXYALL)) { 5378fa6ebe4SBrian Somers int s = ID0socket(AF_INET, SOCK_DGRAM, 0); 5388fa6ebe4SBrian Somers if (s < 0) 5398fa6ebe4SBrian Somers log_Printf(LogERROR, "ipcp_SetIPaddress: socket(): %s\n", 5408fa6ebe4SBrian Somers strerror(errno)); 5418fa6ebe4SBrian Somers else { 5423afe5ccbSBrian Somers if (Enabled(bundle, OPT_PROXYALL)) 5433afe5ccbSBrian Somers ipcp_doproxyall(bundle, arp_SetProxy, s); 5443afe5ccbSBrian Somers else if (Enabled(bundle, OPT_PROXY)) 5458fa6ebe4SBrian Somers arp_SetProxy(bundle, hisaddr, s); 546455aabc3SBrian Somers close(s); 5478fa6ebe4SBrian Somers } 5488fa6ebe4SBrian Somers } 5498fa6ebe4SBrian Somers 5508fa6ebe4SBrian Somers return 0; 551455aabc3SBrian Somers } 552455aabc3SBrian Somers 553455aabc3SBrian Somers static struct in_addr 5548fa6ebe4SBrian Somers ChooseHisAddr(struct bundle *bundle, struct in_addr gw) 555455aabc3SBrian Somers { 556455aabc3SBrian Somers struct in_addr try; 5573a2e4f62SBrian Somers u_long f; 558455aabc3SBrian Somers 5595828db6dSBrian Somers for (f = 0; f < bundle->ncp.ipcp.cfg.peer_list.nItems; f++) { 5605828db6dSBrian Somers try = iplist_next(&bundle->ncp.ipcp.cfg.peer_list); 5613a2e4f62SBrian Somers log_Printf(LogDEBUG, "ChooseHisAddr: Check item %ld (%s)\n", 562455aabc3SBrian Somers f, inet_ntoa(try)); 56330c2f2ffSBrian Somers if (ipcp_SetIPaddress(bundle, gw, try, 1) == 0) { 564dd7e2610SBrian Somers log_Printf(LogIPCP, "Selected IP address %s\n", inet_ntoa(try)); 565455aabc3SBrian Somers break; 566455aabc3SBrian Somers } 567455aabc3SBrian Somers } 568455aabc3SBrian Somers 5695828db6dSBrian Somers if (f == bundle->ncp.ipcp.cfg.peer_list.nItems) { 570dd7e2610SBrian Somers log_Printf(LogDEBUG, "ChooseHisAddr: All addresses in use !\n"); 571455aabc3SBrian Somers try.s_addr = INADDR_ANY; 572455aabc3SBrian Somers } 573455aabc3SBrian Somers 574455aabc3SBrian Somers return try; 575af57ed9fSAtsushi Murai } 576af57ed9fSAtsushi Murai 577af57ed9fSAtsushi Murai static void 578479508cfSBrian Somers IpcpInitRestartCounter(struct fsm *fp, int what) 579af57ed9fSAtsushi Murai { 5807308ec68SBrian Somers /* Set fsm timer load */ 581cd9647a1SBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 582cd9647a1SBrian Somers 583479508cfSBrian Somers fp->FsmTimer.load = ipcp->cfg.fsm.timeout * SECTICKS; 584479508cfSBrian Somers switch (what) { 585479508cfSBrian Somers case FSM_REQ_TIMER: 586479508cfSBrian Somers fp->restart = ipcp->cfg.fsm.maxreq; 587479508cfSBrian Somers break; 588479508cfSBrian Somers case FSM_TRM_TIMER: 589479508cfSBrian Somers fp->restart = ipcp->cfg.fsm.maxtrm; 590479508cfSBrian Somers break; 591479508cfSBrian Somers default: 592479508cfSBrian Somers fp->restart = 1; 593479508cfSBrian Somers break; 594479508cfSBrian Somers } 595af57ed9fSAtsushi Murai } 596af57ed9fSAtsushi Murai 597af57ed9fSAtsushi Murai static void 598944f7098SBrian Somers IpcpSendConfigReq(struct fsm *fp) 599af57ed9fSAtsushi Murai { 6007308ec68SBrian Somers /* Send config REQ please */ 6018c07a7b2SBrian Somers struct physical *p = link2physical(fp->link); 602aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 6033edeb0c6SBrian Somers u_char buff[24]; 6042267893fSBrian Somers struct lcp_opt *o; 605af57ed9fSAtsushi Murai 6062267893fSBrian Somers o = (struct lcp_opt *)buff; 60730c2f2ffSBrian Somers 608dd7e2610SBrian Somers if ((p && !physical_IsSync(p)) || !REJECTED(ipcp, TY_IPADDR)) { 6099e8ec64bSBrian Somers memcpy(o->data, &ipcp->my_ip.s_addr, 4); 6102267893fSBrian Somers INC_LCP_OPT(TY_IPADDR, 6, o); 6110053cc58SBrian Somers } 6120053cc58SBrian Somers 613e43ebac1SBrian Somers if (ipcp->my_compproto && !REJECTED(ipcp, TY_COMPPROTO)) { 61483d1af55SBrian Somers if (ipcp->heis1172) { 6159e8ec64bSBrian Somers u_int16_t proto = PROTO_VJCOMP; 6169e8ec64bSBrian Somers 6179e8ec64bSBrian Somers ua_htons(&proto, o->data); 6182267893fSBrian Somers INC_LCP_OPT(TY_COMPPROTO, 4, o); 6190053cc58SBrian Somers } else { 6207686a200SBrian Somers struct compreq req; 6217686a200SBrian Somers 6227686a200SBrian Somers req.proto = htons(ipcp->my_compproto >> 16); 6237686a200SBrian Somers req.slots = (ipcp->my_compproto >> 8) & 255; 6247686a200SBrian Somers req.compcid = ipcp->my_compproto & 1; 6257686a200SBrian Somers memcpy(o->data, &req, 4); 6262267893fSBrian Somers INC_LCP_OPT(TY_COMPPROTO, 6, o); 6270053cc58SBrian Somers } 628af57ed9fSAtsushi Murai } 6292267893fSBrian Somers 6303edeb0c6SBrian Somers if (IsEnabled(ipcp->cfg.ns.dns_neg) && 6313edeb0c6SBrian Somers !REJECTED(ipcp, TY_PRIMARY_DNS - TY_ADJUST_NS) && 6323edeb0c6SBrian Somers !REJECTED(ipcp, TY_SECONDARY_DNS - TY_ADJUST_NS)) { 6333edeb0c6SBrian Somers struct in_addr dns[2]; 6343edeb0c6SBrian Somers getdns(ipcp, dns); 6359e8ec64bSBrian Somers memcpy(o->data, &dns[0].s_addr, 4); 6363edeb0c6SBrian Somers INC_LCP_OPT(TY_PRIMARY_DNS, 6, o); 6379e8ec64bSBrian Somers memcpy(o->data, &dns[1].s_addr, 4); 6383edeb0c6SBrian Somers INC_LCP_OPT(TY_SECONDARY_DNS, 6, o); 6393edeb0c6SBrian Somers } 6403edeb0c6SBrian Somers 641dd7e2610SBrian Somers fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff); 642af57ed9fSAtsushi Murai } 643af57ed9fSAtsushi Murai 644af57ed9fSAtsushi Murai static void 6452267893fSBrian Somers IpcpSentTerminateReq(struct fsm *fp) 646af57ed9fSAtsushi Murai { 6477308ec68SBrian Somers /* Term REQ just sent by FSM */ 648af57ed9fSAtsushi Murai } 649af57ed9fSAtsushi Murai 650af57ed9fSAtsushi Murai static void 6512267893fSBrian Somers IpcpSendTerminateAck(struct fsm *fp, u_char id) 652af57ed9fSAtsushi Murai { 6537308ec68SBrian Somers /* Send Term ACK please */ 654dd7e2610SBrian Somers fsm_Output(fp, CODE_TERMACK, id, NULL, 0); 655af57ed9fSAtsushi Murai } 656af57ed9fSAtsushi Murai 657af57ed9fSAtsushi Murai static void 658944f7098SBrian Somers IpcpLayerStart(struct fsm *fp) 659af57ed9fSAtsushi Murai { 6607308ec68SBrian Somers /* We're about to start up ! */ 661897f9429SBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 662897f9429SBrian Somers 6633a2e4f62SBrian Somers log_Printf(LogIPCP, "%s: LayerStart.\n", fp->link->name); 664897f9429SBrian Somers throughput_start(&ipcp->throughput, "IPCP throughput", 665897f9429SBrian Somers Enabled(fp->bundle, OPT_THROUGHPUT)); 666479508cfSBrian Somers fp->more.reqs = fp->more.naks = fp->more.rejs = ipcp->cfg.fsm.maxreq * 3; 667af57ed9fSAtsushi Murai } 668af57ed9fSAtsushi Murai 669af57ed9fSAtsushi Murai static void 670944f7098SBrian Somers IpcpLayerFinish(struct fsm *fp) 671af57ed9fSAtsushi Murai { 6727308ec68SBrian Somers /* We're now down */ 673897f9429SBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 674897f9429SBrian Somers 6753a2e4f62SBrian Somers log_Printf(LogIPCP, "%s: LayerFinish.\n", fp->link->name); 676897f9429SBrian Somers throughput_stop(&ipcp->throughput); 677897f9429SBrian Somers throughput_log(&ipcp->throughput, LogIPCP, NULL); 6781ae349f5Scvs2svn } 6791ae349f5Scvs2svn 68068a0f0ccSBrian Somers void 681dd7e2610SBrian Somers ipcp_CleanInterface(struct ipcp *ipcp) 68268a0f0ccSBrian Somers { 6838fa6ebe4SBrian Somers struct iface *iface = ipcp->fsm.bundle->iface; 68468a0f0ccSBrian Somers 685610b185fSBrian Somers route_Clean(ipcp->fsm.bundle, ipcp->route); 686610b185fSBrian Somers 6873afe5ccbSBrian Somers if (iface->in_addrs && (Enabled(ipcp->fsm.bundle, OPT_PROXY) || 6883afe5ccbSBrian Somers Enabled(ipcp->fsm.bundle, OPT_PROXYALL))) { 6898fa6ebe4SBrian Somers int s = ID0socket(AF_INET, SOCK_DGRAM, 0); 6908fa6ebe4SBrian Somers if (s < 0) 6918fa6ebe4SBrian Somers log_Printf(LogERROR, "ipcp_CleanInterface: socket: %s\n", 69268a0f0ccSBrian Somers strerror(errno)); 6938fa6ebe4SBrian Somers else { 6943afe5ccbSBrian Somers if (Enabled(ipcp->fsm.bundle, OPT_PROXYALL)) 6953afe5ccbSBrian Somers ipcp_doproxyall(ipcp->fsm.bundle, arp_ClearProxy, s); 6963afe5ccbSBrian Somers else if (Enabled(ipcp->fsm.bundle, OPT_PROXY)) 6978fa6ebe4SBrian Somers arp_ClearProxy(ipcp->fsm.bundle, iface->in_addr[0].brd, s); 6988fa6ebe4SBrian Somers close(s); 6998fa6ebe4SBrian Somers } 70068a0f0ccSBrian Somers } 70168a0f0ccSBrian Somers 7028fa6ebe4SBrian Somers iface_inClear(ipcp->fsm.bundle->iface, IFACE_CLEAR_ALL); 703af57ed9fSAtsushi Murai } 704af57ed9fSAtsushi Murai 705af57ed9fSAtsushi Murai static void 706944f7098SBrian Somers IpcpLayerDown(struct fsm *fp) 707af57ed9fSAtsushi Murai { 7087308ec68SBrian Somers /* About to come down */ 709aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 710455aabc3SBrian Somers const char *s; 711455aabc3SBrian Somers 7128fa6ebe4SBrian Somers if (ipcp->fsm.bundle->iface->in_addrs) 7138fa6ebe4SBrian Somers s = inet_ntoa(ipcp->fsm.bundle->iface->in_addr[0].ifa); 7148fa6ebe4SBrian Somers else 7158fa6ebe4SBrian Somers s = "Interface configuration error !"; 7163a2e4f62SBrian Somers log_Printf(LogIPCP, "%s: LayerDown: %s\n", fp->link->name, s); 717455aabc3SBrian Somers 718455aabc3SBrian Somers /* 719455aabc3SBrian Somers * XXX this stuff should really live in the FSM. Our config should 720455aabc3SBrian Somers * associate executable sections in files with events. 721455aabc3SBrian Somers */ 72230291ffbSBrian Somers if (system_Select(fp->bundle, s, LINKDOWNFILE, NULL, NULL) < 0) { 72349052c95SBrian Somers if (bundle_GetLabel(fp->bundle)) { 724dd7e2610SBrian Somers if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle), 72530291ffbSBrian Somers LINKDOWNFILE, NULL, NULL) < 0) 72630291ffbSBrian Somers system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL); 727455aabc3SBrian Somers } else 72830291ffbSBrian Somers system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL); 729af57ed9fSAtsushi Murai } 730af57ed9fSAtsushi Murai 731972a1bcfSBrian Somers ipcp_Setup(ipcp, INADDR_NONE); 7321ae349f5Scvs2svn } 7331ae349f5Scvs2svn 734dd0645c5SBrian Somers int 735dd0645c5SBrian Somers ipcp_InterfaceUp(struct ipcp *ipcp) 736dd0645c5SBrian Somers { 737dd0645c5SBrian Somers if (ipcp_SetIPaddress(ipcp->fsm.bundle, ipcp->my_ip, ipcp->peer_ip, 0) < 0) { 738a33b2ef7SBrian Somers log_Printf(LogERROR, "ipcp_InterfaceUp: unable to set ip address\n"); 739dd0645c5SBrian Somers return 0; 740dd0645c5SBrian Somers } 741dd0645c5SBrian Somers 742dd0645c5SBrian Somers #ifndef NOALIAS 743615ad4f9SBrian Somers if (ipcp->fsm.bundle->AliasEnabled) 744615ad4f9SBrian Somers PacketAliasSetAddress(ipcp->my_ip); 745dd0645c5SBrian Somers #endif 746dd0645c5SBrian Somers 747dd0645c5SBrian Somers return 1; 748dd0645c5SBrian Somers } 749dd0645c5SBrian Somers 7506f384573SBrian Somers static int 751944f7098SBrian Somers IpcpLayerUp(struct fsm *fp) 752af57ed9fSAtsushi Murai { 7537308ec68SBrian Somers /* We're now up */ 754aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 7558fa6ebe4SBrian Somers char tbuff[16]; 756af57ed9fSAtsushi Murai 7573a2e4f62SBrian Somers log_Printf(LogIPCP, "%s: LayerUp.\n", fp->link->name); 7588fa6ebe4SBrian Somers snprintf(tbuff, sizeof tbuff, "%s", inet_ntoa(ipcp->my_ip)); 7598fa6ebe4SBrian Somers log_Printf(LogIPCP, "myaddr %s hisaddr = %s\n", 7608fa6ebe4SBrian Somers tbuff, inet_ntoa(ipcp->peer_ip)); 76103604f35SBrian Somers 762503a7782SBrian Somers if (ipcp->peer_compproto >> 16 == PROTO_VJCOMP) 763eaa4df37SBrian Somers sl_compress_init(&ipcp->vj.cslc, (ipcp->peer_compproto >> 8) & 255); 76403604f35SBrian Somers 765dd0645c5SBrian Somers if (!ipcp_InterfaceUp(ipcp)) 7666f384573SBrian Somers return 0; 767455aabc3SBrian Somers 768455aabc3SBrian Somers /* 769455aabc3SBrian Somers * XXX this stuff should really live in the FSM. Our config should 770455aabc3SBrian Somers * associate executable sections in files with events. 771455aabc3SBrian Somers */ 7728fa6ebe4SBrian Somers if (system_Select(fp->bundle, tbuff, LINKUPFILE, NULL, NULL) < 0) { 77349052c95SBrian Somers if (bundle_GetLabel(fp->bundle)) { 774dd7e2610SBrian Somers if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle), 77530291ffbSBrian Somers LINKUPFILE, NULL, NULL) < 0) 77630291ffbSBrian Somers system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL); 777455aabc3SBrian Somers } else 77830291ffbSBrian Somers system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL); 779af57ed9fSAtsushi Murai } 780af57ed9fSAtsushi Murai 781479508cfSBrian Somers fp->more.reqs = fp->more.naks = fp->more.rejs = ipcp->cfg.fsm.maxreq * 3; 7820f2f3eb3SBrian Somers log_DisplayPrompts(); 783479508cfSBrian Somers 7846f384573SBrian Somers return 1; 785af57ed9fSAtsushi Murai } 786af57ed9fSAtsushi Murai 787af57ed9fSAtsushi Murai static int 7888fa6ebe4SBrian Somers AcceptableAddr(const struct in_range *prange, struct in_addr ipaddr) 789af57ed9fSAtsushi Murai { 7907308ec68SBrian Somers /* Is the given IP in the given range ? */ 791057df964SBrian Somers return (prange->ipaddr.s_addr & prange->mask.s_addr) == 792057df964SBrian Somers (ipaddr.s_addr & prange->mask.s_addr) && ipaddr.s_addr; 793af57ed9fSAtsushi Murai } 794af57ed9fSAtsushi Murai 795af57ed9fSAtsushi Murai static void 79630c2f2ffSBrian Somers IpcpDecodeConfig(struct fsm *fp, u_char * cp, int plen, int mode_type, 79730c2f2ffSBrian Somers struct fsm_decode *dec) 798af57ed9fSAtsushi Murai { 7997308ec68SBrian Somers /* Deal with incoming PROTO_IPCP */ 8008fa6ebe4SBrian Somers struct iface *iface = fp->bundle->iface; 801aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 8028fa6ebe4SBrian Somers int type, length, gotdns, gotdnsnak, n; 803fe3125a0SBrian Somers u_int32_t compproto; 804af57ed9fSAtsushi Murai struct compreq *pcomp; 8053edeb0c6SBrian Somers struct in_addr ipaddr, dstipaddr, have_ip, dns[2], dnsnak[2]; 80630c2f2ffSBrian Somers char tbuff[100], tbuff2[100]; 807af57ed9fSAtsushi Murai 8083edeb0c6SBrian Somers gotdns = 0; 8093edeb0c6SBrian Somers gotdnsnak = 0; 8103edeb0c6SBrian Somers dnsnak[0].s_addr = dnsnak[1].s_addr = INADDR_ANY; 811af57ed9fSAtsushi Murai 812af57ed9fSAtsushi Murai while (plen >= sizeof(struct fsmconfig)) { 813af57ed9fSAtsushi Murai type = *cp; 814af57ed9fSAtsushi Murai length = cp[1]; 815d47dceb8SBrian Somers 816d47dceb8SBrian Somers if (length == 0) { 817dd7e2610SBrian Somers log_Printf(LogIPCP, "%s: IPCP size zero\n", fp->link->name); 818d47dceb8SBrian Somers break; 819d47dceb8SBrian Somers } 820d47dceb8SBrian Somers 8219e836af5SBrian Somers if (type < NCFTYPES) 82270ee81ffSBrian Somers snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes[type], length); 8239e836af5SBrian Somers else if (type > 128 && type < 128 + NCFTYPES128) 82470ee81ffSBrian Somers snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes128[type-128], length); 825af57ed9fSAtsushi Murai else 82670ee81ffSBrian Somers snprintf(tbuff, sizeof tbuff, " <%d>[%d] ", type, length); 827af57ed9fSAtsushi Murai 828af57ed9fSAtsushi Murai switch (type) { 829af57ed9fSAtsushi Murai case TY_IPADDR: /* RFC1332 */ 8309e8ec64bSBrian Somers memcpy(&ipaddr.s_addr, cp + 2, 4); 831dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 832af57ed9fSAtsushi Murai 8339780ef31SBrian Somers switch (mode_type) { 834af57ed9fSAtsushi Murai case MODE_REQ: 835503a7782SBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 836f5fb6bd0SBrian Somers if (ipaddr.s_addr == INADDR_ANY || 837503a7782SBrian Somers iplist_ip2pos(&ipcp->cfg.peer_list, ipaddr) < 0 || 83830c2f2ffSBrian Somers ipcp_SetIPaddress(fp->bundle, ipcp->cfg.my_range.ipaddr, 83930c2f2ffSBrian Somers ipaddr, 1)) { 840dd7e2610SBrian Somers log_Printf(LogIPCP, "%s: Address invalid or already in use\n", 841bcc332bdSBrian Somers inet_ntoa(ipaddr)); 8428390b576SBrian Somers /* 8438fa6ebe4SBrian Somers * If we've already had a valid address configured for the peer, 8448fa6ebe4SBrian Somers * try NAKing with that so that we don't have to upset things 8458fa6ebe4SBrian Somers * too much. 8468390b576SBrian Somers */ 8478fa6ebe4SBrian Somers for (n = 0; n < iface->in_addrs; n++) 8488fa6ebe4SBrian Somers if (iplist_ip2pos(&ipcp->cfg.peer_list, iface->in_addr[n].brd) 8498fa6ebe4SBrian Somers >=0) { 8508fa6ebe4SBrian Somers ipcp->peer_ip = iface->in_addr[n].brd; 8518fa6ebe4SBrian Somers break; 8528fa6ebe4SBrian Somers } 8538fa6ebe4SBrian Somers 8548fa6ebe4SBrian Somers if (n == iface->in_addrs) 8558390b576SBrian Somers /* Just pick an IP number from our list */ 856503a7782SBrian Somers ipcp->peer_ip = ChooseHisAddr 85730c2f2ffSBrian Somers (fp->bundle, ipcp->cfg.my_range.ipaddr); 8588390b576SBrian Somers 859503a7782SBrian Somers if (ipcp->peer_ip.s_addr == INADDR_ANY) { 86030c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 86130c2f2ffSBrian Somers dec->rejend += length; 862bcc332bdSBrian Somers } else { 86330c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 86430c2f2ffSBrian Somers memcpy(dec->nakend + 2, &ipcp->peer_ip.s_addr, length - 2); 86530c2f2ffSBrian Somers dec->nakend += length; 866bcc332bdSBrian Somers } 867bcc332bdSBrian Somers break; 868bcc332bdSBrian Somers } 869503a7782SBrian Somers } else if (!AcceptableAddr(&ipcp->cfg.peer_range, ipaddr)) { 870af57ed9fSAtsushi Murai /* 8718390b576SBrian Somers * If destination address is not acceptable, NAK with what we 872944f7098SBrian Somers * want to use. 873af57ed9fSAtsushi Murai */ 87430c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 8758fa6ebe4SBrian Somers for (n = 0; n < iface->in_addrs; n++) 8768fa6ebe4SBrian Somers if ((iface->in_addr[n].brd.s_addr & 8778fa6ebe4SBrian Somers ipcp->cfg.peer_range.mask.s_addr) 8788fa6ebe4SBrian Somers == (ipcp->cfg.peer_range.ipaddr.s_addr & 8798fa6ebe4SBrian Somers ipcp->cfg.peer_range.mask.s_addr)) { 8808390b576SBrian Somers /* We prefer the already-configured address */ 8818fa6ebe4SBrian Somers memcpy(dec->nakend + 2, &iface->in_addr[n].brd.s_addr, 8828fa6ebe4SBrian Somers length - 2); 8838fa6ebe4SBrian Somers break; 8848fa6ebe4SBrian Somers } 8858fa6ebe4SBrian Somers 8868fa6ebe4SBrian Somers if (n == iface->in_addrs) 88730c2f2ffSBrian Somers memcpy(dec->nakend + 2, &ipcp->peer_ip.s_addr, length - 2); 8888fa6ebe4SBrian Somers 88930c2f2ffSBrian Somers dec->nakend += length; 890af57ed9fSAtsushi Murai break; 891af57ed9fSAtsushi Murai } 892503a7782SBrian Somers ipcp->peer_ip = ipaddr; 89330c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 89430c2f2ffSBrian Somers dec->ackend += length; 895af57ed9fSAtsushi Murai break; 8968fa6ebe4SBrian Somers 897af57ed9fSAtsushi Murai case MODE_NAK: 898503a7782SBrian Somers if (AcceptableAddr(&ipcp->cfg.my_range, ipaddr)) { 899bcc332bdSBrian Somers /* Use address suggested by peer */ 90070ee81ffSBrian Somers snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s ", tbuff, 901503a7782SBrian Somers inet_ntoa(ipcp->my_ip)); 902dd7e2610SBrian Somers log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 903503a7782SBrian Somers ipcp->my_ip = ipaddr; 904bcc332bdSBrian Somers } else { 905dd7e2610SBrian Somers log_Printf(log_IsKept(LogIPCP) ? LogIPCP : LogPHASE, 9068390b576SBrian Somers "%s: Unacceptable address!\n", inet_ntoa(ipaddr)); 907dd7e2610SBrian Somers fsm_Close(&ipcp->fsm); 908af57ed9fSAtsushi Murai } 909af57ed9fSAtsushi Murai break; 9108fa6ebe4SBrian Somers 911af57ed9fSAtsushi Murai case MODE_REJ: 912503a7782SBrian Somers ipcp->peer_reject |= (1 << type); 913af57ed9fSAtsushi Murai break; 914af57ed9fSAtsushi Murai } 915af57ed9fSAtsushi Murai break; 9168fa6ebe4SBrian Somers 917af57ed9fSAtsushi Murai case TY_COMPPROTO: 9187686a200SBrian Somers pcomp = (struct compreq *)(cp + 2); 9197686a200SBrian Somers compproto = (ntohs(pcomp->proto) << 16) + (pcomp->slots << 8) + 9207686a200SBrian Somers pcomp->compcid; 921dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto)); 922af57ed9fSAtsushi Murai 9239780ef31SBrian Somers switch (mode_type) { 924af57ed9fSAtsushi Murai case MODE_REQ: 9251342caedSBrian Somers if (!IsAccepted(ipcp->cfg.vj.neg)) { 92630c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 92730c2f2ffSBrian Somers dec->rejend += length; 928af57ed9fSAtsushi Murai } else { 929af57ed9fSAtsushi Murai switch (length) { 930af57ed9fSAtsushi Murai case 4: /* RFC1172 */ 931af57ed9fSAtsushi Murai if (ntohs(pcomp->proto) == PROTO_VJCOMP) { 9327686a200SBrian Somers log_Printf(LogWARN, "Peer is speaking RFC1172 compression " 9337686a200SBrian Somers "protocol !\n"); 93483d1af55SBrian Somers ipcp->heis1172 = 1; 935503a7782SBrian Somers ipcp->peer_compproto = compproto; 93630c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 93730c2f2ffSBrian Somers dec->ackend += length; 938af57ed9fSAtsushi Murai } else { 93930c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 940af57ed9fSAtsushi Murai pcomp->proto = htons(PROTO_VJCOMP); 94130c2f2ffSBrian Somers memcpy(dec->nakend+2, &pcomp, 2); 94230c2f2ffSBrian Somers dec->nakend += length; 943af57ed9fSAtsushi Murai } 944af57ed9fSAtsushi Murai break; 945af57ed9fSAtsushi Murai case 6: /* RFC1332 */ 9467686a200SBrian Somers if (ntohs(pcomp->proto) == PROTO_VJCOMP) { 9477686a200SBrian Somers if (pcomp->slots <= MAX_VJ_STATES 948503a7782SBrian Somers && pcomp->slots >= MIN_VJ_STATES) { 9497686a200SBrian Somers /* Ok, we can do that */ 950503a7782SBrian Somers ipcp->peer_compproto = compproto; 95183d1af55SBrian Somers ipcp->heis1172 = 0; 95230c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 95330c2f2ffSBrian Somers dec->ackend += length; 954af57ed9fSAtsushi Murai } else { 9557686a200SBrian Somers /* Get as close as we can to what he wants */ 9567686a200SBrian Somers ipcp->heis1172 = 0; 9577686a200SBrian Somers memcpy(dec->nakend, cp, 2); 9587686a200SBrian Somers pcomp->slots = pcomp->slots < MIN_VJ_STATES ? 9597686a200SBrian Somers MIN_VJ_STATES : MAX_VJ_STATES; 9607686a200SBrian Somers memcpy(dec->nakend+2, &pcomp, sizeof pcomp); 9617686a200SBrian Somers dec->nakend += length; 9627686a200SBrian Somers } 9637686a200SBrian Somers } else { 9647686a200SBrian Somers /* What we really want */ 96530c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 966af57ed9fSAtsushi Murai pcomp->proto = htons(PROTO_VJCOMP); 967503a7782SBrian Somers pcomp->slots = DEF_VJ_STATES; 9687686a200SBrian Somers pcomp->compcid = 1; 96930c2f2ffSBrian Somers memcpy(dec->nakend+2, &pcomp, sizeof pcomp); 97030c2f2ffSBrian Somers dec->nakend += length; 971af57ed9fSAtsushi Murai } 972af57ed9fSAtsushi Murai break; 973af57ed9fSAtsushi Murai default: 97430c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 97530c2f2ffSBrian Somers dec->rejend += length; 976af57ed9fSAtsushi Murai break; 977af57ed9fSAtsushi Murai } 978af57ed9fSAtsushi Murai } 979af57ed9fSAtsushi Murai break; 9808fa6ebe4SBrian Somers 981af57ed9fSAtsushi Murai case MODE_NAK: 9827686a200SBrian Somers if (ntohs(pcomp->proto) == PROTO_VJCOMP) { 9837686a200SBrian Somers if (pcomp->slots > MAX_VJ_STATES) 9847686a200SBrian Somers pcomp->slots = MAX_VJ_STATES; 9857686a200SBrian Somers else if (pcomp->slots < MIN_VJ_STATES) 9867686a200SBrian Somers pcomp->slots = MIN_VJ_STATES; 9877686a200SBrian Somers compproto = (ntohs(pcomp->proto) << 16) + (pcomp->slots << 8) + 9887686a200SBrian Somers pcomp->compcid; 9897686a200SBrian Somers } else 9907686a200SBrian Somers compproto = 0; 991dd7e2610SBrian Somers log_Printf(LogIPCP, "%s changing compproto: %08x --> %08x\n", 992503a7782SBrian Somers tbuff, ipcp->my_compproto, compproto); 993503a7782SBrian Somers ipcp->my_compproto = compproto; 994af57ed9fSAtsushi Murai break; 9958fa6ebe4SBrian Somers 996af57ed9fSAtsushi Murai case MODE_REJ: 997503a7782SBrian Somers ipcp->peer_reject |= (1 << type); 998af57ed9fSAtsushi Murai break; 999af57ed9fSAtsushi Murai } 1000af57ed9fSAtsushi Murai break; 10018fa6ebe4SBrian Somers 1002af57ed9fSAtsushi Murai case TY_IPADDRS: /* RFC1172 */ 10039e8ec64bSBrian Somers memcpy(&ipaddr.s_addr, cp + 2, 4); 10049e8ec64bSBrian Somers memcpy(&dstipaddr.s_addr, cp + 6, 4); 100570ee81ffSBrian Somers snprintf(tbuff2, sizeof tbuff2, "%s %s,", tbuff, inet_ntoa(ipaddr)); 1006dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr)); 1007af57ed9fSAtsushi Murai 10089780ef31SBrian Somers switch (mode_type) { 1009af57ed9fSAtsushi Murai case MODE_REQ: 1010503a7782SBrian Somers ipcp->peer_ip = ipaddr; 1011503a7782SBrian Somers ipcp->my_ip = dstipaddr; 101230c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 101330c2f2ffSBrian Somers dec->ackend += length; 1014af57ed9fSAtsushi Murai break; 10158fa6ebe4SBrian Somers 1016af57ed9fSAtsushi Murai case MODE_NAK: 101770ee81ffSBrian Somers snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s", tbuff, 1018503a7782SBrian Somers inet_ntoa(ipcp->my_ip)); 1019dd7e2610SBrian Somers log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 1020503a7782SBrian Somers ipcp->my_ip = ipaddr; 1021503a7782SBrian Somers ipcp->peer_ip = dstipaddr; 1022af57ed9fSAtsushi Murai break; 10238fa6ebe4SBrian Somers 1024af57ed9fSAtsushi Murai case MODE_REJ: 1025503a7782SBrian Somers ipcp->peer_reject |= (1 << type); 1026af57ed9fSAtsushi Murai break; 1027af57ed9fSAtsushi Murai } 1028af57ed9fSAtsushi Murai break; 1029d8e55738SJordan K. Hubbard 10303edeb0c6SBrian Somers case TY_PRIMARY_DNS: /* DNS negotiation (rfc1877) */ 1031d8e55738SJordan K. Hubbard case TY_SECONDARY_DNS: 10329e8ec64bSBrian Somers memcpy(&ipaddr.s_addr, cp + 2, 4); 1033dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 10343edeb0c6SBrian Somers 10359780ef31SBrian Somers switch (mode_type) { 1036d8e55738SJordan K. Hubbard case MODE_REQ: 10373edeb0c6SBrian Somers if (!IsAccepted(ipcp->cfg.ns.dns_neg)) { 10383edeb0c6SBrian Somers ipcp->my_reject |= (1 << (type - TY_ADJUST_NS)); 103930c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 104030c2f2ffSBrian Somers dec->rejend += length; 1041d8e55738SJordan K. Hubbard break; 1042d8e55738SJordan K. Hubbard } 10433edeb0c6SBrian Somers if (!gotdns) { 10443edeb0c6SBrian Somers dns[0] = ipcp->cfg.ns.dns[0]; 10453edeb0c6SBrian Somers dns[1] = ipcp->cfg.ns.dns[1]; 10463edeb0c6SBrian Somers if (dns[0].s_addr == INADDR_ANY && dns[1].s_addr == INADDR_ANY) 10473edeb0c6SBrian Somers getdns(ipcp, dns); 10483edeb0c6SBrian Somers gotdns = 1; 10493edeb0c6SBrian Somers } 10503edeb0c6SBrian Somers have_ip = dns[type == TY_PRIMARY_DNS ? 0 : 1]; 1051944f7098SBrian Somers 10523edeb0c6SBrian Somers if (ipaddr.s_addr != have_ip.s_addr) { 10531ae349f5Scvs2svn /* 10543edeb0c6SBrian Somers * The client has got the DNS stuff wrong (first request) so 10551ae349f5Scvs2svn * we'll tell 'em how it is 10561ae349f5Scvs2svn */ 105730c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); /* copy first two (type/length) */ 10583edeb0c6SBrian Somers memcpy(dec->nakend + 2, &have_ip.s_addr, length - 2); 105930c2f2ffSBrian Somers dec->nakend += length; 10603edeb0c6SBrian Somers } else { 1061d8e55738SJordan K. Hubbard /* 1062944f7098SBrian Somers * Otherwise they have it right (this time) so we send a ack packet 1063944f7098SBrian Somers * back confirming it... end of story 1064d8e55738SJordan K. Hubbard */ 106530c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 106630c2f2ffSBrian Somers dec->ackend += length; 10673edeb0c6SBrian Somers } 1068d8e55738SJordan K. Hubbard break; 10698fa6ebe4SBrian Somers 1070d8e55738SJordan K. Hubbard case MODE_NAK: /* what does this mean?? */ 10713edeb0c6SBrian Somers if (IsEnabled(ipcp->cfg.ns.dns_neg)) { 10723edeb0c6SBrian Somers gotdnsnak = 1; 10739e8ec64bSBrian Somers memcpy(&dnsnak[type == TY_PRIMARY_DNS ? 0 : 1].s_addr, cp + 2, 4); 10743edeb0c6SBrian Somers } 1075d8e55738SJordan K. Hubbard break; 10768fa6ebe4SBrian Somers 10773edeb0c6SBrian Somers case MODE_REJ: /* Can't do much, stop asking */ 10783edeb0c6SBrian Somers ipcp->peer_reject |= (1 << (type - TY_ADJUST_NS)); 1079d8e55738SJordan K. Hubbard break; 1080d8e55738SJordan K. Hubbard } 1081d8e55738SJordan K. Hubbard break; 1082d8e55738SJordan K. Hubbard 10833edeb0c6SBrian Somers case TY_PRIMARY_NBNS: /* M$ NetBIOS nameserver hack (rfc1877) */ 1084d8e55738SJordan K. Hubbard case TY_SECONDARY_NBNS: 10859e8ec64bSBrian Somers memcpy(&ipaddr.s_addr, cp + 2, 4); 1086dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 10873edeb0c6SBrian Somers 10889780ef31SBrian Somers switch (mode_type) { 1089d8e55738SJordan K. Hubbard case MODE_REQ: 10903edeb0c6SBrian Somers have_ip.s_addr = 10913edeb0c6SBrian Somers ipcp->cfg.ns.nbns[type == TY_PRIMARY_NBNS ? 0 : 1].s_addr; 10923edeb0c6SBrian Somers 10933edeb0c6SBrian Somers if (have_ip.s_addr == INADDR_ANY) { 1094dd7e2610SBrian Somers log_Printf(LogIPCP, "NBNS REQ - rejected - nbns not set\n"); 10953edeb0c6SBrian Somers ipcp->my_reject |= (1 << (type - TY_ADJUST_NS)); 109630c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 109730c2f2ffSBrian Somers dec->rejend += length; 1098d8e55738SJordan K. Hubbard break; 1099d8e55738SJordan K. Hubbard } 11003edeb0c6SBrian Somers 11013edeb0c6SBrian Somers if (ipaddr.s_addr != have_ip.s_addr) { 110230c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 11033edeb0c6SBrian Somers memcpy(dec->nakend+2, &have_ip.s_addr, length); 110430c2f2ffSBrian Somers dec->nakend += length; 11053edeb0c6SBrian Somers } else { 110630c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 110730c2f2ffSBrian Somers dec->ackend += length; 11083edeb0c6SBrian Somers } 1109d8e55738SJordan K. Hubbard break; 11108fa6ebe4SBrian Somers 1111d8e55738SJordan K. Hubbard case MODE_NAK: 1112dd7e2610SBrian Somers log_Printf(LogIPCP, "MS NBNS req %d - NAK??\n", type); 1113d8e55738SJordan K. Hubbard break; 11148fa6ebe4SBrian Somers 1115d8e55738SJordan K. Hubbard case MODE_REJ: 1116dd7e2610SBrian Somers log_Printf(LogIPCP, "MS NBNS req %d - REJ??\n", type); 1117d8e55738SJordan K. Hubbard break; 1118d8e55738SJordan K. Hubbard } 1119d8e55738SJordan K. Hubbard break; 1120d8e55738SJordan K. Hubbard 1121af57ed9fSAtsushi Murai default: 112230c2f2ffSBrian Somers if (mode_type != MODE_NOP) { 112383d1af55SBrian Somers ipcp->my_reject |= (1 << type); 112430c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 112530c2f2ffSBrian Somers dec->rejend += length; 112630c2f2ffSBrian Somers } 1127af57ed9fSAtsushi Murai break; 1128af57ed9fSAtsushi Murai } 1129af57ed9fSAtsushi Murai plen -= length; 1130af57ed9fSAtsushi Murai cp += length; 1131af57ed9fSAtsushi Murai } 11321342caedSBrian Somers 11333edeb0c6SBrian Somers if (gotdnsnak) 11343edeb0c6SBrian Somers if (!setdns(ipcp, dnsnak)) { 11353edeb0c6SBrian Somers ipcp->peer_reject |= (1 << (TY_PRIMARY_DNS - TY_ADJUST_NS)); 11363edeb0c6SBrian Somers ipcp->peer_reject |= (1 << (TY_SECONDARY_DNS - TY_ADJUST_NS)); 11373edeb0c6SBrian Somers } 11383edeb0c6SBrian Somers 1139e43ebac1SBrian Somers if (mode_type != MODE_NOP) { 11401342caedSBrian Somers if (dec->rejend != dec->rej) { 11411342caedSBrian Somers /* rejects are preferred */ 11421342caedSBrian Somers dec->ackend = dec->ack; 11431342caedSBrian Somers dec->nakend = dec->nak; 11441342caedSBrian Somers } else if (dec->nakend != dec->nak) 11451342caedSBrian Somers /* then NAKs */ 11461342caedSBrian Somers dec->ackend = dec->ack; 11471ae349f5Scvs2svn } 1148af57ed9fSAtsushi Murai } 1149af57ed9fSAtsushi Murai 1150af57ed9fSAtsushi Murai void 1151641684cdSBrian Somers ipcp_Input(struct ipcp *ipcp, struct bundle *bundle, struct mbuf *bp) 1152af57ed9fSAtsushi Murai { 11537308ec68SBrian Somers /* Got PROTO_IPCP from link */ 1154641684cdSBrian Somers if (bundle_Phase(bundle) == PHASE_NETWORK) 1155dd7e2610SBrian Somers fsm_Input(&ipcp->fsm, bp); 1156641684cdSBrian Somers else { 1157641684cdSBrian Somers if (bundle_Phase(bundle) < PHASE_NETWORK) 1158641684cdSBrian Somers log_Printf(LogIPCP, "%s: Error: Unexpected IPCP in phase %s (ignored)\n", 1159641684cdSBrian Somers ipcp->fsm.link->name, bundle_PhaseName(bundle)); 1160641684cdSBrian Somers mbuf_Free(bp); 1161641684cdSBrian Somers } 1162af57ed9fSAtsushi Murai } 11639c97abd8SBrian Somers 11649c97abd8SBrian Somers int 1165972a1bcfSBrian Somers ipcp_UseHisIPaddr(struct bundle *bundle, struct in_addr hisaddr) 1166972a1bcfSBrian Somers { 1167972a1bcfSBrian Somers struct ipcp *ipcp = &bundle->ncp.ipcp; 1168972a1bcfSBrian Somers 1169972a1bcfSBrian Somers memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 1170972a1bcfSBrian Somers iplist_reset(&ipcp->cfg.peer_list); 1171972a1bcfSBrian Somers ipcp->peer_ip = ipcp->cfg.peer_range.ipaddr = hisaddr; 1172972a1bcfSBrian Somers ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 1173972a1bcfSBrian Somers ipcp->cfg.peer_range.width = 32; 1174972a1bcfSBrian Somers 1175972a1bcfSBrian Somers if (ipcp_SetIPaddress(bundle, ipcp->cfg.my_range.ipaddr, hisaddr, 0) < 0) 1176972a1bcfSBrian Somers return 0; 1177972a1bcfSBrian Somers 1178972a1bcfSBrian Somers return 1; /* Ok */ 1179972a1bcfSBrian Somers } 1180972a1bcfSBrian Somers 1181972a1bcfSBrian Somers int 1182dd7e2610SBrian Somers ipcp_UseHisaddr(struct bundle *bundle, const char *hisaddr, int setaddr) 11839c97abd8SBrian Somers { 11845828db6dSBrian Somers struct ipcp *ipcp = &bundle->ncp.ipcp; 11855828db6dSBrian Somers 11867308ec68SBrian Somers /* Use `hisaddr' for the peers address (set iface if `setaddr') */ 11875828db6dSBrian Somers memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 11885828db6dSBrian Somers iplist_reset(&ipcp->cfg.peer_list); 11899c97abd8SBrian Somers if (strpbrk(hisaddr, ",-")) { 11905828db6dSBrian Somers iplist_setsrc(&ipcp->cfg.peer_list, hisaddr); 11915828db6dSBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 11925828db6dSBrian Somers iplist_setrandpos(&ipcp->cfg.peer_list); 119330c2f2ffSBrian Somers ipcp->peer_ip = ChooseHisAddr(bundle, ipcp->my_ip); 11945828db6dSBrian Somers if (ipcp->peer_ip.s_addr == INADDR_ANY) { 1195dd7e2610SBrian Somers log_Printf(LogWARN, "%s: None available !\n", ipcp->cfg.peer_list.src); 11969c97abd8SBrian Somers return(0); 11979c97abd8SBrian Somers } 11985828db6dSBrian Somers ipcp->cfg.peer_range.ipaddr.s_addr = ipcp->peer_ip.s_addr; 11995828db6dSBrian Somers ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 12005828db6dSBrian Somers ipcp->cfg.peer_range.width = 32; 12019c97abd8SBrian Somers } else { 1202dd7e2610SBrian Somers log_Printf(LogWARN, "%s: Invalid range !\n", hisaddr); 12039c97abd8SBrian Somers return 0; 12049c97abd8SBrian Somers } 1205972a1bcfSBrian Somers } else if (ParseAddr(ipcp, hisaddr, &ipcp->cfg.peer_range.ipaddr, 12065828db6dSBrian Somers &ipcp->cfg.peer_range.mask, 12075828db6dSBrian Somers &ipcp->cfg.peer_range.width) != 0) { 12085828db6dSBrian Somers ipcp->peer_ip.s_addr = ipcp->cfg.peer_range.ipaddr.s_addr; 12099c97abd8SBrian Somers 121030c2f2ffSBrian Somers if (setaddr && ipcp_SetIPaddress(bundle, ipcp->cfg.my_range.ipaddr, 12118fa6ebe4SBrian Somers ipcp->cfg.peer_range.ipaddr, 0) < 0) 12129c97abd8SBrian Somers return 0; 12139c97abd8SBrian Somers } else 12149c97abd8SBrian Somers return 0; 12159c97abd8SBrian Somers 12169c97abd8SBrian Somers return 1; 12179c97abd8SBrian Somers } 1218bc76350eSBrian Somers 1219bc76350eSBrian Somers struct in_addr 1220bc76350eSBrian Somers addr2mask(struct in_addr addr) 1221bc76350eSBrian Somers { 1222bc76350eSBrian Somers u_int32_t haddr = ntohl(addr.s_addr); 1223bc76350eSBrian Somers 1224bc76350eSBrian Somers haddr = IN_CLASSA(haddr) ? IN_CLASSA_NET : 1225bc76350eSBrian Somers IN_CLASSB(haddr) ? IN_CLASSB_NET : 1226bc76350eSBrian Somers IN_CLASSC_NET; 1227bc76350eSBrian Somers addr.s_addr = htonl(haddr); 1228bc76350eSBrian Somers 1229bc76350eSBrian Somers return addr; 1230bc76350eSBrian Somers } 1231