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 * 20aa857470SBrian Somers * $Id: ipcp.c,v 1.79 1999/06/02 15:59:01 brian Exp $ 21af57ed9fSAtsushi Murai * 22af57ed9fSAtsushi Murai * TODO: 235d9e6103SBrian Somers * o Support IPADDRS properly 245d9e6103SBrian Somers * o Validate the length in IpcpDecodeConfig 25af57ed9fSAtsushi Murai */ 2675240ed1SBrian Somers #include <sys/param.h> 275b4c5b00SBrian Somers #include <netinet/in_systm.h> 285b4c5b00SBrian Somers #include <netinet/in.h> 295b4c5b00SBrian Somers #include <netinet/ip.h> 305b4c5b00SBrian Somers #include <arpa/inet.h> 315b4c5b00SBrian Somers #include <sys/socket.h> 323afe5ccbSBrian Somers #include <net/route.h> 3375240ed1SBrian Somers #include <netdb.h> 341fa665f5SBrian Somers #include <sys/un.h> 3575240ed1SBrian Somers 36119386a3SBrian Somers #include <errno.h> 373edeb0c6SBrian Somers #include <fcntl.h> 383edeb0c6SBrian Somers #include <resolv.h> 39d1a3ea47SBrian Somers #include <stdlib.h> 4075240ed1SBrian Somers #include <string.h> 416140ba11SBrian Somers #include <termios.h> 4275240ed1SBrian Somers #include <unistd.h> 4375240ed1SBrian Somers 441595bacdSBrian Somers #ifndef NOALIAS 457884358fSBrian Somers #ifdef __FreeBSD__ 461595bacdSBrian Somers #include <alias.h> 477884358fSBrian Somers #else 487884358fSBrian Somers #include "alias.h" 491595bacdSBrian Somers #endif 501595bacdSBrian Somers #endif 515d9e6103SBrian Somers #include "layer.h" 529e8ec64bSBrian Somers #include "ua.h" 53c9e11a11SBrian Somers #include "defs.h" 54b6e82f33SBrian Somers #include "command.h" 5575240ed1SBrian Somers #include "mbuf.h" 5675240ed1SBrian Somers #include "log.h" 5775240ed1SBrian Somers #include "timer.h" 58af57ed9fSAtsushi Murai #include "fsm.h" 595d9e6103SBrian Somers #include "proto.h" 60af57ed9fSAtsushi Murai #include "lcp.h" 61bcc332bdSBrian Somers #include "iplist.h" 629a0b991fSBrian Somers #include "throughput.h" 631ae349f5Scvs2svn #include "slcompress.h" 645a72b6edSBrian Somers #include "lqr.h" 655a72b6edSBrian Somers #include "hdlc.h" 66eaa4df37SBrian Somers #include "ipcp.h" 679c97abd8SBrian Somers #include "filter.h" 682f786681SBrian Somers #include "descriptor.h" 691ae349f5Scvs2svn #include "vjcomp.h" 706140ba11SBrian Somers #include "async.h" 713b0f8d2eSBrian Somers #include "ccp.h" 728c07a7b2SBrian Somers #include "link.h" 7363b73463SBrian Somers #include "physical.h" 743b0f8d2eSBrian Somers #include "mp.h" 75972a1bcfSBrian Somers #ifndef NORADIUS 76972a1bcfSBrian Somers #include "radius.h" 77972a1bcfSBrian Somers #endif 783b0f8d2eSBrian Somers #include "bundle.h" 79455aabc3SBrian Somers #include "id.h" 80455aabc3SBrian Somers #include "arp.h" 81455aabc3SBrian Somers #include "systems.h" 8285b542cfSBrian Somers #include "prompt.h" 83610b185fSBrian Somers #include "route.h" 848fa6ebe4SBrian Somers #include "iface.h" 85af57ed9fSAtsushi Murai 86503a7782SBrian Somers #undef REJECTED 87503a7782SBrian Somers #define REJECTED(p, x) ((p)->peer_reject & (1<<(x))) 883edeb0c6SBrian Somers #define issep(ch) ((ch) == ' ' || (ch) == '\t') 893edeb0c6SBrian Somers #define isip(ch) (((ch) >= '0' && (ch) <= '9') || (ch) == '.') 90d8e55738SJordan K. Hubbard 9129e275ceSBrian Somers struct compreq { 9229e275ceSBrian Somers u_short proto; 9329e275ceSBrian Somers u_char slots; 9429e275ceSBrian Somers u_char compcid; 9529e275ceSBrian Somers }; 9675240ed1SBrian Somers 976f384573SBrian Somers static int IpcpLayerUp(struct fsm *); 981ae349f5Scvs2svn static void IpcpLayerDown(struct fsm *); 99927145beSBrian Somers static void IpcpLayerStart(struct fsm *); 100927145beSBrian Somers static void IpcpLayerFinish(struct fsm *); 101479508cfSBrian Somers static void IpcpInitRestartCounter(struct fsm *, int); 1027308ec68SBrian Somers static void IpcpSendConfigReq(struct fsm *); 1032267893fSBrian Somers static void IpcpSentTerminateReq(struct fsm *); 1042267893fSBrian Somers static void IpcpSendTerminateAck(struct fsm *, u_char); 10530c2f2ffSBrian Somers static void IpcpDecodeConfig(struct fsm *, u_char *, int, int, 10630c2f2ffSBrian Somers struct fsm_decode *); 107af57ed9fSAtsushi Murai 10883d1af55SBrian Somers static struct fsm_callbacks ipcp_Callbacks = { 109af57ed9fSAtsushi Murai IpcpLayerUp, 110af57ed9fSAtsushi Murai IpcpLayerDown, 111af57ed9fSAtsushi Murai IpcpLayerStart, 112af57ed9fSAtsushi Murai IpcpLayerFinish, 113af57ed9fSAtsushi Murai IpcpInitRestartCounter, 114af57ed9fSAtsushi Murai IpcpSendConfigReq, 1152267893fSBrian Somers IpcpSentTerminateReq, 116af57ed9fSAtsushi Murai IpcpSendTerminateAck, 117af57ed9fSAtsushi Murai IpcpDecodeConfig, 118dd7e2610SBrian Somers fsm_NullRecvResetReq, 119dd7e2610SBrian Somers fsm_NullRecvResetAck 120af57ed9fSAtsushi Murai }; 121af57ed9fSAtsushi Murai 122b6e82f33SBrian Somers static const char *cftypes[] = { 1239e836af5SBrian Somers /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */ 1249e836af5SBrian Somers "???", 1259e836af5SBrian Somers "IPADDRS", /* 1: IP-Addresses */ /* deprecated */ 1269e836af5SBrian Somers "COMPPROTO", /* 2: IP-Compression-Protocol */ 1279e836af5SBrian Somers "IPADDR", /* 3: IP-Address */ 128af57ed9fSAtsushi Murai }; 129af57ed9fSAtsushi Murai 13070ee81ffSBrian Somers #define NCFTYPES (sizeof cftypes/sizeof cftypes[0]) 1319e836af5SBrian Somers 132b6e82f33SBrian Somers static const char *cftypes128[] = { 1339e836af5SBrian Somers /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */ 1349e836af5SBrian Somers "???", 1359e836af5SBrian Somers "PRIDNS", /* 129: Primary DNS Server Address */ 1369e836af5SBrian Somers "PRINBNS", /* 130: Primary NBNS Server Address */ 1379e836af5SBrian Somers "SECDNS", /* 131: Secondary DNS Server Address */ 1389e836af5SBrian Somers "SECNBNS", /* 132: Secondary NBNS Server Address */ 1399e836af5SBrian Somers }; 1409e836af5SBrian Somers 14170ee81ffSBrian Somers #define NCFTYPES128 (sizeof cftypes128/sizeof cftypes128[0]) 1429e836af5SBrian Somers 1439a0b991fSBrian Somers void 1445828db6dSBrian Somers ipcp_AddInOctets(struct ipcp *ipcp, int n) 145af57ed9fSAtsushi Murai { 1465828db6dSBrian Somers throughput_addin(&ipcp->throughput, n); 147af57ed9fSAtsushi Murai } 148af57ed9fSAtsushi Murai 1499a0b991fSBrian Somers void 1505828db6dSBrian Somers ipcp_AddOutOctets(struct ipcp *ipcp, int n) 151af57ed9fSAtsushi Murai { 1525828db6dSBrian Somers throughput_addout(&ipcp->throughput, n); 1531ae349f5Scvs2svn } 1541ae349f5Scvs2svn 1553edeb0c6SBrian Somers static void 1563edeb0c6SBrian Somers getdns(struct ipcp *ipcp, struct in_addr addr[2]) 1573edeb0c6SBrian Somers { 1583edeb0c6SBrian Somers FILE *fp; 1593edeb0c6SBrian Somers 1603edeb0c6SBrian Somers addr[0].s_addr = addr[1].s_addr = INADDR_ANY; 1613edeb0c6SBrian Somers if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { 1623edeb0c6SBrian Somers char buf[LINE_LEN], *cp, *end; 1633edeb0c6SBrian Somers int n; 1643edeb0c6SBrian Somers 1653edeb0c6SBrian Somers n = 0; 1663edeb0c6SBrian Somers buf[sizeof buf - 1] = '\0'; 1673edeb0c6SBrian Somers while (fgets(buf, sizeof buf - 1, fp)) { 1683edeb0c6SBrian Somers if (!strncmp(buf, "nameserver", 10) && issep(buf[10])) { 1693edeb0c6SBrian Somers for (cp = buf + 11; issep(*cp); cp++) 1703edeb0c6SBrian Somers ; 1713edeb0c6SBrian Somers for (end = cp; isip(*end); end++) 1723edeb0c6SBrian Somers ; 1733edeb0c6SBrian Somers *end = '\0'; 1743edeb0c6SBrian Somers if (inet_aton(cp, addr+n) && ++n == 2) 1753edeb0c6SBrian Somers break; 1763edeb0c6SBrian Somers } 1773edeb0c6SBrian Somers } 1783edeb0c6SBrian Somers if (n == 1) 1793edeb0c6SBrian Somers addr[1] = addr[0]; 1803edeb0c6SBrian Somers fclose(fp); 1813edeb0c6SBrian Somers } 1823edeb0c6SBrian Somers } 1833edeb0c6SBrian Somers 1843edeb0c6SBrian Somers static int 1853edeb0c6SBrian Somers setdns(struct ipcp *ipcp, struct in_addr addr[2]) 1863edeb0c6SBrian Somers { 1873edeb0c6SBrian Somers FILE *fp; 1883edeb0c6SBrian Somers char wbuf[LINE_LEN + 54]; 1893edeb0c6SBrian Somers int wlen; 1903edeb0c6SBrian Somers 1913edeb0c6SBrian Somers if (addr[0].s_addr == INADDR_ANY || addr[1].s_addr == INADDR_ANY) { 1923edeb0c6SBrian Somers struct in_addr old[2]; 1933edeb0c6SBrian Somers 1943edeb0c6SBrian Somers getdns(ipcp, old); 1953edeb0c6SBrian Somers if (addr[0].s_addr == INADDR_ANY) 1963edeb0c6SBrian Somers addr[0] = old[0]; 1973edeb0c6SBrian Somers if (addr[1].s_addr == INADDR_ANY) 1983edeb0c6SBrian Somers addr[1] = old[1]; 1993edeb0c6SBrian Somers } 2003edeb0c6SBrian Somers 2013edeb0c6SBrian Somers if (addr[0].s_addr == INADDR_ANY && addr[1].s_addr == INADDR_ANY) { 202dd7e2610SBrian Somers log_Printf(LogWARN, "%s not modified: All nameservers NAKd\n", 2033edeb0c6SBrian Somers _PATH_RESCONF); 2043edeb0c6SBrian Somers return 0; 2053edeb0c6SBrian Somers } 2063edeb0c6SBrian Somers 2073edeb0c6SBrian Somers wlen = 0; 2083edeb0c6SBrian Somers if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { 2093edeb0c6SBrian Somers char buf[LINE_LEN]; 2103edeb0c6SBrian Somers int len; 2113edeb0c6SBrian Somers 2123edeb0c6SBrian Somers buf[sizeof buf - 1] = '\0'; 2133edeb0c6SBrian Somers while (fgets(buf, sizeof buf - 1, fp)) { 2143edeb0c6SBrian Somers if (strncmp(buf, "nameserver", 10) || !issep(buf[10])) { 2153edeb0c6SBrian Somers len = strlen(buf); 2163edeb0c6SBrian Somers if (len > sizeof wbuf - wlen) { 217dd7e2610SBrian Somers log_Printf(LogWARN, "%s: Can only cope with max file size %d\n", 2183edeb0c6SBrian Somers _PATH_RESCONF, LINE_LEN); 2193edeb0c6SBrian Somers fclose(fp); 2203edeb0c6SBrian Somers return 0; 2213edeb0c6SBrian Somers } 2223edeb0c6SBrian Somers memcpy(wbuf + wlen, buf, len); 2233edeb0c6SBrian Somers wlen += len; 2243edeb0c6SBrian Somers } 2253edeb0c6SBrian Somers } 2263edeb0c6SBrian Somers fclose(fp); 2273edeb0c6SBrian Somers } 2283edeb0c6SBrian Somers 2293edeb0c6SBrian Somers if (addr[0].s_addr != INADDR_ANY) { 2303edeb0c6SBrian Somers snprintf(wbuf + wlen, sizeof wbuf - wlen, "nameserver %s\n", 2313edeb0c6SBrian Somers inet_ntoa(addr[0])); 232dd7e2610SBrian Somers log_Printf(LogIPCP, "Primary nameserver set to %s", wbuf + wlen + 11); 2333edeb0c6SBrian Somers wlen += strlen(wbuf + wlen); 2343edeb0c6SBrian Somers } 2353edeb0c6SBrian Somers 2363edeb0c6SBrian Somers if (addr[1].s_addr != INADDR_ANY && addr[1].s_addr != addr[0].s_addr) { 2373edeb0c6SBrian Somers snprintf(wbuf + wlen, sizeof wbuf - wlen, "nameserver %s\n", 2383edeb0c6SBrian Somers inet_ntoa(addr[1])); 239dd7e2610SBrian Somers log_Printf(LogIPCP, "Secondary nameserver set to %s", wbuf + wlen + 11); 2403edeb0c6SBrian Somers wlen += strlen(wbuf + wlen); 2413edeb0c6SBrian Somers } 2423edeb0c6SBrian Somers 2433edeb0c6SBrian Somers if (wlen) { 2443edeb0c6SBrian Somers int fd; 2453edeb0c6SBrian Somers 2463edeb0c6SBrian Somers if ((fd = ID0open(_PATH_RESCONF, O_WRONLY|O_CREAT, 0644)) != -1) { 2473edeb0c6SBrian Somers if (write(fd, wbuf, wlen) != wlen) { 248dd7e2610SBrian Somers log_Printf(LogERROR, "setdns: write(): %s\n", strerror(errno)); 2493edeb0c6SBrian Somers close(fd); 2503edeb0c6SBrian Somers return 0; 2513edeb0c6SBrian Somers } 2523edeb0c6SBrian Somers if (ftruncate(fd, wlen) == -1) { 253dd7e2610SBrian Somers log_Printf(LogERROR, "setdns: truncate(): %s\n", strerror(errno)); 2543edeb0c6SBrian Somers close(fd); 2553edeb0c6SBrian Somers return 0; 2563edeb0c6SBrian Somers } 2573edeb0c6SBrian Somers close(fd); 2583edeb0c6SBrian Somers } else { 259dd7e2610SBrian Somers log_Printf(LogERROR, "setdns: open(): %s\n", strerror(errno)); 2603edeb0c6SBrian Somers return 0; 2613edeb0c6SBrian Somers } 2623edeb0c6SBrian Somers } 2633edeb0c6SBrian Somers 2643edeb0c6SBrian Somers return 1; 265af57ed9fSAtsushi Murai } 266af57ed9fSAtsushi Murai 267274e766cSBrian Somers int 268dd7e2610SBrian Somers ipcp_Show(struct cmdargs const *arg) 269af57ed9fSAtsushi Murai { 270610b185fSBrian Somers struct ipcp *ipcp = &arg->bundle->ncp.ipcp; 271af57ed9fSAtsushi Murai 272610b185fSBrian Somers prompt_Printf(arg->prompt, "%s [%s]\n", ipcp->fsm.name, 273610b185fSBrian Somers State2Nam(ipcp->fsm.state)); 274610b185fSBrian Somers if (ipcp->fsm.state == ST_OPENED) { 275b6217683SBrian Somers prompt_Printf(arg->prompt, " His side: %s, %s\n", 276610b185fSBrian Somers inet_ntoa(ipcp->peer_ip), vj2asc(ipcp->peer_compproto)); 277b6217683SBrian Somers prompt_Printf(arg->prompt, " My side: %s, %s\n", 278610b185fSBrian Somers inet_ntoa(ipcp->my_ip), vj2asc(ipcp->my_compproto)); 279d1a3ea47SBrian Somers } 2805b4c5b00SBrian Somers 281610b185fSBrian Somers if (ipcp->route) { 282610b185fSBrian Somers prompt_Printf(arg->prompt, "\n"); 283972a1bcfSBrian Somers route_ShowSticky(arg->prompt, ipcp->route, "Sticky routes", 1); 2841ae349f5Scvs2svn } 285927145beSBrian Somers 286b6217683SBrian Somers prompt_Printf(arg->prompt, "\nDefaults:\n"); 287479508cfSBrian Somers prompt_Printf(arg->prompt, " FSM retry = %us, max %u Config" 288479508cfSBrian Somers " REQ%s, %u Term REQ%s\n", ipcp->cfg.fsm.timeout, 289479508cfSBrian Somers ipcp->cfg.fsm.maxreq, ipcp->cfg.fsm.maxreq == 1 ? "" : "s", 290479508cfSBrian Somers ipcp->cfg.fsm.maxtrm, ipcp->cfg.fsm.maxtrm == 1 ? "" : "s"); 29150abd4c8SBrian Somers prompt_Printf(arg->prompt, " My Address: %s/%d", 292610b185fSBrian Somers inet_ntoa(ipcp->cfg.my_range.ipaddr), ipcp->cfg.my_range.width); 293bc76350eSBrian Somers prompt_Printf(arg->prompt, ", netmask %s\n", inet_ntoa(ipcp->cfg.netmask)); 294610b185fSBrian Somers if (ipcp->cfg.HaveTriggerAddress) 295bc76350eSBrian Somers prompt_Printf(arg->prompt, " Trigger address: %s\n", 296610b185fSBrian Somers inet_ntoa(ipcp->cfg.TriggerAddress)); 297bc76350eSBrian Somers 298bc76350eSBrian Somers prompt_Printf(arg->prompt, " VJ compression: %s (%d slots %s slot " 299610b185fSBrian Somers "compression)\n", command_ShowNegval(ipcp->cfg.vj.neg), 300610b185fSBrian Somers ipcp->cfg.vj.slots, ipcp->cfg.vj.slotcomp ? "with" : "without"); 30150abd4c8SBrian Somers 302610b185fSBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) 303b6217683SBrian Somers prompt_Printf(arg->prompt, " His Address: %s\n", 304610b185fSBrian Somers ipcp->cfg.peer_list.src); 3051ae349f5Scvs2svn else 306b6217683SBrian Somers prompt_Printf(arg->prompt, " His Address: %s/%d\n", 307610b185fSBrian Somers inet_ntoa(ipcp->cfg.peer_range.ipaddr), 308610b185fSBrian Somers ipcp->cfg.peer_range.width); 30950abd4c8SBrian Somers 3103edeb0c6SBrian Somers prompt_Printf(arg->prompt, " DNS: %s, ", 311610b185fSBrian Somers inet_ntoa(ipcp->cfg.ns.dns[0])); 312610b185fSBrian Somers prompt_Printf(arg->prompt, "%s, %s\n", inet_ntoa(ipcp->cfg.ns.dns[1]), 313610b185fSBrian Somers command_ShowNegval(ipcp->cfg.ns.dns_neg)); 3143edeb0c6SBrian Somers prompt_Printf(arg->prompt, " NetBIOS NS: %s, ", 315610b185fSBrian Somers inet_ntoa(ipcp->cfg.ns.nbns[0])); 316610b185fSBrian Somers prompt_Printf(arg->prompt, "%s\n", inet_ntoa(ipcp->cfg.ns.nbns[1])); 3171342caedSBrian Somers 318b6217683SBrian Somers prompt_Printf(arg->prompt, "\n"); 319610b185fSBrian Somers throughput_disp(&ipcp->throughput, arg->prompt); 3209a0b991fSBrian Somers 321927145beSBrian Somers return 0; 322af57ed9fSAtsushi Murai } 323af57ed9fSAtsushi Murai 324d1a3ea47SBrian Somers int 325dd7e2610SBrian Somers ipcp_vjset(struct cmdargs const *arg) 326d1a3ea47SBrian Somers { 32725092092SBrian Somers if (arg->argc != arg->argn+2) 328d1a3ea47SBrian Somers return -1; 32925092092SBrian Somers if (!strcasecmp(arg->argv[arg->argn], "slots")) { 330d1a3ea47SBrian Somers int slots; 331d1a3ea47SBrian Somers 33225092092SBrian Somers slots = atoi(arg->argv[arg->argn+1]); 333d1a3ea47SBrian Somers if (slots < 4 || slots > 16) 334d1a3ea47SBrian Somers return 1; 3351342caedSBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slots = slots; 336d1a3ea47SBrian Somers return 0; 33725092092SBrian Somers } else if (!strcasecmp(arg->argv[arg->argn], "slotcomp")) { 33825092092SBrian Somers if (!strcasecmp(arg->argv[arg->argn+1], "on")) 3391342caedSBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 1; 34025092092SBrian Somers else if (!strcasecmp(arg->argv[arg->argn+1], "off")) 3411342caedSBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 0; 342d1a3ea47SBrian Somers else 343d1a3ea47SBrian Somers return 2; 344d1a3ea47SBrian Somers return 0; 345d1a3ea47SBrian Somers } 346d1a3ea47SBrian Somers return -1; 347d1a3ea47SBrian Somers } 348d1a3ea47SBrian Somers 3491ae349f5Scvs2svn void 3506d666775SBrian Somers ipcp_Init(struct ipcp *ipcp, struct bundle *bundle, struct link *l, 3516d666775SBrian Somers const struct fsm_parent *parent) 352d1a3ea47SBrian Somers { 353503a7782SBrian Somers struct hostent *hp; 354503a7782SBrian Somers char name[MAXHOSTNAMELEN]; 3553b0f8d2eSBrian Somers static const char *timer_names[] = 3563b0f8d2eSBrian Somers {"IPCP restart", "IPCP openmode", "IPCP stopped"}; 35729e275ceSBrian Somers 358479508cfSBrian Somers fsm_Init(&ipcp->fsm, "IPCP", PROTO_IPCP, 1, IPCP_MAXCODE, LogIPCP, 3593b0f8d2eSBrian Somers bundle, l, parent, &ipcp_Callbacks, timer_names); 360503a7782SBrian Somers 361610b185fSBrian Somers ipcp->route = NULL; 3621342caedSBrian Somers ipcp->cfg.vj.slots = DEF_VJ_STATES; 3631342caedSBrian Somers ipcp->cfg.vj.slotcomp = 1; 364503a7782SBrian Somers memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range); 365503a7782SBrian Somers if (gethostname(name, sizeof name) == 0) { 366503a7782SBrian Somers hp = gethostbyname(name); 3678fa6ebe4SBrian Somers if (hp && hp->h_addrtype == AF_INET) 368503a7782SBrian Somers memcpy(&ipcp->cfg.my_range.ipaddr.s_addr, hp->h_addr, hp->h_length); 369503a7782SBrian Somers } 37030c2f2ffSBrian Somers ipcp->cfg.netmask.s_addr = INADDR_ANY; 371503a7782SBrian Somers memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 372503a7782SBrian Somers iplist_setsrc(&ipcp->cfg.peer_list, ""); 373503a7782SBrian Somers ipcp->cfg.HaveTriggerAddress = 0; 374503a7782SBrian Somers 3753edeb0c6SBrian Somers ipcp->cfg.ns.dns[0].s_addr = INADDR_ANY; 3763edeb0c6SBrian Somers ipcp->cfg.ns.dns[1].s_addr = INADDR_ANY; 3773edeb0c6SBrian Somers ipcp->cfg.ns.dns_neg = 0; 3783edeb0c6SBrian Somers ipcp->cfg.ns.nbns[0].s_addr = INADDR_ANY; 3793edeb0c6SBrian Somers ipcp->cfg.ns.nbns[1].s_addr = INADDR_ANY; 380cd9647a1SBrian Somers 381479508cfSBrian Somers ipcp->cfg.fsm.timeout = DEF_FSMRETRY; 382479508cfSBrian Somers ipcp->cfg.fsm.maxreq = DEF_FSMTRIES; 383479508cfSBrian Somers ipcp->cfg.fsm.maxtrm = DEF_FSMTRIES; 3841342caedSBrian Somers ipcp->cfg.vj.neg = NEG_ENABLED|NEG_ACCEPTED; 385503a7782SBrian Somers 386eaa4df37SBrian Somers memset(&ipcp->vj, '\0', sizeof ipcp->vj); 387eaa4df37SBrian Somers 388fdf61171SBrian Somers throughput_init(&ipcp->throughput); 3895a72b6edSBrian Somers memset(ipcp->Queue, '\0', sizeof ipcp->Queue); 390972a1bcfSBrian Somers ipcp_Setup(ipcp, INADDR_NONE); 391d1a3ea47SBrian Somers } 392d1a3ea47SBrian Somers 393af57ed9fSAtsushi Murai void 394ce828a6eSBrian Somers ipcp_SetLink(struct ipcp *ipcp, struct link *l) 395af57ed9fSAtsushi Murai { 396ce828a6eSBrian Somers ipcp->fsm.link = l; 397af57ed9fSAtsushi Murai } 398549d663dSAtsushi Murai 399ce828a6eSBrian Somers void 400972a1bcfSBrian Somers ipcp_Setup(struct ipcp *ipcp, u_int32_t mask) 401503a7782SBrian Somers { 4028fa6ebe4SBrian Somers struct iface *iface = ipcp->fsm.bundle->iface; 4038fa6ebe4SBrian Somers int pos, n; 404503a7782SBrian Somers 405503a7782SBrian Somers ipcp->fsm.open_mode = 0; 406972a1bcfSBrian Somers ipcp->ifmask.s_addr = mask == INADDR_NONE ? ipcp->cfg.netmask.s_addr : mask; 407503a7782SBrian Somers 408503a7782SBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 4098fa6ebe4SBrian Somers /* Try to give the peer a previously configured IP address */ 4108fa6ebe4SBrian Somers for (n = 0; n < iface->in_addrs; n++) { 4118fa6ebe4SBrian Somers pos = iplist_ip2pos(&ipcp->cfg.peer_list, iface->in_addr[n].brd); 4128fa6ebe4SBrian Somers if (pos != -1) { 4138fa6ebe4SBrian Somers ipcp->cfg.peer_range.ipaddr = 4148fa6ebe4SBrian Somers iplist_setcurpos(&ipcp->cfg.peer_list, pos); 4158fa6ebe4SBrian Somers break; 4168fa6ebe4SBrian Somers } 4178fa6ebe4SBrian Somers } 4188fa6ebe4SBrian Somers if (n == iface->in_addrs) 4198fa6ebe4SBrian Somers /* Ok, so none of 'em fit.... pick a random one */ 420503a7782SBrian Somers ipcp->cfg.peer_range.ipaddr = iplist_setrandpos(&ipcp->cfg.peer_list); 4218fa6ebe4SBrian Somers 422503a7782SBrian Somers ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 423503a7782SBrian Somers ipcp->cfg.peer_range.width = 32; 424503a7782SBrian Somers } 425503a7782SBrian Somers 426503a7782SBrian Somers ipcp->heis1172 = 0; 427503a7782SBrian Somers 428503a7782SBrian Somers ipcp->peer_ip = ipcp->cfg.peer_range.ipaddr; 429503a7782SBrian Somers ipcp->peer_compproto = 0; 4301ae349f5Scvs2svn 4318390b576SBrian Somers if (ipcp->cfg.HaveTriggerAddress) { 432549d663dSAtsushi Murai /* 4335b4c5b00SBrian Somers * Some implementations of PPP require that we send a 4345b4c5b00SBrian Somers * *special* value as our address, even though the rfc specifies 4355b4c5b00SBrian Somers * full negotiation (e.g. "0.0.0.0" or Not "0.0.0.0"). 436549d663dSAtsushi Murai */ 437503a7782SBrian Somers ipcp->my_ip = ipcp->cfg.TriggerAddress; 438dd7e2610SBrian Somers log_Printf(LogIPCP, "Using trigger address %s\n", 439503a7782SBrian Somers inet_ntoa(ipcp->cfg.TriggerAddress)); 4408fa6ebe4SBrian Somers } else { 4418390b576SBrian Somers /* 4428fa6ebe4SBrian Somers * Otherwise, if we've used an IP number before and it's still within 4438fa6ebe4SBrian Somers * the network specified on the ``set ifaddr'' line, we really 4448fa6ebe4SBrian Somers * want to keep that IP number so that we can keep any existing 4458fa6ebe4SBrian Somers * connections that are bound to that IP (assuming we're not 4468fa6ebe4SBrian Somers * ``iface-alias''ing). 4478390b576SBrian Somers */ 4488fa6ebe4SBrian Somers for (n = 0; n < iface->in_addrs; n++) 4498fa6ebe4SBrian Somers if ((iface->in_addr[n].ifa.s_addr & ipcp->cfg.my_range.mask.s_addr) == 4508fa6ebe4SBrian Somers (ipcp->cfg.my_range.ipaddr.s_addr & ipcp->cfg.my_range.mask.s_addr)) { 4518fa6ebe4SBrian Somers ipcp->my_ip = iface->in_addr[n].ifa; 4528fa6ebe4SBrian Somers break; 4538fa6ebe4SBrian Somers } 4548fa6ebe4SBrian Somers if (n == iface->in_addrs) 455503a7782SBrian Somers ipcp->my_ip = ipcp->cfg.my_range.ipaddr; 4568fa6ebe4SBrian Somers } 45729e275ceSBrian Somers 458972a1bcfSBrian Somers if (IsEnabled(ipcp->cfg.vj.neg) 459972a1bcfSBrian Somers #ifndef NORADIUS 460972a1bcfSBrian Somers || (ipcp->fsm.bundle->radius.valid && ipcp->fsm.bundle->radius.vj) 461972a1bcfSBrian Somers #endif 462972a1bcfSBrian Somers ) 463503a7782SBrian Somers ipcp->my_compproto = (PROTO_VJCOMP << 16) + 4641342caedSBrian Somers ((ipcp->cfg.vj.slots - 1) << 8) + 4651342caedSBrian Somers ipcp->cfg.vj.slotcomp; 4661ae349f5Scvs2svn else 467503a7782SBrian Somers ipcp->my_compproto = 0; 4681342caedSBrian Somers sl_compress_init(&ipcp->vj.cslc, ipcp->cfg.vj.slots - 1); 46929e275ceSBrian Somers 470503a7782SBrian Somers ipcp->peer_reject = 0; 471503a7782SBrian Somers ipcp->my_reject = 0; 4721ae349f5Scvs2svn } 4731ae349f5Scvs2svn 474455aabc3SBrian Somers static int 4753afe5ccbSBrian Somers ipcp_doproxyall(struct bundle *bundle, 4763afe5ccbSBrian Somers int (*proxyfun)(struct bundle *, struct in_addr, int), int s) 4773afe5ccbSBrian Somers { 4783afe5ccbSBrian Somers int n, ret; 4793afe5ccbSBrian Somers struct sticky_route *rp; 4803afe5ccbSBrian Somers struct in_addr addr; 4813afe5ccbSBrian Somers struct ipcp *ipcp; 4823afe5ccbSBrian Somers 4833afe5ccbSBrian Somers ipcp = &bundle->ncp.ipcp; 4843afe5ccbSBrian Somers for (rp = ipcp->route; rp != NULL; rp = rp->next) { 485bc76350eSBrian Somers if (rp->mask.s_addr == INADDR_BROADCAST) 4863afe5ccbSBrian Somers continue; 487bc76350eSBrian Somers n = ntohl(INADDR_BROADCAST) - ntohl(rp->mask.s_addr) - 1; 4883afe5ccbSBrian Somers if (n > 0 && n <= 254 && rp->dst.s_addr != INADDR_ANY) { 4893afe5ccbSBrian Somers addr = rp->dst; 4903afe5ccbSBrian Somers while (n--) { 4913afe5ccbSBrian Somers addr.s_addr = htonl(ntohl(addr.s_addr) + 1); 4923afe5ccbSBrian Somers log_Printf(LogDEBUG, "ipcp_doproxyall: %s\n", inet_ntoa(addr)); 4933afe5ccbSBrian Somers ret = (*proxyfun)(bundle, addr, s); 4943afe5ccbSBrian Somers if (!ret) 4953afe5ccbSBrian Somers return ret; 4963afe5ccbSBrian Somers } 4973afe5ccbSBrian Somers } 4983afe5ccbSBrian Somers } 4993afe5ccbSBrian Somers 5003afe5ccbSBrian Somers return 0; 5013afe5ccbSBrian Somers } 5023afe5ccbSBrian Somers 5033afe5ccbSBrian Somers static int 50430c2f2ffSBrian Somers ipcp_SetIPaddress(struct bundle *bundle, struct in_addr myaddr, 50530c2f2ffSBrian Somers struct in_addr hisaddr, int silent) 506455aabc3SBrian Somers { 5073afe5ccbSBrian Somers static struct in_addr none = { INADDR_ANY }; 5088fa6ebe4SBrian Somers struct in_addr mask, oaddr; 509455aabc3SBrian Somers 510bc76350eSBrian Somers mask = addr2mask(myaddr); 511455aabc3SBrian Somers 512972a1bcfSBrian Somers if (bundle->ncp.ipcp.ifmask.s_addr != INADDR_ANY && 513bc76350eSBrian Somers (bundle->ncp.ipcp.ifmask.s_addr & mask.s_addr) == mask.s_addr) 514bc76350eSBrian Somers mask.s_addr = bundle->ncp.ipcp.ifmask.s_addr; 515455aabc3SBrian Somers 5168fa6ebe4SBrian Somers oaddr.s_addr = bundle->iface->in_addrs ? 5178fa6ebe4SBrian Somers bundle->iface->in_addr[0].ifa.s_addr : INADDR_ANY; 5188fa6ebe4SBrian Somers if (!iface_inAdd(bundle->iface, myaddr, mask, hisaddr, 5198fa6ebe4SBrian Somers IFACE_ADD_FIRST|IFACE_FORCE_ADD)) 5208fa6ebe4SBrian Somers return -1; 521455aabc3SBrian Somers 5228fa6ebe4SBrian Somers if (!Enabled(bundle, OPT_IFACEALIAS) && bundle->iface->in_addrs > 1 5238fa6ebe4SBrian Somers && myaddr.s_addr != oaddr.s_addr) 5248fa6ebe4SBrian Somers /* Nuke the old one */ 5258fa6ebe4SBrian Somers iface_inDelete(bundle->iface, oaddr); 526455aabc3SBrian Somers 5273afe5ccbSBrian Somers if (bundle->ncp.ipcp.cfg.sendpipe > 0 || bundle->ncp.ipcp.cfg.recvpipe > 0) 5283afe5ccbSBrian Somers bundle_SetRoute(bundle, RTM_CHANGE, hisaddr, myaddr, none, 0, 0); 5293afe5ccbSBrian Somers 530610b185fSBrian Somers if (Enabled(bundle, OPT_SROUTES)) 531610b185fSBrian Somers route_Change(bundle, bundle->ncp.ipcp.route, myaddr, hisaddr); 532610b185fSBrian Somers 533972a1bcfSBrian Somers #ifndef NORADIUS 534972a1bcfSBrian Somers if (bundle->radius.valid) 535972a1bcfSBrian Somers route_Change(bundle, bundle->radius.routes, myaddr, hisaddr); 536972a1bcfSBrian Somers #endif 537972a1bcfSBrian Somers 5383afe5ccbSBrian Somers if (Enabled(bundle, OPT_PROXY) || Enabled(bundle, OPT_PROXYALL)) { 5398fa6ebe4SBrian Somers int s = ID0socket(AF_INET, SOCK_DGRAM, 0); 5408fa6ebe4SBrian Somers if (s < 0) 5418fa6ebe4SBrian Somers log_Printf(LogERROR, "ipcp_SetIPaddress: socket(): %s\n", 5428fa6ebe4SBrian Somers strerror(errno)); 5438fa6ebe4SBrian Somers else { 5443afe5ccbSBrian Somers if (Enabled(bundle, OPT_PROXYALL)) 5453afe5ccbSBrian Somers ipcp_doproxyall(bundle, arp_SetProxy, s); 5463afe5ccbSBrian Somers else if (Enabled(bundle, OPT_PROXY)) 5478fa6ebe4SBrian Somers arp_SetProxy(bundle, hisaddr, s); 548455aabc3SBrian Somers close(s); 5498fa6ebe4SBrian Somers } 5508fa6ebe4SBrian Somers } 5518fa6ebe4SBrian Somers 5528fa6ebe4SBrian Somers return 0; 553455aabc3SBrian Somers } 554455aabc3SBrian Somers 555455aabc3SBrian Somers static struct in_addr 5568fa6ebe4SBrian Somers ChooseHisAddr(struct bundle *bundle, struct in_addr gw) 557455aabc3SBrian Somers { 558455aabc3SBrian Somers struct in_addr try; 5593a2e4f62SBrian Somers u_long f; 560455aabc3SBrian Somers 5615828db6dSBrian Somers for (f = 0; f < bundle->ncp.ipcp.cfg.peer_list.nItems; f++) { 5625828db6dSBrian Somers try = iplist_next(&bundle->ncp.ipcp.cfg.peer_list); 5633a2e4f62SBrian Somers log_Printf(LogDEBUG, "ChooseHisAddr: Check item %ld (%s)\n", 564455aabc3SBrian Somers f, inet_ntoa(try)); 56530c2f2ffSBrian Somers if (ipcp_SetIPaddress(bundle, gw, try, 1) == 0) { 566dd7e2610SBrian Somers log_Printf(LogIPCP, "Selected IP address %s\n", inet_ntoa(try)); 567455aabc3SBrian Somers break; 568455aabc3SBrian Somers } 569455aabc3SBrian Somers } 570455aabc3SBrian Somers 5715828db6dSBrian Somers if (f == bundle->ncp.ipcp.cfg.peer_list.nItems) { 572dd7e2610SBrian Somers log_Printf(LogDEBUG, "ChooseHisAddr: All addresses in use !\n"); 573455aabc3SBrian Somers try.s_addr = INADDR_ANY; 574455aabc3SBrian Somers } 575455aabc3SBrian Somers 576455aabc3SBrian Somers return try; 577af57ed9fSAtsushi Murai } 578af57ed9fSAtsushi Murai 579af57ed9fSAtsushi Murai static void 580479508cfSBrian Somers IpcpInitRestartCounter(struct fsm *fp, int what) 581af57ed9fSAtsushi Murai { 5827308ec68SBrian Somers /* Set fsm timer load */ 583cd9647a1SBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 584cd9647a1SBrian Somers 585479508cfSBrian Somers fp->FsmTimer.load = ipcp->cfg.fsm.timeout * SECTICKS; 586479508cfSBrian Somers switch (what) { 587479508cfSBrian Somers case FSM_REQ_TIMER: 588479508cfSBrian Somers fp->restart = ipcp->cfg.fsm.maxreq; 589479508cfSBrian Somers break; 590479508cfSBrian Somers case FSM_TRM_TIMER: 591479508cfSBrian Somers fp->restart = ipcp->cfg.fsm.maxtrm; 592479508cfSBrian Somers break; 593479508cfSBrian Somers default: 594479508cfSBrian Somers fp->restart = 1; 595479508cfSBrian Somers break; 596479508cfSBrian Somers } 597af57ed9fSAtsushi Murai } 598af57ed9fSAtsushi Murai 599af57ed9fSAtsushi Murai static void 600944f7098SBrian Somers IpcpSendConfigReq(struct fsm *fp) 601af57ed9fSAtsushi Murai { 6027308ec68SBrian Somers /* Send config REQ please */ 6038c07a7b2SBrian Somers struct physical *p = link2physical(fp->link); 604aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 6053edeb0c6SBrian Somers u_char buff[24]; 6062267893fSBrian Somers struct lcp_opt *o; 607af57ed9fSAtsushi Murai 6082267893fSBrian Somers o = (struct lcp_opt *)buff; 60930c2f2ffSBrian Somers 610dd7e2610SBrian Somers if ((p && !physical_IsSync(p)) || !REJECTED(ipcp, TY_IPADDR)) { 6119e8ec64bSBrian Somers memcpy(o->data, &ipcp->my_ip.s_addr, 4); 6122267893fSBrian Somers INC_LCP_OPT(TY_IPADDR, 6, o); 6130053cc58SBrian Somers } 6140053cc58SBrian Somers 615e43ebac1SBrian Somers if (ipcp->my_compproto && !REJECTED(ipcp, TY_COMPPROTO)) { 61683d1af55SBrian Somers if (ipcp->heis1172) { 6179e8ec64bSBrian Somers u_int16_t proto = PROTO_VJCOMP; 6189e8ec64bSBrian Somers 6199e8ec64bSBrian Somers ua_htons(&proto, o->data); 6202267893fSBrian Somers INC_LCP_OPT(TY_COMPPROTO, 4, o); 6210053cc58SBrian Somers } else { 6227686a200SBrian Somers struct compreq req; 6237686a200SBrian Somers 6247686a200SBrian Somers req.proto = htons(ipcp->my_compproto >> 16); 6257686a200SBrian Somers req.slots = (ipcp->my_compproto >> 8) & 255; 6267686a200SBrian Somers req.compcid = ipcp->my_compproto & 1; 6277686a200SBrian Somers memcpy(o->data, &req, 4); 6282267893fSBrian Somers INC_LCP_OPT(TY_COMPPROTO, 6, o); 6290053cc58SBrian Somers } 630af57ed9fSAtsushi Murai } 6312267893fSBrian Somers 6323edeb0c6SBrian Somers if (IsEnabled(ipcp->cfg.ns.dns_neg) && 6333edeb0c6SBrian Somers !REJECTED(ipcp, TY_PRIMARY_DNS - TY_ADJUST_NS) && 6343edeb0c6SBrian Somers !REJECTED(ipcp, TY_SECONDARY_DNS - TY_ADJUST_NS)) { 6353edeb0c6SBrian Somers struct in_addr dns[2]; 6363edeb0c6SBrian Somers getdns(ipcp, dns); 6379e8ec64bSBrian Somers memcpy(o->data, &dns[0].s_addr, 4); 6383edeb0c6SBrian Somers INC_LCP_OPT(TY_PRIMARY_DNS, 6, o); 6399e8ec64bSBrian Somers memcpy(o->data, &dns[1].s_addr, 4); 6403edeb0c6SBrian Somers INC_LCP_OPT(TY_SECONDARY_DNS, 6, o); 6413edeb0c6SBrian Somers } 6423edeb0c6SBrian Somers 643411675baSBrian Somers fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff, 644411675baSBrian Somers MB_IPCPOUT); 645af57ed9fSAtsushi Murai } 646af57ed9fSAtsushi Murai 647af57ed9fSAtsushi Murai static void 6482267893fSBrian Somers IpcpSentTerminateReq(struct fsm *fp) 649af57ed9fSAtsushi Murai { 6507308ec68SBrian Somers /* Term REQ just sent by FSM */ 651af57ed9fSAtsushi Murai } 652af57ed9fSAtsushi Murai 653af57ed9fSAtsushi Murai static void 6542267893fSBrian Somers IpcpSendTerminateAck(struct fsm *fp, u_char id) 655af57ed9fSAtsushi Murai { 6567308ec68SBrian Somers /* Send Term ACK please */ 657411675baSBrian Somers fsm_Output(fp, CODE_TERMACK, id, NULL, 0, MB_IPCPOUT); 658af57ed9fSAtsushi Murai } 659af57ed9fSAtsushi Murai 660af57ed9fSAtsushi Murai static void 661944f7098SBrian Somers IpcpLayerStart(struct fsm *fp) 662af57ed9fSAtsushi Murai { 6637308ec68SBrian Somers /* We're about to start up ! */ 664897f9429SBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 665897f9429SBrian Somers 6663a2e4f62SBrian Somers log_Printf(LogIPCP, "%s: LayerStart.\n", fp->link->name); 667897f9429SBrian Somers throughput_start(&ipcp->throughput, "IPCP throughput", 668897f9429SBrian Somers Enabled(fp->bundle, OPT_THROUGHPUT)); 669479508cfSBrian Somers fp->more.reqs = fp->more.naks = fp->more.rejs = ipcp->cfg.fsm.maxreq * 3; 670af57ed9fSAtsushi Murai } 671af57ed9fSAtsushi Murai 672af57ed9fSAtsushi Murai static void 673944f7098SBrian Somers IpcpLayerFinish(struct fsm *fp) 674af57ed9fSAtsushi Murai { 6757308ec68SBrian Somers /* We're now down */ 676897f9429SBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 677897f9429SBrian Somers 6783a2e4f62SBrian Somers log_Printf(LogIPCP, "%s: LayerFinish.\n", fp->link->name); 679897f9429SBrian Somers throughput_stop(&ipcp->throughput); 680897f9429SBrian Somers throughput_log(&ipcp->throughput, LogIPCP, NULL); 6811ae349f5Scvs2svn } 6821ae349f5Scvs2svn 68368a0f0ccSBrian Somers void 684dd7e2610SBrian Somers ipcp_CleanInterface(struct ipcp *ipcp) 68568a0f0ccSBrian Somers { 6868fa6ebe4SBrian Somers struct iface *iface = ipcp->fsm.bundle->iface; 68768a0f0ccSBrian Somers 688610b185fSBrian Somers route_Clean(ipcp->fsm.bundle, ipcp->route); 689610b185fSBrian Somers 6903afe5ccbSBrian Somers if (iface->in_addrs && (Enabled(ipcp->fsm.bundle, OPT_PROXY) || 6913afe5ccbSBrian Somers Enabled(ipcp->fsm.bundle, OPT_PROXYALL))) { 6928fa6ebe4SBrian Somers int s = ID0socket(AF_INET, SOCK_DGRAM, 0); 6938fa6ebe4SBrian Somers if (s < 0) 6948fa6ebe4SBrian Somers log_Printf(LogERROR, "ipcp_CleanInterface: socket: %s\n", 69568a0f0ccSBrian Somers strerror(errno)); 6968fa6ebe4SBrian Somers else { 6973afe5ccbSBrian Somers if (Enabled(ipcp->fsm.bundle, OPT_PROXYALL)) 6983afe5ccbSBrian Somers ipcp_doproxyall(ipcp->fsm.bundle, arp_ClearProxy, s); 6993afe5ccbSBrian Somers else if (Enabled(ipcp->fsm.bundle, OPT_PROXY)) 7008fa6ebe4SBrian Somers arp_ClearProxy(ipcp->fsm.bundle, iface->in_addr[0].brd, s); 7018fa6ebe4SBrian Somers close(s); 7028fa6ebe4SBrian Somers } 70368a0f0ccSBrian Somers } 70468a0f0ccSBrian Somers 7058fa6ebe4SBrian Somers iface_inClear(ipcp->fsm.bundle->iface, IFACE_CLEAR_ALL); 706af57ed9fSAtsushi Murai } 707af57ed9fSAtsushi Murai 708af57ed9fSAtsushi Murai static void 709944f7098SBrian Somers IpcpLayerDown(struct fsm *fp) 710af57ed9fSAtsushi Murai { 7117308ec68SBrian Somers /* About to come down */ 712aa857470SBrian Somers static int recursing; 713aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 714455aabc3SBrian Somers const char *s; 715455aabc3SBrian Somers 716aa857470SBrian Somers if (!recursing++) { 7178fa6ebe4SBrian Somers if (ipcp->fsm.bundle->iface->in_addrs) 7188fa6ebe4SBrian Somers s = inet_ntoa(ipcp->fsm.bundle->iface->in_addr[0].ifa); 7198fa6ebe4SBrian Somers else 7208fa6ebe4SBrian Somers s = "Interface configuration error !"; 7213a2e4f62SBrian Somers log_Printf(LogIPCP, "%s: LayerDown: %s\n", fp->link->name, s); 722455aabc3SBrian Somers 723455aabc3SBrian Somers /* 724455aabc3SBrian Somers * XXX this stuff should really live in the FSM. Our config should 725455aabc3SBrian Somers * associate executable sections in files with events. 726455aabc3SBrian Somers */ 72730291ffbSBrian Somers if (system_Select(fp->bundle, s, LINKDOWNFILE, NULL, NULL) < 0) { 72849052c95SBrian Somers if (bundle_GetLabel(fp->bundle)) { 729dd7e2610SBrian Somers if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle), 73030291ffbSBrian Somers LINKDOWNFILE, NULL, NULL) < 0) 73130291ffbSBrian Somers system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL); 732455aabc3SBrian Somers } else 73330291ffbSBrian Somers system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL); 734af57ed9fSAtsushi Murai } 735af57ed9fSAtsushi Murai 736972a1bcfSBrian Somers ipcp_Setup(ipcp, INADDR_NONE); 7371ae349f5Scvs2svn } 738aa857470SBrian Somers recursing--; 739aa857470SBrian Somers } 7401ae349f5Scvs2svn 741dd0645c5SBrian Somers int 742dd0645c5SBrian Somers ipcp_InterfaceUp(struct ipcp *ipcp) 743dd0645c5SBrian Somers { 744dd0645c5SBrian Somers if (ipcp_SetIPaddress(ipcp->fsm.bundle, ipcp->my_ip, ipcp->peer_ip, 0) < 0) { 745a33b2ef7SBrian Somers log_Printf(LogERROR, "ipcp_InterfaceUp: unable to set ip address\n"); 746dd0645c5SBrian Somers return 0; 747dd0645c5SBrian Somers } 748dd0645c5SBrian Somers 749dd0645c5SBrian Somers #ifndef NOALIAS 750615ad4f9SBrian Somers if (ipcp->fsm.bundle->AliasEnabled) 751615ad4f9SBrian Somers PacketAliasSetAddress(ipcp->my_ip); 752dd0645c5SBrian Somers #endif 753dd0645c5SBrian Somers 754dd0645c5SBrian Somers return 1; 755dd0645c5SBrian Somers } 756dd0645c5SBrian Somers 7576f384573SBrian Somers static int 758944f7098SBrian Somers IpcpLayerUp(struct fsm *fp) 759af57ed9fSAtsushi Murai { 7607308ec68SBrian Somers /* We're now up */ 761aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 7628fa6ebe4SBrian Somers char tbuff[16]; 763af57ed9fSAtsushi Murai 7643a2e4f62SBrian Somers log_Printf(LogIPCP, "%s: LayerUp.\n", fp->link->name); 7658fa6ebe4SBrian Somers snprintf(tbuff, sizeof tbuff, "%s", inet_ntoa(ipcp->my_ip)); 7668fa6ebe4SBrian Somers log_Printf(LogIPCP, "myaddr %s hisaddr = %s\n", 7678fa6ebe4SBrian Somers tbuff, inet_ntoa(ipcp->peer_ip)); 76803604f35SBrian Somers 769503a7782SBrian Somers if (ipcp->peer_compproto >> 16 == PROTO_VJCOMP) 770eaa4df37SBrian Somers sl_compress_init(&ipcp->vj.cslc, (ipcp->peer_compproto >> 8) & 255); 77103604f35SBrian Somers 772dd0645c5SBrian Somers if (!ipcp_InterfaceUp(ipcp)) 7736f384573SBrian Somers return 0; 774455aabc3SBrian Somers 775455aabc3SBrian Somers /* 776455aabc3SBrian Somers * XXX this stuff should really live in the FSM. Our config should 777455aabc3SBrian Somers * associate executable sections in files with events. 778455aabc3SBrian Somers */ 7798fa6ebe4SBrian Somers if (system_Select(fp->bundle, tbuff, LINKUPFILE, NULL, NULL) < 0) { 78049052c95SBrian Somers if (bundle_GetLabel(fp->bundle)) { 781dd7e2610SBrian Somers if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle), 78230291ffbSBrian Somers LINKUPFILE, NULL, NULL) < 0) 78330291ffbSBrian Somers system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL); 784455aabc3SBrian Somers } else 78530291ffbSBrian Somers system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL); 786af57ed9fSAtsushi Murai } 787af57ed9fSAtsushi Murai 788479508cfSBrian Somers fp->more.reqs = fp->more.naks = fp->more.rejs = ipcp->cfg.fsm.maxreq * 3; 7890f2f3eb3SBrian Somers log_DisplayPrompts(); 790479508cfSBrian Somers 7916f384573SBrian Somers return 1; 792af57ed9fSAtsushi Murai } 793af57ed9fSAtsushi Murai 794af57ed9fSAtsushi Murai static int 7958fa6ebe4SBrian Somers AcceptableAddr(const struct in_range *prange, struct in_addr ipaddr) 796af57ed9fSAtsushi Murai { 7977308ec68SBrian Somers /* Is the given IP in the given range ? */ 798057df964SBrian Somers return (prange->ipaddr.s_addr & prange->mask.s_addr) == 799057df964SBrian Somers (ipaddr.s_addr & prange->mask.s_addr) && ipaddr.s_addr; 800af57ed9fSAtsushi Murai } 801af57ed9fSAtsushi Murai 802af57ed9fSAtsushi Murai static void 80330c2f2ffSBrian Somers IpcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, 80430c2f2ffSBrian Somers struct fsm_decode *dec) 805af57ed9fSAtsushi Murai { 8067308ec68SBrian Somers /* Deal with incoming PROTO_IPCP */ 8078fa6ebe4SBrian Somers struct iface *iface = fp->bundle->iface; 808aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 8098fa6ebe4SBrian Somers int type, length, gotdns, gotdnsnak, n; 810fe3125a0SBrian Somers u_int32_t compproto; 811af57ed9fSAtsushi Murai struct compreq *pcomp; 8123edeb0c6SBrian Somers struct in_addr ipaddr, dstipaddr, have_ip, dns[2], dnsnak[2]; 81330c2f2ffSBrian Somers char tbuff[100], tbuff2[100]; 814af57ed9fSAtsushi Murai 8153edeb0c6SBrian Somers gotdns = 0; 8163edeb0c6SBrian Somers gotdnsnak = 0; 8173edeb0c6SBrian Somers dnsnak[0].s_addr = dnsnak[1].s_addr = INADDR_ANY; 818af57ed9fSAtsushi Murai 819af57ed9fSAtsushi Murai while (plen >= sizeof(struct fsmconfig)) { 820af57ed9fSAtsushi Murai type = *cp; 821af57ed9fSAtsushi Murai length = cp[1]; 822d47dceb8SBrian Somers 823d47dceb8SBrian Somers if (length == 0) { 824dd7e2610SBrian Somers log_Printf(LogIPCP, "%s: IPCP size zero\n", fp->link->name); 825d47dceb8SBrian Somers break; 826d47dceb8SBrian Somers } 827d47dceb8SBrian Somers 8289e836af5SBrian Somers if (type < NCFTYPES) 82970ee81ffSBrian Somers snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes[type], length); 8309e836af5SBrian Somers else if (type > 128 && type < 128 + NCFTYPES128) 83170ee81ffSBrian Somers snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes128[type-128], length); 832af57ed9fSAtsushi Murai else 83370ee81ffSBrian Somers snprintf(tbuff, sizeof tbuff, " <%d>[%d] ", type, length); 834af57ed9fSAtsushi Murai 835af57ed9fSAtsushi Murai switch (type) { 836af57ed9fSAtsushi Murai case TY_IPADDR: /* RFC1332 */ 8379e8ec64bSBrian Somers memcpy(&ipaddr.s_addr, cp + 2, 4); 838dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 839af57ed9fSAtsushi Murai 8409780ef31SBrian Somers switch (mode_type) { 841af57ed9fSAtsushi Murai case MODE_REQ: 842503a7782SBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 843f5fb6bd0SBrian Somers if (ipaddr.s_addr == INADDR_ANY || 844503a7782SBrian Somers iplist_ip2pos(&ipcp->cfg.peer_list, ipaddr) < 0 || 84530c2f2ffSBrian Somers ipcp_SetIPaddress(fp->bundle, ipcp->cfg.my_range.ipaddr, 84630c2f2ffSBrian Somers ipaddr, 1)) { 847dd7e2610SBrian Somers log_Printf(LogIPCP, "%s: Address invalid or already in use\n", 848bcc332bdSBrian Somers inet_ntoa(ipaddr)); 8498390b576SBrian Somers /* 8508fa6ebe4SBrian Somers * If we've already had a valid address configured for the peer, 8518fa6ebe4SBrian Somers * try NAKing with that so that we don't have to upset things 8528fa6ebe4SBrian Somers * too much. 8538390b576SBrian Somers */ 8548fa6ebe4SBrian Somers for (n = 0; n < iface->in_addrs; n++) 8558fa6ebe4SBrian Somers if (iplist_ip2pos(&ipcp->cfg.peer_list, iface->in_addr[n].brd) 8568fa6ebe4SBrian Somers >=0) { 8578fa6ebe4SBrian Somers ipcp->peer_ip = iface->in_addr[n].brd; 8588fa6ebe4SBrian Somers break; 8598fa6ebe4SBrian Somers } 8608fa6ebe4SBrian Somers 8618fa6ebe4SBrian Somers if (n == iface->in_addrs) 8628390b576SBrian Somers /* Just pick an IP number from our list */ 863503a7782SBrian Somers ipcp->peer_ip = ChooseHisAddr 86430c2f2ffSBrian Somers (fp->bundle, ipcp->cfg.my_range.ipaddr); 8658390b576SBrian Somers 866503a7782SBrian Somers if (ipcp->peer_ip.s_addr == INADDR_ANY) { 86730c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 86830c2f2ffSBrian Somers dec->rejend += length; 869bcc332bdSBrian Somers } else { 87030c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 87130c2f2ffSBrian Somers memcpy(dec->nakend + 2, &ipcp->peer_ip.s_addr, length - 2); 87230c2f2ffSBrian Somers dec->nakend += length; 873bcc332bdSBrian Somers } 874bcc332bdSBrian Somers break; 875bcc332bdSBrian Somers } 876503a7782SBrian Somers } else if (!AcceptableAddr(&ipcp->cfg.peer_range, ipaddr)) { 877af57ed9fSAtsushi Murai /* 8788390b576SBrian Somers * If destination address is not acceptable, NAK with what we 879944f7098SBrian Somers * want to use. 880af57ed9fSAtsushi Murai */ 88130c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 8828fa6ebe4SBrian Somers for (n = 0; n < iface->in_addrs; n++) 8838fa6ebe4SBrian Somers if ((iface->in_addr[n].brd.s_addr & 8848fa6ebe4SBrian Somers ipcp->cfg.peer_range.mask.s_addr) 8858fa6ebe4SBrian Somers == (ipcp->cfg.peer_range.ipaddr.s_addr & 8868fa6ebe4SBrian Somers ipcp->cfg.peer_range.mask.s_addr)) { 8878390b576SBrian Somers /* We prefer the already-configured address */ 8888fa6ebe4SBrian Somers memcpy(dec->nakend + 2, &iface->in_addr[n].brd.s_addr, 8898fa6ebe4SBrian Somers length - 2); 8908fa6ebe4SBrian Somers break; 8918fa6ebe4SBrian Somers } 8928fa6ebe4SBrian Somers 8938fa6ebe4SBrian Somers if (n == iface->in_addrs) 89430c2f2ffSBrian Somers memcpy(dec->nakend + 2, &ipcp->peer_ip.s_addr, length - 2); 8958fa6ebe4SBrian Somers 89630c2f2ffSBrian Somers dec->nakend += length; 897af57ed9fSAtsushi Murai break; 898af57ed9fSAtsushi Murai } 899503a7782SBrian Somers ipcp->peer_ip = ipaddr; 90030c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 90130c2f2ffSBrian Somers dec->ackend += length; 902af57ed9fSAtsushi Murai break; 9038fa6ebe4SBrian Somers 904af57ed9fSAtsushi Murai case MODE_NAK: 905503a7782SBrian Somers if (AcceptableAddr(&ipcp->cfg.my_range, ipaddr)) { 906bcc332bdSBrian Somers /* Use address suggested by peer */ 90770ee81ffSBrian Somers snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s ", tbuff, 908503a7782SBrian Somers inet_ntoa(ipcp->my_ip)); 909dd7e2610SBrian Somers log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 910503a7782SBrian Somers ipcp->my_ip = ipaddr; 9111d1fc017SBrian Somers bundle_AdjustFilters(fp->bundle, &ipcp->my_ip, NULL); 912bcc332bdSBrian Somers } else { 913dd7e2610SBrian Somers log_Printf(log_IsKept(LogIPCP) ? LogIPCP : LogPHASE, 9148390b576SBrian Somers "%s: Unacceptable address!\n", inet_ntoa(ipaddr)); 915dd7e2610SBrian Somers fsm_Close(&ipcp->fsm); 916af57ed9fSAtsushi Murai } 917af57ed9fSAtsushi Murai break; 9188fa6ebe4SBrian Somers 919af57ed9fSAtsushi Murai case MODE_REJ: 920503a7782SBrian Somers ipcp->peer_reject |= (1 << type); 921af57ed9fSAtsushi Murai break; 922af57ed9fSAtsushi Murai } 923af57ed9fSAtsushi Murai break; 9248fa6ebe4SBrian Somers 925af57ed9fSAtsushi Murai case TY_COMPPROTO: 9267686a200SBrian Somers pcomp = (struct compreq *)(cp + 2); 9277686a200SBrian Somers compproto = (ntohs(pcomp->proto) << 16) + (pcomp->slots << 8) + 9287686a200SBrian Somers pcomp->compcid; 929dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto)); 930af57ed9fSAtsushi Murai 9319780ef31SBrian Somers switch (mode_type) { 932af57ed9fSAtsushi Murai case MODE_REQ: 9331342caedSBrian Somers if (!IsAccepted(ipcp->cfg.vj.neg)) { 93430c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 93530c2f2ffSBrian Somers dec->rejend += length; 936af57ed9fSAtsushi Murai } else { 937af57ed9fSAtsushi Murai switch (length) { 938af57ed9fSAtsushi Murai case 4: /* RFC1172 */ 939af57ed9fSAtsushi Murai if (ntohs(pcomp->proto) == PROTO_VJCOMP) { 9407686a200SBrian Somers log_Printf(LogWARN, "Peer is speaking RFC1172 compression " 9417686a200SBrian Somers "protocol !\n"); 94283d1af55SBrian Somers ipcp->heis1172 = 1; 943503a7782SBrian Somers ipcp->peer_compproto = compproto; 94430c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 94530c2f2ffSBrian Somers dec->ackend += length; 946af57ed9fSAtsushi Murai } else { 94730c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 948af57ed9fSAtsushi Murai pcomp->proto = htons(PROTO_VJCOMP); 94930c2f2ffSBrian Somers memcpy(dec->nakend+2, &pcomp, 2); 95030c2f2ffSBrian Somers dec->nakend += length; 951af57ed9fSAtsushi Murai } 952af57ed9fSAtsushi Murai break; 953af57ed9fSAtsushi Murai case 6: /* RFC1332 */ 9547686a200SBrian Somers if (ntohs(pcomp->proto) == PROTO_VJCOMP) { 9557686a200SBrian Somers if (pcomp->slots <= MAX_VJ_STATES 956503a7782SBrian Somers && pcomp->slots >= MIN_VJ_STATES) { 9577686a200SBrian Somers /* Ok, we can do that */ 958503a7782SBrian Somers ipcp->peer_compproto = compproto; 95983d1af55SBrian Somers ipcp->heis1172 = 0; 96030c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 96130c2f2ffSBrian Somers dec->ackend += length; 962af57ed9fSAtsushi Murai } else { 9637686a200SBrian Somers /* Get as close as we can to what he wants */ 9647686a200SBrian Somers ipcp->heis1172 = 0; 9657686a200SBrian Somers memcpy(dec->nakend, cp, 2); 9667686a200SBrian Somers pcomp->slots = pcomp->slots < MIN_VJ_STATES ? 9677686a200SBrian Somers MIN_VJ_STATES : MAX_VJ_STATES; 9687686a200SBrian Somers memcpy(dec->nakend+2, &pcomp, sizeof pcomp); 9697686a200SBrian Somers dec->nakend += length; 9707686a200SBrian Somers } 9717686a200SBrian Somers } else { 9727686a200SBrian Somers /* What we really want */ 97330c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 974af57ed9fSAtsushi Murai pcomp->proto = htons(PROTO_VJCOMP); 975503a7782SBrian Somers pcomp->slots = DEF_VJ_STATES; 9767686a200SBrian Somers pcomp->compcid = 1; 97730c2f2ffSBrian Somers memcpy(dec->nakend+2, &pcomp, sizeof pcomp); 97830c2f2ffSBrian Somers dec->nakend += length; 979af57ed9fSAtsushi Murai } 980af57ed9fSAtsushi Murai break; 981af57ed9fSAtsushi Murai default: 98230c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 98330c2f2ffSBrian Somers dec->rejend += length; 984af57ed9fSAtsushi Murai break; 985af57ed9fSAtsushi Murai } 986af57ed9fSAtsushi Murai } 987af57ed9fSAtsushi Murai break; 9888fa6ebe4SBrian Somers 989af57ed9fSAtsushi Murai case MODE_NAK: 9907686a200SBrian Somers if (ntohs(pcomp->proto) == PROTO_VJCOMP) { 9917686a200SBrian Somers if (pcomp->slots > MAX_VJ_STATES) 9927686a200SBrian Somers pcomp->slots = MAX_VJ_STATES; 9937686a200SBrian Somers else if (pcomp->slots < MIN_VJ_STATES) 9947686a200SBrian Somers pcomp->slots = MIN_VJ_STATES; 9957686a200SBrian Somers compproto = (ntohs(pcomp->proto) << 16) + (pcomp->slots << 8) + 9967686a200SBrian Somers pcomp->compcid; 9977686a200SBrian Somers } else 9987686a200SBrian Somers compproto = 0; 999dd7e2610SBrian Somers log_Printf(LogIPCP, "%s changing compproto: %08x --> %08x\n", 1000503a7782SBrian Somers tbuff, ipcp->my_compproto, compproto); 1001503a7782SBrian Somers ipcp->my_compproto = compproto; 1002af57ed9fSAtsushi Murai break; 10038fa6ebe4SBrian Somers 1004af57ed9fSAtsushi Murai case MODE_REJ: 1005503a7782SBrian Somers ipcp->peer_reject |= (1 << type); 1006af57ed9fSAtsushi Murai break; 1007af57ed9fSAtsushi Murai } 1008af57ed9fSAtsushi Murai break; 10098fa6ebe4SBrian Somers 1010af57ed9fSAtsushi Murai case TY_IPADDRS: /* RFC1172 */ 10119e8ec64bSBrian Somers memcpy(&ipaddr.s_addr, cp + 2, 4); 10129e8ec64bSBrian Somers memcpy(&dstipaddr.s_addr, cp + 6, 4); 101370ee81ffSBrian Somers snprintf(tbuff2, sizeof tbuff2, "%s %s,", tbuff, inet_ntoa(ipaddr)); 1014dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr)); 1015af57ed9fSAtsushi Murai 10169780ef31SBrian Somers switch (mode_type) { 1017af57ed9fSAtsushi Murai case MODE_REQ: 10185d9e6103SBrian Somers memcpy(dec->rejend, cp, length); 10195d9e6103SBrian Somers dec->rejend += length; 1020af57ed9fSAtsushi Murai break; 10218fa6ebe4SBrian Somers 1022af57ed9fSAtsushi Murai case MODE_NAK: 1023af57ed9fSAtsushi Murai case MODE_REJ: 1024af57ed9fSAtsushi Murai break; 1025af57ed9fSAtsushi Murai } 1026af57ed9fSAtsushi Murai break; 1027d8e55738SJordan K. Hubbard 10283edeb0c6SBrian Somers case TY_PRIMARY_DNS: /* DNS negotiation (rfc1877) */ 1029d8e55738SJordan K. Hubbard case TY_SECONDARY_DNS: 10309e8ec64bSBrian Somers memcpy(&ipaddr.s_addr, cp + 2, 4); 1031dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 10323edeb0c6SBrian Somers 10339780ef31SBrian Somers switch (mode_type) { 1034d8e55738SJordan K. Hubbard case MODE_REQ: 10353edeb0c6SBrian Somers if (!IsAccepted(ipcp->cfg.ns.dns_neg)) { 10363edeb0c6SBrian Somers ipcp->my_reject |= (1 << (type - TY_ADJUST_NS)); 103730c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 103830c2f2ffSBrian Somers dec->rejend += length; 1039d8e55738SJordan K. Hubbard break; 1040d8e55738SJordan K. Hubbard } 10413edeb0c6SBrian Somers if (!gotdns) { 10423edeb0c6SBrian Somers dns[0] = ipcp->cfg.ns.dns[0]; 10433edeb0c6SBrian Somers dns[1] = ipcp->cfg.ns.dns[1]; 10443edeb0c6SBrian Somers if (dns[0].s_addr == INADDR_ANY && dns[1].s_addr == INADDR_ANY) 10453edeb0c6SBrian Somers getdns(ipcp, dns); 10463edeb0c6SBrian Somers gotdns = 1; 10473edeb0c6SBrian Somers } 10483edeb0c6SBrian Somers have_ip = dns[type == TY_PRIMARY_DNS ? 0 : 1]; 1049944f7098SBrian Somers 10503edeb0c6SBrian Somers if (ipaddr.s_addr != have_ip.s_addr) { 10511ae349f5Scvs2svn /* 10523edeb0c6SBrian Somers * The client has got the DNS stuff wrong (first request) so 10531ae349f5Scvs2svn * we'll tell 'em how it is 10541ae349f5Scvs2svn */ 105530c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); /* copy first two (type/length) */ 10563edeb0c6SBrian Somers memcpy(dec->nakend + 2, &have_ip.s_addr, length - 2); 105730c2f2ffSBrian Somers dec->nakend += length; 10583edeb0c6SBrian Somers } else { 1059d8e55738SJordan K. Hubbard /* 1060944f7098SBrian Somers * Otherwise they have it right (this time) so we send a ack packet 1061944f7098SBrian Somers * back confirming it... end of story 1062d8e55738SJordan K. Hubbard */ 106330c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 106430c2f2ffSBrian Somers dec->ackend += length; 10653edeb0c6SBrian Somers } 1066d8e55738SJordan K. Hubbard break; 10678fa6ebe4SBrian Somers 1068d8e55738SJordan K. Hubbard case MODE_NAK: /* what does this mean?? */ 10693edeb0c6SBrian Somers if (IsEnabled(ipcp->cfg.ns.dns_neg)) { 10703edeb0c6SBrian Somers gotdnsnak = 1; 10719e8ec64bSBrian Somers memcpy(&dnsnak[type == TY_PRIMARY_DNS ? 0 : 1].s_addr, cp + 2, 4); 10723edeb0c6SBrian Somers } 1073d8e55738SJordan K. Hubbard break; 10748fa6ebe4SBrian Somers 10753edeb0c6SBrian Somers case MODE_REJ: /* Can't do much, stop asking */ 10763edeb0c6SBrian Somers ipcp->peer_reject |= (1 << (type - TY_ADJUST_NS)); 1077d8e55738SJordan K. Hubbard break; 1078d8e55738SJordan K. Hubbard } 1079d8e55738SJordan K. Hubbard break; 1080d8e55738SJordan K. Hubbard 10813edeb0c6SBrian Somers case TY_PRIMARY_NBNS: /* M$ NetBIOS nameserver hack (rfc1877) */ 1082d8e55738SJordan K. Hubbard case TY_SECONDARY_NBNS: 10839e8ec64bSBrian Somers memcpy(&ipaddr.s_addr, cp + 2, 4); 1084dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 10853edeb0c6SBrian Somers 10869780ef31SBrian Somers switch (mode_type) { 1087d8e55738SJordan K. Hubbard case MODE_REQ: 10883edeb0c6SBrian Somers have_ip.s_addr = 10893edeb0c6SBrian Somers ipcp->cfg.ns.nbns[type == TY_PRIMARY_NBNS ? 0 : 1].s_addr; 10903edeb0c6SBrian Somers 10913edeb0c6SBrian Somers if (have_ip.s_addr == INADDR_ANY) { 1092dd7e2610SBrian Somers log_Printf(LogIPCP, "NBNS REQ - rejected - nbns not set\n"); 10933edeb0c6SBrian Somers ipcp->my_reject |= (1 << (type - TY_ADJUST_NS)); 109430c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 109530c2f2ffSBrian Somers dec->rejend += length; 1096d8e55738SJordan K. Hubbard break; 1097d8e55738SJordan K. Hubbard } 10983edeb0c6SBrian Somers 10993edeb0c6SBrian Somers if (ipaddr.s_addr != have_ip.s_addr) { 110030c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 11013edeb0c6SBrian Somers memcpy(dec->nakend+2, &have_ip.s_addr, length); 110230c2f2ffSBrian Somers dec->nakend += length; 11033edeb0c6SBrian Somers } else { 110430c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 110530c2f2ffSBrian Somers dec->ackend += length; 11063edeb0c6SBrian Somers } 1107d8e55738SJordan K. Hubbard break; 11088fa6ebe4SBrian Somers 1109d8e55738SJordan K. Hubbard case MODE_NAK: 1110dd7e2610SBrian Somers log_Printf(LogIPCP, "MS NBNS req %d - NAK??\n", type); 1111d8e55738SJordan K. Hubbard break; 11128fa6ebe4SBrian Somers 1113d8e55738SJordan K. Hubbard case MODE_REJ: 1114dd7e2610SBrian Somers log_Printf(LogIPCP, "MS NBNS req %d - REJ??\n", type); 1115d8e55738SJordan K. Hubbard break; 1116d8e55738SJordan K. Hubbard } 1117d8e55738SJordan K. Hubbard break; 1118d8e55738SJordan K. Hubbard 1119af57ed9fSAtsushi Murai default: 112030c2f2ffSBrian Somers if (mode_type != MODE_NOP) { 112183d1af55SBrian Somers ipcp->my_reject |= (1 << type); 112230c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 112330c2f2ffSBrian Somers dec->rejend += length; 112430c2f2ffSBrian Somers } 1125af57ed9fSAtsushi Murai break; 1126af57ed9fSAtsushi Murai } 1127af57ed9fSAtsushi Murai plen -= length; 1128af57ed9fSAtsushi Murai cp += length; 1129af57ed9fSAtsushi Murai } 11301342caedSBrian Somers 11313edeb0c6SBrian Somers if (gotdnsnak) 11323edeb0c6SBrian Somers if (!setdns(ipcp, dnsnak)) { 11333edeb0c6SBrian Somers ipcp->peer_reject |= (1 << (TY_PRIMARY_DNS - TY_ADJUST_NS)); 11343edeb0c6SBrian Somers ipcp->peer_reject |= (1 << (TY_SECONDARY_DNS - TY_ADJUST_NS)); 11353edeb0c6SBrian Somers } 11363edeb0c6SBrian Somers 1137e43ebac1SBrian Somers if (mode_type != MODE_NOP) { 11381342caedSBrian Somers if (dec->rejend != dec->rej) { 11391342caedSBrian Somers /* rejects are preferred */ 11401342caedSBrian Somers dec->ackend = dec->ack; 11411342caedSBrian Somers dec->nakend = dec->nak; 11421342caedSBrian Somers } else if (dec->nakend != dec->nak) 11431342caedSBrian Somers /* then NAKs */ 11441342caedSBrian Somers dec->ackend = dec->ack; 11451ae349f5Scvs2svn } 1146af57ed9fSAtsushi Murai } 1147af57ed9fSAtsushi Murai 11485d9e6103SBrian Somers extern struct mbuf * 11495d9e6103SBrian Somers ipcp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 1150af57ed9fSAtsushi Murai { 11517308ec68SBrian Somers /* Got PROTO_IPCP from link */ 1152411675baSBrian Somers mbuf_SetType(bp, MB_IPCPIN); 1153641684cdSBrian Somers if (bundle_Phase(bundle) == PHASE_NETWORK) 11545d9e6103SBrian Somers fsm_Input(&bundle->ncp.ipcp.fsm, bp); 1155641684cdSBrian Somers else { 1156641684cdSBrian Somers if (bundle_Phase(bundle) < PHASE_NETWORK) 1157641684cdSBrian Somers log_Printf(LogIPCP, "%s: Error: Unexpected IPCP in phase %s (ignored)\n", 11585d9e6103SBrian Somers l->name, bundle_PhaseName(bundle)); 1159641684cdSBrian Somers mbuf_Free(bp); 1160641684cdSBrian Somers } 11615d9e6103SBrian Somers return NULL; 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); 11961d1fc017SBrian 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 12161d1fc017SBrian Somers bundle_AdjustFilters(bundle, NULL, &ipcp->peer_ip); 12171d1fc017SBrian Somers 12181d1fc017SBrian Somers return 1; /* Ok */ 12199c97abd8SBrian Somers } 1220bc76350eSBrian Somers 1221bc76350eSBrian Somers struct in_addr 1222bc76350eSBrian Somers addr2mask(struct in_addr addr) 1223bc76350eSBrian Somers { 1224bc76350eSBrian Somers u_int32_t haddr = ntohl(addr.s_addr); 1225bc76350eSBrian Somers 1226bc76350eSBrian Somers haddr = IN_CLASSA(haddr) ? IN_CLASSA_NET : 1227bc76350eSBrian Somers IN_CLASSB(haddr) ? IN_CLASSB_NET : 1228bc76350eSBrian Somers IN_CLASSC_NET; 1229bc76350eSBrian Somers addr.s_addr = htonl(haddr); 1230bc76350eSBrian Somers 1231bc76350eSBrian Somers return addr; 1232bc76350eSBrian Somers } 1233