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 * 209e8ec64bSBrian Somers * $Id: ipcp.c,v 1.64 1998/08/26 17:39:37 brian Exp $ 21af57ed9fSAtsushi Murai * 22af57ed9fSAtsushi Murai * TODO: 23897f9429SBrian Somers * o More RFC1772 backward compatibility 24af57ed9fSAtsushi Murai */ 2575240ed1SBrian Somers #include <sys/param.h> 265b4c5b00SBrian Somers #include <netinet/in_systm.h> 275b4c5b00SBrian Somers #include <netinet/in.h> 285b4c5b00SBrian Somers #include <netinet/ip.h> 295b4c5b00SBrian Somers #include <arpa/inet.h> 305b4c5b00SBrian Somers #include <sys/socket.h> 3175240ed1SBrian Somers #include <netdb.h> 32455aabc3SBrian Somers #include <net/if.h> 33455aabc3SBrian Somers #include <sys/sockio.h> 341fa665f5SBrian Somers #include <sys/un.h> 3575240ed1SBrian Somers 36615ad4f9SBrian Somers #ifndef NOALIAS 37615ad4f9SBrian Somers #include <alias.h> 38615ad4f9SBrian Somers #endif 393edeb0c6SBrian Somers #include <fcntl.h> 403edeb0c6SBrian Somers #include <resolv.h> 41d1a3ea47SBrian Somers #include <stdlib.h> 4275240ed1SBrian Somers #include <string.h> 43455aabc3SBrian Somers #include <sys/errno.h> 446140ba11SBrian Somers #include <termios.h> 4575240ed1SBrian Somers #include <unistd.h> 4675240ed1SBrian Somers 479e8ec64bSBrian Somers #include "ua.h" 48c9e11a11SBrian Somers #include "defs.h" 49b6e82f33SBrian Somers #include "command.h" 5075240ed1SBrian Somers #include "mbuf.h" 5175240ed1SBrian Somers #include "log.h" 5275240ed1SBrian Somers #include "timer.h" 53af57ed9fSAtsushi Murai #include "fsm.h" 54af57ed9fSAtsushi Murai #include "lcpproto.h" 55af57ed9fSAtsushi Murai #include "lcp.h" 56bcc332bdSBrian Somers #include "iplist.h" 579a0b991fSBrian Somers #include "throughput.h" 581ae349f5Scvs2svn #include "slcompress.h" 595a72b6edSBrian Somers #include "lqr.h" 605a72b6edSBrian Somers #include "hdlc.h" 61eaa4df37SBrian Somers #include "ipcp.h" 629c97abd8SBrian Somers #include "filter.h" 632f786681SBrian Somers #include "descriptor.h" 641ae349f5Scvs2svn #include "vjcomp.h" 656140ba11SBrian Somers #include "async.h" 663b0f8d2eSBrian Somers #include "ccp.h" 678c07a7b2SBrian Somers #include "link.h" 6863b73463SBrian Somers #include "physical.h" 693b0f8d2eSBrian Somers #include "mp.h" 703b0f8d2eSBrian Somers #include "bundle.h" 71455aabc3SBrian Somers #include "id.h" 72455aabc3SBrian Somers #include "arp.h" 73455aabc3SBrian Somers #include "systems.h" 7485b542cfSBrian Somers #include "prompt.h" 75610b185fSBrian Somers #include "route.h" 76af57ed9fSAtsushi Murai 77503a7782SBrian Somers #undef REJECTED 78503a7782SBrian Somers #define REJECTED(p, x) ((p)->peer_reject & (1<<(x))) 793edeb0c6SBrian Somers #define issep(ch) ((ch) == ' ' || (ch) == '\t') 803edeb0c6SBrian Somers #define isip(ch) (((ch) >= '0' && (ch) <= '9') || (ch) == '.') 81d8e55738SJordan K. Hubbard 8229e275ceSBrian Somers struct compreq { 8329e275ceSBrian Somers u_short proto; 8429e275ceSBrian Somers u_char slots; 8529e275ceSBrian Somers u_char compcid; 8629e275ceSBrian Somers }; 8775240ed1SBrian Somers 886f384573SBrian Somers static int IpcpLayerUp(struct fsm *); 891ae349f5Scvs2svn static void IpcpLayerDown(struct fsm *); 90927145beSBrian Somers static void IpcpLayerStart(struct fsm *); 91927145beSBrian Somers static void IpcpLayerFinish(struct fsm *); 92927145beSBrian Somers static void IpcpInitRestartCounter(struct fsm *); 937308ec68SBrian Somers static void IpcpSendConfigReq(struct fsm *); 942267893fSBrian Somers static void IpcpSentTerminateReq(struct fsm *); 952267893fSBrian Somers static void IpcpSendTerminateAck(struct fsm *, u_char); 9630c2f2ffSBrian Somers static void IpcpDecodeConfig(struct fsm *, u_char *, int, int, 9730c2f2ffSBrian Somers struct fsm_decode *); 98af57ed9fSAtsushi Murai 9983d1af55SBrian Somers static struct fsm_callbacks ipcp_Callbacks = { 100af57ed9fSAtsushi Murai IpcpLayerUp, 101af57ed9fSAtsushi Murai IpcpLayerDown, 102af57ed9fSAtsushi Murai IpcpLayerStart, 103af57ed9fSAtsushi Murai IpcpLayerFinish, 104af57ed9fSAtsushi Murai IpcpInitRestartCounter, 105af57ed9fSAtsushi Murai IpcpSendConfigReq, 1062267893fSBrian Somers IpcpSentTerminateReq, 107af57ed9fSAtsushi Murai IpcpSendTerminateAck, 108af57ed9fSAtsushi Murai IpcpDecodeConfig, 109dd7e2610SBrian Somers fsm_NullRecvResetReq, 110dd7e2610SBrian Somers fsm_NullRecvResetAck 111af57ed9fSAtsushi Murai }; 112af57ed9fSAtsushi Murai 113b6e82f33SBrian Somers static const char *cftypes[] = { 1149e836af5SBrian Somers /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */ 1159e836af5SBrian Somers "???", 1169e836af5SBrian Somers "IPADDRS", /* 1: IP-Addresses */ /* deprecated */ 1179e836af5SBrian Somers "COMPPROTO", /* 2: IP-Compression-Protocol */ 1189e836af5SBrian Somers "IPADDR", /* 3: IP-Address */ 119af57ed9fSAtsushi Murai }; 120af57ed9fSAtsushi Murai 12170ee81ffSBrian Somers #define NCFTYPES (sizeof cftypes/sizeof cftypes[0]) 1229e836af5SBrian Somers 123b6e82f33SBrian Somers static const char *cftypes128[] = { 1249e836af5SBrian Somers /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */ 1259e836af5SBrian Somers "???", 1269e836af5SBrian Somers "PRIDNS", /* 129: Primary DNS Server Address */ 1279e836af5SBrian Somers "PRINBNS", /* 130: Primary NBNS Server Address */ 1289e836af5SBrian Somers "SECDNS", /* 131: Secondary DNS Server Address */ 1299e836af5SBrian Somers "SECNBNS", /* 132: Secondary NBNS Server Address */ 1309e836af5SBrian Somers }; 1319e836af5SBrian Somers 13270ee81ffSBrian Somers #define NCFTYPES128 (sizeof cftypes128/sizeof cftypes128[0]) 1339e836af5SBrian Somers 1349a0b991fSBrian Somers void 1355828db6dSBrian Somers ipcp_AddInOctets(struct ipcp *ipcp, int n) 136af57ed9fSAtsushi Murai { 1375828db6dSBrian Somers throughput_addin(&ipcp->throughput, n); 138af57ed9fSAtsushi Murai } 139af57ed9fSAtsushi Murai 1409a0b991fSBrian Somers void 1415828db6dSBrian Somers ipcp_AddOutOctets(struct ipcp *ipcp, int n) 142af57ed9fSAtsushi Murai { 1435828db6dSBrian Somers throughput_addout(&ipcp->throughput, n); 1441ae349f5Scvs2svn } 1451ae349f5Scvs2svn 1463edeb0c6SBrian Somers static void 1473edeb0c6SBrian Somers getdns(struct ipcp *ipcp, struct in_addr addr[2]) 1483edeb0c6SBrian Somers { 1493edeb0c6SBrian Somers FILE *fp; 1503edeb0c6SBrian Somers 1513edeb0c6SBrian Somers addr[0].s_addr = addr[1].s_addr = INADDR_ANY; 1523edeb0c6SBrian Somers if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { 1533edeb0c6SBrian Somers char buf[LINE_LEN], *cp, *end; 1543edeb0c6SBrian Somers int n; 1553edeb0c6SBrian Somers 1563edeb0c6SBrian Somers n = 0; 1573edeb0c6SBrian Somers buf[sizeof buf - 1] = '\0'; 1583edeb0c6SBrian Somers while (fgets(buf, sizeof buf - 1, fp)) { 1593edeb0c6SBrian Somers if (!strncmp(buf, "nameserver", 10) && issep(buf[10])) { 1603edeb0c6SBrian Somers for (cp = buf + 11; issep(*cp); cp++) 1613edeb0c6SBrian Somers ; 1623edeb0c6SBrian Somers for (end = cp; isip(*end); end++) 1633edeb0c6SBrian Somers ; 1643edeb0c6SBrian Somers *end = '\0'; 1653edeb0c6SBrian Somers if (inet_aton(cp, addr+n) && ++n == 2) 1663edeb0c6SBrian Somers break; 1673edeb0c6SBrian Somers } 1683edeb0c6SBrian Somers } 1693edeb0c6SBrian Somers if (n == 1) 1703edeb0c6SBrian Somers addr[1] = addr[0]; 1713edeb0c6SBrian Somers fclose(fp); 1723edeb0c6SBrian Somers } 1733edeb0c6SBrian Somers } 1743edeb0c6SBrian Somers 1753edeb0c6SBrian Somers static int 1763edeb0c6SBrian Somers setdns(struct ipcp *ipcp, struct in_addr addr[2]) 1773edeb0c6SBrian Somers { 1783edeb0c6SBrian Somers FILE *fp; 1793edeb0c6SBrian Somers char wbuf[LINE_LEN + 54]; 1803edeb0c6SBrian Somers int wlen; 1813edeb0c6SBrian Somers 1823edeb0c6SBrian Somers if (addr[0].s_addr == INADDR_ANY || addr[1].s_addr == INADDR_ANY) { 1833edeb0c6SBrian Somers struct in_addr old[2]; 1843edeb0c6SBrian Somers 1853edeb0c6SBrian Somers getdns(ipcp, old); 1863edeb0c6SBrian Somers if (addr[0].s_addr == INADDR_ANY) 1873edeb0c6SBrian Somers addr[0] = old[0]; 1883edeb0c6SBrian Somers if (addr[1].s_addr == INADDR_ANY) 1893edeb0c6SBrian Somers addr[1] = old[1]; 1903edeb0c6SBrian Somers } 1913edeb0c6SBrian Somers 1923edeb0c6SBrian Somers if (addr[0].s_addr == INADDR_ANY && addr[1].s_addr == INADDR_ANY) { 193dd7e2610SBrian Somers log_Printf(LogWARN, "%s not modified: All nameservers NAKd\n", 1943edeb0c6SBrian Somers _PATH_RESCONF); 1953edeb0c6SBrian Somers return 0; 1963edeb0c6SBrian Somers } 1973edeb0c6SBrian Somers 1983edeb0c6SBrian Somers wlen = 0; 1993edeb0c6SBrian Somers if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { 2003edeb0c6SBrian Somers char buf[LINE_LEN]; 2013edeb0c6SBrian Somers int len; 2023edeb0c6SBrian Somers 2033edeb0c6SBrian Somers buf[sizeof buf - 1] = '\0'; 2043edeb0c6SBrian Somers while (fgets(buf, sizeof buf - 1, fp)) { 2053edeb0c6SBrian Somers if (strncmp(buf, "nameserver", 10) || !issep(buf[10])) { 2063edeb0c6SBrian Somers len = strlen(buf); 2073edeb0c6SBrian Somers if (len > sizeof wbuf - wlen) { 208dd7e2610SBrian Somers log_Printf(LogWARN, "%s: Can only cope with max file size %d\n", 2093edeb0c6SBrian Somers _PATH_RESCONF, LINE_LEN); 2103edeb0c6SBrian Somers fclose(fp); 2113edeb0c6SBrian Somers return 0; 2123edeb0c6SBrian Somers } 2133edeb0c6SBrian Somers memcpy(wbuf + wlen, buf, len); 2143edeb0c6SBrian Somers wlen += len; 2153edeb0c6SBrian Somers } 2163edeb0c6SBrian Somers } 2173edeb0c6SBrian Somers fclose(fp); 2183edeb0c6SBrian Somers } 2193edeb0c6SBrian Somers 2203edeb0c6SBrian Somers if (addr[0].s_addr != INADDR_ANY) { 2213edeb0c6SBrian Somers snprintf(wbuf + wlen, sizeof wbuf - wlen, "nameserver %s\n", 2223edeb0c6SBrian Somers inet_ntoa(addr[0])); 223dd7e2610SBrian Somers log_Printf(LogIPCP, "Primary nameserver set to %s", wbuf + wlen + 11); 2243edeb0c6SBrian Somers wlen += strlen(wbuf + wlen); 2253edeb0c6SBrian Somers } 2263edeb0c6SBrian Somers 2273edeb0c6SBrian Somers if (addr[1].s_addr != INADDR_ANY && addr[1].s_addr != addr[0].s_addr) { 2283edeb0c6SBrian Somers snprintf(wbuf + wlen, sizeof wbuf - wlen, "nameserver %s\n", 2293edeb0c6SBrian Somers inet_ntoa(addr[1])); 230dd7e2610SBrian Somers log_Printf(LogIPCP, "Secondary nameserver set to %s", wbuf + wlen + 11); 2313edeb0c6SBrian Somers wlen += strlen(wbuf + wlen); 2323edeb0c6SBrian Somers } 2333edeb0c6SBrian Somers 2343edeb0c6SBrian Somers if (wlen) { 2353edeb0c6SBrian Somers int fd; 2363edeb0c6SBrian Somers 2373edeb0c6SBrian Somers if ((fd = ID0open(_PATH_RESCONF, O_WRONLY|O_CREAT, 0644)) != -1) { 2383edeb0c6SBrian Somers if (write(fd, wbuf, wlen) != wlen) { 239dd7e2610SBrian Somers log_Printf(LogERROR, "setdns: write(): %s\n", strerror(errno)); 2403edeb0c6SBrian Somers close(fd); 2413edeb0c6SBrian Somers return 0; 2423edeb0c6SBrian Somers } 2433edeb0c6SBrian Somers if (ftruncate(fd, wlen) == -1) { 244dd7e2610SBrian Somers log_Printf(LogERROR, "setdns: truncate(): %s\n", strerror(errno)); 2453edeb0c6SBrian Somers close(fd); 2463edeb0c6SBrian Somers return 0; 2473edeb0c6SBrian Somers } 2483edeb0c6SBrian Somers close(fd); 2493edeb0c6SBrian Somers } else { 250dd7e2610SBrian Somers log_Printf(LogERROR, "setdns: open(): %s\n", strerror(errno)); 2513edeb0c6SBrian Somers return 0; 2523edeb0c6SBrian Somers } 2533edeb0c6SBrian Somers } 2543edeb0c6SBrian Somers 2553edeb0c6SBrian Somers return 1; 256af57ed9fSAtsushi Murai } 257af57ed9fSAtsushi Murai 258274e766cSBrian Somers int 259dd7e2610SBrian Somers ipcp_Show(struct cmdargs const *arg) 260af57ed9fSAtsushi Murai { 261610b185fSBrian Somers struct ipcp *ipcp = &arg->bundle->ncp.ipcp; 262af57ed9fSAtsushi Murai 263610b185fSBrian Somers prompt_Printf(arg->prompt, "%s [%s]\n", ipcp->fsm.name, 264610b185fSBrian Somers State2Nam(ipcp->fsm.state)); 265610b185fSBrian Somers if (ipcp->fsm.state == ST_OPENED) { 266b6217683SBrian Somers prompt_Printf(arg->prompt, " His side: %s, %s\n", 267610b185fSBrian Somers inet_ntoa(ipcp->peer_ip), vj2asc(ipcp->peer_compproto)); 268b6217683SBrian Somers prompt_Printf(arg->prompt, " My side: %s, %s\n", 269610b185fSBrian Somers inet_ntoa(ipcp->my_ip), vj2asc(ipcp->my_compproto)); 270d1a3ea47SBrian Somers } 2715b4c5b00SBrian Somers 272610b185fSBrian Somers if (ipcp->route) { 273610b185fSBrian Somers prompt_Printf(arg->prompt, "\n"); 274610b185fSBrian Somers route_ShowSticky(arg->prompt, ipcp->route); 2751ae349f5Scvs2svn } 276927145beSBrian Somers 277b6217683SBrian Somers prompt_Printf(arg->prompt, "\nDefaults:\n"); 27850abd4c8SBrian Somers prompt_Printf(arg->prompt, " My Address: %s/%d", 279610b185fSBrian Somers inet_ntoa(ipcp->cfg.my_range.ipaddr), ipcp->cfg.my_range.width); 28050abd4c8SBrian Somers 281610b185fSBrian Somers if (ipcp->cfg.HaveTriggerAddress) 28250abd4c8SBrian Somers prompt_Printf(arg->prompt, " (trigger with %s)", 283610b185fSBrian Somers inet_ntoa(ipcp->cfg.TriggerAddress)); 28450abd4c8SBrian Somers prompt_Printf(arg->prompt, "\n VJ compression: %s (%d slots %s slot " 285610b185fSBrian Somers "compression)\n", command_ShowNegval(ipcp->cfg.vj.neg), 286610b185fSBrian Somers ipcp->cfg.vj.slots, ipcp->cfg.vj.slotcomp ? "with" : "without"); 28750abd4c8SBrian Somers 288610b185fSBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) 289b6217683SBrian Somers prompt_Printf(arg->prompt, " His Address: %s\n", 290610b185fSBrian Somers ipcp->cfg.peer_list.src); 2911ae349f5Scvs2svn else 292b6217683SBrian Somers prompt_Printf(arg->prompt, " His Address: %s/%d\n", 293610b185fSBrian Somers inet_ntoa(ipcp->cfg.peer_range.ipaddr), 294610b185fSBrian Somers ipcp->cfg.peer_range.width); 29550abd4c8SBrian Somers 2963edeb0c6SBrian Somers prompt_Printf(arg->prompt, " DNS: %s, ", 297610b185fSBrian Somers inet_ntoa(ipcp->cfg.ns.dns[0])); 298610b185fSBrian Somers prompt_Printf(arg->prompt, "%s, %s\n", inet_ntoa(ipcp->cfg.ns.dns[1]), 299610b185fSBrian Somers command_ShowNegval(ipcp->cfg.ns.dns_neg)); 3003edeb0c6SBrian Somers prompt_Printf(arg->prompt, " NetBIOS NS: %s, ", 301610b185fSBrian Somers inet_ntoa(ipcp->cfg.ns.nbns[0])); 302610b185fSBrian Somers prompt_Printf(arg->prompt, "%s\n", inet_ntoa(ipcp->cfg.ns.nbns[1])); 3031342caedSBrian Somers 304b6217683SBrian Somers prompt_Printf(arg->prompt, "\n"); 305610b185fSBrian Somers throughput_disp(&ipcp->throughput, arg->prompt); 3069a0b991fSBrian Somers 307927145beSBrian Somers return 0; 308af57ed9fSAtsushi Murai } 309af57ed9fSAtsushi Murai 310d1a3ea47SBrian Somers int 311dd7e2610SBrian Somers ipcp_vjset(struct cmdargs const *arg) 312d1a3ea47SBrian Somers { 31325092092SBrian Somers if (arg->argc != arg->argn+2) 314d1a3ea47SBrian Somers return -1; 31525092092SBrian Somers if (!strcasecmp(arg->argv[arg->argn], "slots")) { 316d1a3ea47SBrian Somers int slots; 317d1a3ea47SBrian Somers 31825092092SBrian Somers slots = atoi(arg->argv[arg->argn+1]); 319d1a3ea47SBrian Somers if (slots < 4 || slots > 16) 320d1a3ea47SBrian Somers return 1; 3211342caedSBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slots = slots; 322d1a3ea47SBrian Somers return 0; 32325092092SBrian Somers } else if (!strcasecmp(arg->argv[arg->argn], "slotcomp")) { 32425092092SBrian Somers if (!strcasecmp(arg->argv[arg->argn+1], "on")) 3251342caedSBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 1; 32625092092SBrian Somers else if (!strcasecmp(arg->argv[arg->argn+1], "off")) 3271342caedSBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 0; 328d1a3ea47SBrian Somers else 329d1a3ea47SBrian Somers return 2; 330d1a3ea47SBrian Somers return 0; 331d1a3ea47SBrian Somers } 332d1a3ea47SBrian Somers return -1; 333d1a3ea47SBrian Somers } 334d1a3ea47SBrian Somers 3351ae349f5Scvs2svn void 3366d666775SBrian Somers ipcp_Init(struct ipcp *ipcp, struct bundle *bundle, struct link *l, 3376d666775SBrian Somers const struct fsm_parent *parent) 338d1a3ea47SBrian Somers { 339503a7782SBrian Somers struct hostent *hp; 340503a7782SBrian Somers char name[MAXHOSTNAMELEN]; 3413b0f8d2eSBrian Somers static const char *timer_names[] = 3423b0f8d2eSBrian Somers {"IPCP restart", "IPCP openmode", "IPCP stopped"}; 34329e275ceSBrian Somers 3443b0f8d2eSBrian Somers fsm_Init(&ipcp->fsm, "IPCP", PROTO_IPCP, 1, IPCP_MAXCODE, 10, LogIPCP, 3453b0f8d2eSBrian Somers bundle, l, parent, &ipcp_Callbacks, timer_names); 346503a7782SBrian Somers 347610b185fSBrian Somers ipcp->route = NULL; 3481342caedSBrian Somers ipcp->cfg.vj.slots = DEF_VJ_STATES; 3491342caedSBrian Somers ipcp->cfg.vj.slotcomp = 1; 350503a7782SBrian Somers memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range); 351503a7782SBrian Somers if (gethostname(name, sizeof name) == 0) { 352503a7782SBrian Somers hp = gethostbyname(name); 353503a7782SBrian Somers if (hp && hp->h_addrtype == AF_INET) { 354503a7782SBrian Somers memcpy(&ipcp->cfg.my_range.ipaddr.s_addr, hp->h_addr, hp->h_length); 355503a7782SBrian Somers ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 356503a7782SBrian Somers ipcp->cfg.peer_range.width = 32; 357d1a3ea47SBrian Somers } 358503a7782SBrian Somers } 35930c2f2ffSBrian Somers ipcp->cfg.netmask.s_addr = INADDR_ANY; 360503a7782SBrian Somers memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 361503a7782SBrian Somers iplist_setsrc(&ipcp->cfg.peer_list, ""); 362503a7782SBrian Somers ipcp->cfg.HaveTriggerAddress = 0; 363503a7782SBrian Somers 3643edeb0c6SBrian Somers ipcp->cfg.ns.dns[0].s_addr = INADDR_ANY; 3653edeb0c6SBrian Somers ipcp->cfg.ns.dns[1].s_addr = INADDR_ANY; 3663edeb0c6SBrian Somers ipcp->cfg.ns.dns_neg = 0; 3673edeb0c6SBrian Somers ipcp->cfg.ns.nbns[0].s_addr = INADDR_ANY; 3683edeb0c6SBrian Somers ipcp->cfg.ns.nbns[1].s_addr = INADDR_ANY; 369cd9647a1SBrian Somers 370cd9647a1SBrian Somers ipcp->cfg.fsmretry = DEF_FSMRETRY; 3711342caedSBrian Somers ipcp->cfg.vj.neg = NEG_ENABLED|NEG_ACCEPTED; 372503a7782SBrian Somers 373eaa4df37SBrian Somers memset(&ipcp->vj, '\0', sizeof ipcp->vj); 374eaa4df37SBrian Somers 375503a7782SBrian Somers ipcp->my_ifip.s_addr = INADDR_ANY; 376503a7782SBrian Somers ipcp->peer_ifip.s_addr = INADDR_ANY; 377503a7782SBrian Somers 378fdf61171SBrian Somers throughput_init(&ipcp->throughput); 3795a72b6edSBrian Somers memset(ipcp->Queue, '\0', sizeof ipcp->Queue); 380503a7782SBrian Somers ipcp_Setup(ipcp); 381d1a3ea47SBrian Somers } 382d1a3ea47SBrian Somers 383af57ed9fSAtsushi Murai void 384ce828a6eSBrian Somers ipcp_SetLink(struct ipcp *ipcp, struct link *l) 385af57ed9fSAtsushi Murai { 386ce828a6eSBrian Somers ipcp->fsm.link = l; 387af57ed9fSAtsushi Murai } 388549d663dSAtsushi Murai 389ce828a6eSBrian Somers void 390503a7782SBrian Somers ipcp_Setup(struct ipcp *ipcp) 391503a7782SBrian Somers { 392503a7782SBrian Somers int pos; 393503a7782SBrian Somers 394503a7782SBrian Somers ipcp->fsm.open_mode = 0; 3955454ccd9SBrian Somers ipcp->fsm.maxconfig = 10; 396503a7782SBrian Somers 397503a7782SBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 398503a7782SBrian Somers if (ipcp->my_ifip.s_addr != INADDR_ANY && 399503a7782SBrian Somers (pos = iplist_ip2pos(&ipcp->cfg.peer_list, ipcp->my_ifip)) != -1) 400503a7782SBrian Somers ipcp->cfg.peer_range.ipaddr = iplist_setcurpos(&ipcp->cfg.peer_list, pos); 401503a7782SBrian Somers else 402503a7782SBrian Somers ipcp->cfg.peer_range.ipaddr = iplist_setrandpos(&ipcp->cfg.peer_list); 403503a7782SBrian Somers ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 404503a7782SBrian Somers ipcp->cfg.peer_range.width = 32; 405503a7782SBrian Somers } 406503a7782SBrian Somers 407503a7782SBrian Somers ipcp->heis1172 = 0; 408503a7782SBrian Somers 409503a7782SBrian Somers ipcp->peer_ip = ipcp->cfg.peer_range.ipaddr; 410503a7782SBrian Somers ipcp->peer_compproto = 0; 4111ae349f5Scvs2svn 4128390b576SBrian Somers if (ipcp->cfg.HaveTriggerAddress) { 413549d663dSAtsushi Murai /* 4145b4c5b00SBrian Somers * Some implementations of PPP require that we send a 4155b4c5b00SBrian Somers * *special* value as our address, even though the rfc specifies 4165b4c5b00SBrian Somers * full negotiation (e.g. "0.0.0.0" or Not "0.0.0.0"). 417549d663dSAtsushi Murai */ 418503a7782SBrian Somers ipcp->my_ip = ipcp->cfg.TriggerAddress; 419dd7e2610SBrian Somers log_Printf(LogIPCP, "Using trigger address %s\n", 420503a7782SBrian Somers inet_ntoa(ipcp->cfg.TriggerAddress)); 4218390b576SBrian Somers } else if ((ipcp->my_ifip.s_addr & ipcp->cfg.my_range.mask.s_addr) == 4228390b576SBrian Somers (ipcp->cfg.my_range.ipaddr.s_addr & 4238390b576SBrian Somers ipcp->cfg.my_range.mask.s_addr)) 4248390b576SBrian Somers /* 4258390b576SBrian Somers * Otherwise, if we've been assigned an IP number before, we really 4268390b576SBrian Somers * want to keep the same IP number so that we can keep any existing 4278390b576SBrian Somers * connections that are bound to that IP. 4288390b576SBrian Somers */ 4298390b576SBrian Somers ipcp->my_ip = ipcp->my_ifip; 430af57ed9fSAtsushi Murai else 431503a7782SBrian Somers ipcp->my_ip = ipcp->cfg.my_range.ipaddr; 43229e275ceSBrian Somers 4331342caedSBrian Somers if (IsEnabled(ipcp->cfg.vj.neg)) 434503a7782SBrian Somers ipcp->my_compproto = (PROTO_VJCOMP << 16) + 4351342caedSBrian Somers ((ipcp->cfg.vj.slots - 1) << 8) + 4361342caedSBrian Somers ipcp->cfg.vj.slotcomp; 4371ae349f5Scvs2svn else 438503a7782SBrian Somers ipcp->my_compproto = 0; 4391342caedSBrian Somers sl_compress_init(&ipcp->vj.cslc, ipcp->cfg.vj.slots - 1); 44029e275ceSBrian Somers 441503a7782SBrian Somers ipcp->peer_reject = 0; 442503a7782SBrian Somers ipcp->my_reject = 0; 4431ae349f5Scvs2svn } 4441ae349f5Scvs2svn 445455aabc3SBrian Somers static int 44630c2f2ffSBrian Somers ipcp_SetIPaddress(struct bundle *bundle, struct in_addr myaddr, 44730c2f2ffSBrian Somers struct in_addr hisaddr, int silent) 448455aabc3SBrian Somers { 449455aabc3SBrian Somers struct sockaddr_in *sock_in; 450455aabc3SBrian Somers int s; 4512d42ffabSBrian Somers u_int32_t mask, addr; 452455aabc3SBrian Somers struct ifaliasreq ifra; 453455aabc3SBrian Somers 454455aabc3SBrian Somers /* If given addresses are alreay set, then ignore this request */ 45530c2f2ffSBrian Somers if (bundle->ncp.ipcp.my_ifip.s_addr == myaddr.s_addr && 45630c2f2ffSBrian Somers bundle->ncp.ipcp.peer_ifip.s_addr == hisaddr.s_addr) 457455aabc3SBrian Somers return 0; 458455aabc3SBrian Somers 459dd7e2610SBrian Somers ipcp_CleanInterface(&bundle->ncp.ipcp); 46068a0f0ccSBrian Somers 461455aabc3SBrian Somers s = ID0socket(AF_INET, SOCK_DGRAM, 0); 462455aabc3SBrian Somers if (s < 0) { 463a33b2ef7SBrian Somers log_Printf(LogERROR, "SetIPaddress: socket(): %s\n", strerror(errno)); 464455aabc3SBrian Somers return (-1); 465455aabc3SBrian Somers } 466455aabc3SBrian Somers 467455aabc3SBrian Somers memset(&ifra, '\0', sizeof ifra); 468faefde08SBrian Somers strncpy(ifra.ifra_name, bundle->ifp.Name, sizeof ifra.ifra_name - 1); 469455aabc3SBrian Somers ifra.ifra_name[sizeof ifra.ifra_name - 1] = '\0'; 470455aabc3SBrian Somers 471455aabc3SBrian Somers /* Set interface address */ 472455aabc3SBrian Somers sock_in = (struct sockaddr_in *)&ifra.ifra_addr; 473455aabc3SBrian Somers sock_in->sin_family = AF_INET; 474455aabc3SBrian Somers sock_in->sin_addr = myaddr; 475455aabc3SBrian Somers sock_in->sin_len = sizeof *sock_in; 476455aabc3SBrian Somers 477455aabc3SBrian Somers /* Set destination address */ 478455aabc3SBrian Somers sock_in = (struct sockaddr_in *)&ifra.ifra_broadaddr; 479455aabc3SBrian Somers sock_in->sin_family = AF_INET; 480455aabc3SBrian Somers sock_in->sin_addr = hisaddr; 481455aabc3SBrian Somers sock_in->sin_len = sizeof *sock_in; 482455aabc3SBrian Somers 483455aabc3SBrian Somers addr = ntohl(myaddr.s_addr); 484455aabc3SBrian Somers if (IN_CLASSA(addr)) 485455aabc3SBrian Somers mask = IN_CLASSA_NET; 486455aabc3SBrian Somers else if (IN_CLASSB(addr)) 487455aabc3SBrian Somers mask = IN_CLASSB_NET; 488455aabc3SBrian Somers else 489455aabc3SBrian Somers mask = IN_CLASSC_NET; 490455aabc3SBrian Somers 491455aabc3SBrian Somers /* if subnet mask is given, use it instead of class mask */ 49230c2f2ffSBrian Somers if (bundle->ncp.ipcp.cfg.netmask.s_addr != INADDR_ANY && 49330c2f2ffSBrian Somers (ntohl(bundle->ncp.ipcp.cfg.netmask.s_addr) & mask) == mask) 49430c2f2ffSBrian Somers mask = ntohl(bundle->ncp.ipcp.cfg.netmask.s_addr); 495455aabc3SBrian Somers 496455aabc3SBrian Somers sock_in = (struct sockaddr_in *)&ifra.ifra_mask; 497455aabc3SBrian Somers sock_in->sin_family = AF_INET; 498455aabc3SBrian Somers sock_in->sin_addr.s_addr = htonl(mask); 499455aabc3SBrian Somers sock_in->sin_len = sizeof *sock_in; 500455aabc3SBrian Somers 501455aabc3SBrian Somers if (ID0ioctl(s, SIOCAIFADDR, &ifra) < 0) { 502455aabc3SBrian Somers if (!silent) 503a33b2ef7SBrian Somers log_Printf(LogERROR, "SetIPaddress: ioctl(SIOCAIFADDR): %s\n", 504455aabc3SBrian Somers strerror(errno)); 505455aabc3SBrian Somers close(s); 506455aabc3SBrian Somers return (-1); 507455aabc3SBrian Somers } 508455aabc3SBrian Somers 509610b185fSBrian Somers if (Enabled(bundle, OPT_SROUTES)) 510610b185fSBrian Somers route_Change(bundle, bundle->ncp.ipcp.route, myaddr, hisaddr); 511610b185fSBrian Somers 51230c2f2ffSBrian Somers bundle->ncp.ipcp.peer_ifip.s_addr = hisaddr.s_addr; 51330c2f2ffSBrian Somers bundle->ncp.ipcp.my_ifip.s_addr = myaddr.s_addr; 514455aabc3SBrian Somers 5151342caedSBrian Somers if (Enabled(bundle, OPT_PROXY)) 516dd7e2610SBrian Somers arp_SetProxy(bundle, bundle->ncp.ipcp.peer_ifip, s); 517455aabc3SBrian Somers 518455aabc3SBrian Somers close(s); 519455aabc3SBrian Somers return (0); 520455aabc3SBrian Somers } 521455aabc3SBrian Somers 522455aabc3SBrian Somers static struct in_addr 52330c2f2ffSBrian Somers ChooseHisAddr(struct bundle *bundle, const struct in_addr gw) 524455aabc3SBrian Somers { 525455aabc3SBrian Somers struct in_addr try; 5263a2e4f62SBrian Somers u_long f; 527455aabc3SBrian Somers 5285828db6dSBrian Somers for (f = 0; f < bundle->ncp.ipcp.cfg.peer_list.nItems; f++) { 5295828db6dSBrian Somers try = iplist_next(&bundle->ncp.ipcp.cfg.peer_list); 5303a2e4f62SBrian Somers log_Printf(LogDEBUG, "ChooseHisAddr: Check item %ld (%s)\n", 531455aabc3SBrian Somers f, inet_ntoa(try)); 53230c2f2ffSBrian Somers if (ipcp_SetIPaddress(bundle, gw, try, 1) == 0) { 533dd7e2610SBrian Somers log_Printf(LogIPCP, "Selected IP address %s\n", inet_ntoa(try)); 534455aabc3SBrian Somers break; 535455aabc3SBrian Somers } 536455aabc3SBrian Somers } 537455aabc3SBrian Somers 5385828db6dSBrian Somers if (f == bundle->ncp.ipcp.cfg.peer_list.nItems) { 539dd7e2610SBrian Somers log_Printf(LogDEBUG, "ChooseHisAddr: All addresses in use !\n"); 540455aabc3SBrian Somers try.s_addr = INADDR_ANY; 541455aabc3SBrian Somers } 542455aabc3SBrian Somers 543455aabc3SBrian Somers return try; 544af57ed9fSAtsushi Murai } 545af57ed9fSAtsushi Murai 546af57ed9fSAtsushi Murai static void 547944f7098SBrian Somers IpcpInitRestartCounter(struct fsm * fp) 548af57ed9fSAtsushi Murai { 5497308ec68SBrian Somers /* Set fsm timer load */ 550cd9647a1SBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 551cd9647a1SBrian Somers 552cd9647a1SBrian Somers fp->FsmTimer.load = ipcp->cfg.fsmretry * SECTICKS; 55392b09558SBrian Somers fp->restart = DEF_REQs; 554af57ed9fSAtsushi Murai } 555af57ed9fSAtsushi Murai 556af57ed9fSAtsushi Murai static void 557944f7098SBrian Somers IpcpSendConfigReq(struct fsm *fp) 558af57ed9fSAtsushi Murai { 5597308ec68SBrian Somers /* Send config REQ please */ 5608c07a7b2SBrian Somers struct physical *p = link2physical(fp->link); 561aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 5623edeb0c6SBrian Somers u_char buff[24]; 5632267893fSBrian Somers struct lcp_opt *o; 564af57ed9fSAtsushi Murai 5652267893fSBrian Somers o = (struct lcp_opt *)buff; 56630c2f2ffSBrian Somers 567dd7e2610SBrian Somers if ((p && !physical_IsSync(p)) || !REJECTED(ipcp, TY_IPADDR)) { 5689e8ec64bSBrian Somers memcpy(o->data, &ipcp->my_ip.s_addr, 4); 5692267893fSBrian Somers INC_LCP_OPT(TY_IPADDR, 6, o); 5700053cc58SBrian Somers } 5710053cc58SBrian Somers 572e43ebac1SBrian Somers if (ipcp->my_compproto && !REJECTED(ipcp, TY_COMPPROTO)) { 57383d1af55SBrian Somers if (ipcp->heis1172) { 5749e8ec64bSBrian Somers u_int16_t proto = PROTO_VJCOMP; 5759e8ec64bSBrian Somers 5769e8ec64bSBrian Somers ua_htons(&proto, o->data); 5772267893fSBrian Somers INC_LCP_OPT(TY_COMPPROTO, 4, o); 5780053cc58SBrian Somers } else { 5799e8ec64bSBrian Somers ua_htonl(&ipcp->my_compproto, o->data); 5802267893fSBrian Somers INC_LCP_OPT(TY_COMPPROTO, 6, o); 5810053cc58SBrian Somers } 582af57ed9fSAtsushi Murai } 5832267893fSBrian Somers 5843edeb0c6SBrian Somers if (IsEnabled(ipcp->cfg.ns.dns_neg) && 5853edeb0c6SBrian Somers !REJECTED(ipcp, TY_PRIMARY_DNS - TY_ADJUST_NS) && 5863edeb0c6SBrian Somers !REJECTED(ipcp, TY_SECONDARY_DNS - TY_ADJUST_NS)) { 5873edeb0c6SBrian Somers struct in_addr dns[2]; 5883edeb0c6SBrian Somers getdns(ipcp, dns); 5899e8ec64bSBrian Somers memcpy(o->data, &dns[0].s_addr, 4); 5903edeb0c6SBrian Somers INC_LCP_OPT(TY_PRIMARY_DNS, 6, o); 5919e8ec64bSBrian Somers memcpy(o->data, &dns[1].s_addr, 4); 5923edeb0c6SBrian Somers INC_LCP_OPT(TY_SECONDARY_DNS, 6, o); 5933edeb0c6SBrian Somers } 5943edeb0c6SBrian Somers 595dd7e2610SBrian Somers fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff); 596af57ed9fSAtsushi Murai } 597af57ed9fSAtsushi Murai 598af57ed9fSAtsushi Murai static void 5992267893fSBrian Somers IpcpSentTerminateReq(struct fsm * fp) 600af57ed9fSAtsushi Murai { 6017308ec68SBrian Somers /* Term REQ just sent by FSM */ 602af57ed9fSAtsushi Murai } 603af57ed9fSAtsushi Murai 604af57ed9fSAtsushi Murai static void 6052267893fSBrian Somers IpcpSendTerminateAck(struct fsm *fp, u_char id) 606af57ed9fSAtsushi Murai { 6077308ec68SBrian Somers /* Send Term ACK please */ 608dd7e2610SBrian Somers fsm_Output(fp, CODE_TERMACK, id, NULL, 0); 609af57ed9fSAtsushi Murai } 610af57ed9fSAtsushi Murai 611af57ed9fSAtsushi Murai static void 612944f7098SBrian Somers IpcpLayerStart(struct fsm *fp) 613af57ed9fSAtsushi Murai { 6147308ec68SBrian Somers /* We're about to start up ! */ 615897f9429SBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 616897f9429SBrian Somers 6173a2e4f62SBrian Somers log_Printf(LogIPCP, "%s: LayerStart.\n", fp->link->name); 618897f9429SBrian Somers throughput_start(&ipcp->throughput, "IPCP throughput", 619897f9429SBrian Somers Enabled(fp->bundle, OPT_THROUGHPUT)); 620455aabc3SBrian Somers 62181358fa3SBrian Somers /* This is where we should be setting up the interface in AUTO mode */ 622af57ed9fSAtsushi Murai } 623af57ed9fSAtsushi Murai 624af57ed9fSAtsushi Murai static void 625944f7098SBrian Somers IpcpLayerFinish(struct fsm *fp) 626af57ed9fSAtsushi Murai { 6277308ec68SBrian Somers /* We're now down */ 628897f9429SBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 629897f9429SBrian Somers 6303a2e4f62SBrian Somers log_Printf(LogIPCP, "%s: LayerFinish.\n", fp->link->name); 631897f9429SBrian Somers throughput_stop(&ipcp->throughput); 632897f9429SBrian Somers throughput_log(&ipcp->throughput, LogIPCP, NULL); 6331ae349f5Scvs2svn } 6341ae349f5Scvs2svn 63568a0f0ccSBrian Somers void 636dd7e2610SBrian Somers ipcp_CleanInterface(struct ipcp *ipcp) 63768a0f0ccSBrian Somers { 63868a0f0ccSBrian Somers struct ifaliasreq ifra; 63968a0f0ccSBrian Somers struct sockaddr_in *me, *peer; 64068a0f0ccSBrian Somers int s; 64168a0f0ccSBrian Somers 64268a0f0ccSBrian Somers s = ID0socket(AF_INET, SOCK_DGRAM, 0); 64368a0f0ccSBrian Somers if (s < 0) { 644dd7e2610SBrian Somers log_Printf(LogERROR, "ipcp_CleanInterface: socket: %s\n", strerror(errno)); 64568a0f0ccSBrian Somers return; 64668a0f0ccSBrian Somers } 64768a0f0ccSBrian Somers 648610b185fSBrian Somers route_Clean(ipcp->fsm.bundle, ipcp->route); 649610b185fSBrian Somers 6501342caedSBrian Somers if (Enabled(ipcp->fsm.bundle, OPT_PROXY)) 651dd7e2610SBrian Somers arp_ClearProxy(ipcp->fsm.bundle, ipcp->peer_ifip, s); 65268a0f0ccSBrian Somers 653503a7782SBrian Somers if (ipcp->my_ifip.s_addr != INADDR_ANY || 654503a7782SBrian Somers ipcp->peer_ifip.s_addr != INADDR_ANY) { 65568a0f0ccSBrian Somers memset(&ifra, '\0', sizeof ifra); 656faefde08SBrian Somers strncpy(ifra.ifra_name, ipcp->fsm.bundle->ifp.Name, 657565e35e5SBrian Somers sizeof ifra.ifra_name - 1); 65868a0f0ccSBrian Somers ifra.ifra_name[sizeof ifra.ifra_name - 1] = '\0'; 65968a0f0ccSBrian Somers me = (struct sockaddr_in *)&ifra.ifra_addr; 66068a0f0ccSBrian Somers peer = (struct sockaddr_in *)&ifra.ifra_broadaddr; 66168a0f0ccSBrian Somers me->sin_family = peer->sin_family = AF_INET; 66268a0f0ccSBrian Somers me->sin_len = peer->sin_len = sizeof(struct sockaddr_in); 663503a7782SBrian Somers me->sin_addr = ipcp->my_ifip; 664503a7782SBrian Somers peer->sin_addr = ipcp->peer_ifip; 6650f8037a9SBrian Somers if (ID0ioctl(s, SIOCDIFADDR, &ifra) < 0) 666dd7e2610SBrian Somers log_Printf(LogERROR, "ipcp_CleanInterface: ioctl(SIOCDIFADDR): %s\n", 66768a0f0ccSBrian Somers strerror(errno)); 668503a7782SBrian Somers ipcp->my_ifip.s_addr = ipcp->peer_ifip.s_addr = INADDR_ANY; 66968a0f0ccSBrian Somers } 67068a0f0ccSBrian Somers 67168a0f0ccSBrian Somers close(s); 672af57ed9fSAtsushi Murai } 673af57ed9fSAtsushi Murai 674af57ed9fSAtsushi Murai static void 675944f7098SBrian Somers IpcpLayerDown(struct fsm *fp) 676af57ed9fSAtsushi Murai { 6777308ec68SBrian Somers /* About to come down */ 678aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 679455aabc3SBrian Somers const char *s; 680455aabc3SBrian Somers 681503a7782SBrian Somers s = inet_ntoa(ipcp->peer_ifip); 6823a2e4f62SBrian Somers log_Printf(LogIPCP, "%s: LayerDown: %s\n", fp->link->name, s); 683455aabc3SBrian Somers 684455aabc3SBrian Somers /* 685455aabc3SBrian Somers * XXX this stuff should really live in the FSM. Our config should 686455aabc3SBrian Somers * associate executable sections in files with events. 687455aabc3SBrian Somers */ 68830291ffbSBrian Somers if (system_Select(fp->bundle, s, LINKDOWNFILE, NULL, NULL) < 0) { 68949052c95SBrian Somers if (bundle_GetLabel(fp->bundle)) { 690dd7e2610SBrian Somers if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle), 69130291ffbSBrian Somers LINKDOWNFILE, NULL, NULL) < 0) 69230291ffbSBrian Somers system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL); 693455aabc3SBrian Somers } else 69430291ffbSBrian Somers system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL); 695af57ed9fSAtsushi Murai } 696af57ed9fSAtsushi Murai 697ff0f9439SBrian Somers if (!(ipcp->fsm.bundle->phys_type.all & PHYS_AUTO)) 698dd7e2610SBrian Somers ipcp_CleanInterface(ipcp); 699897f9429SBrian Somers 700897f9429SBrian Somers ipcp_Setup(ipcp); 7011ae349f5Scvs2svn } 7021ae349f5Scvs2svn 703dd0645c5SBrian Somers int 704dd0645c5SBrian Somers ipcp_InterfaceUp(struct ipcp *ipcp) 705dd0645c5SBrian Somers { 706dd0645c5SBrian Somers if (ipcp_SetIPaddress(ipcp->fsm.bundle, ipcp->my_ip, ipcp->peer_ip, 0) < 0) { 707a33b2ef7SBrian Somers log_Printf(LogERROR, "ipcp_InterfaceUp: unable to set ip address\n"); 708dd0645c5SBrian Somers return 0; 709dd0645c5SBrian Somers } 710dd0645c5SBrian Somers 711dd0645c5SBrian Somers #ifndef NOALIAS 712615ad4f9SBrian Somers if (ipcp->fsm.bundle->AliasEnabled) 713615ad4f9SBrian Somers PacketAliasSetAddress(ipcp->my_ip); 714dd0645c5SBrian Somers #endif 715dd0645c5SBrian Somers 716dd0645c5SBrian Somers return 1; 717dd0645c5SBrian Somers } 718dd0645c5SBrian Somers 7196f384573SBrian Somers static int 720944f7098SBrian Somers IpcpLayerUp(struct fsm *fp) 721af57ed9fSAtsushi Murai { 7227308ec68SBrian Somers /* We're now up */ 723aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 724af57ed9fSAtsushi Murai char tbuff[100]; 725af57ed9fSAtsushi Murai 7263a2e4f62SBrian Somers log_Printf(LogIPCP, "%s: LayerUp.\n", fp->link->name); 727503a7782SBrian Somers snprintf(tbuff, sizeof tbuff, "myaddr = %s ", inet_ntoa(ipcp->my_ip)); 728dd7e2610SBrian Somers log_Printf(LogIPCP, " %s hisaddr = %s\n", tbuff, inet_ntoa(ipcp->peer_ip)); 72903604f35SBrian Somers 730503a7782SBrian Somers if (ipcp->peer_compproto >> 16 == PROTO_VJCOMP) 731eaa4df37SBrian Somers sl_compress_init(&ipcp->vj.cslc, (ipcp->peer_compproto >> 8) & 255); 73203604f35SBrian Somers 733dd0645c5SBrian Somers if (!ipcp_InterfaceUp(ipcp)) 7346f384573SBrian Somers return 0; 735455aabc3SBrian Somers 736455aabc3SBrian Somers /* 737455aabc3SBrian Somers * XXX this stuff should really live in the FSM. Our config should 738455aabc3SBrian Somers * associate executable sections in files with events. 739455aabc3SBrian Somers */ 74030291ffbSBrian Somers if (system_Select(fp->bundle, inet_ntoa(ipcp->my_ifip), LINKUPFILE, 74130291ffbSBrian Somers NULL, NULL) < 0) { 74249052c95SBrian Somers if (bundle_GetLabel(fp->bundle)) { 743dd7e2610SBrian Somers if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle), 74430291ffbSBrian Somers LINKUPFILE, NULL, NULL) < 0) 74530291ffbSBrian Somers system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL); 746455aabc3SBrian Somers } else 74730291ffbSBrian Somers system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL); 748af57ed9fSAtsushi Murai } 749af57ed9fSAtsushi Murai 7500f2f3eb3SBrian Somers log_DisplayPrompts(); 7516f384573SBrian Somers return 1; 752af57ed9fSAtsushi Murai } 753af57ed9fSAtsushi Murai 754af57ed9fSAtsushi Murai static int 755944f7098SBrian Somers AcceptableAddr(struct in_range *prange, struct in_addr ipaddr) 756af57ed9fSAtsushi Murai { 7577308ec68SBrian Somers /* Is the given IP in the given range ? */ 758057df964SBrian Somers return (prange->ipaddr.s_addr & prange->mask.s_addr) == 759057df964SBrian Somers (ipaddr.s_addr & prange->mask.s_addr) && ipaddr.s_addr; 760af57ed9fSAtsushi Murai } 761af57ed9fSAtsushi Murai 762af57ed9fSAtsushi Murai static void 76330c2f2ffSBrian Somers IpcpDecodeConfig(struct fsm *fp, u_char * cp, int plen, int mode_type, 76430c2f2ffSBrian Somers struct fsm_decode *dec) 765af57ed9fSAtsushi Murai { 7667308ec68SBrian Somers /* Deal with incoming PROTO_IPCP */ 767aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 76853c9f6c0SAtsushi Murai int type, length; 769fe3125a0SBrian Somers u_int32_t compproto; 770af57ed9fSAtsushi Murai struct compreq *pcomp; 7713edeb0c6SBrian Somers struct in_addr ipaddr, dstipaddr, have_ip, dns[2], dnsnak[2]; 77230c2f2ffSBrian Somers char tbuff[100], tbuff2[100]; 7733edeb0c6SBrian Somers int gotdns, gotdnsnak; 774af57ed9fSAtsushi Murai 7753edeb0c6SBrian Somers gotdns = 0; 7763edeb0c6SBrian Somers gotdnsnak = 0; 7773edeb0c6SBrian Somers dnsnak[0].s_addr = dnsnak[1].s_addr = INADDR_ANY; 778af57ed9fSAtsushi Murai 779af57ed9fSAtsushi Murai while (plen >= sizeof(struct fsmconfig)) { 780af57ed9fSAtsushi Murai type = *cp; 781af57ed9fSAtsushi Murai length = cp[1]; 782d47dceb8SBrian Somers 783d47dceb8SBrian Somers if (length == 0) { 784dd7e2610SBrian Somers log_Printf(LogIPCP, "%s: IPCP size zero\n", fp->link->name); 785d47dceb8SBrian Somers break; 786d47dceb8SBrian Somers } 787d47dceb8SBrian Somers 7889e836af5SBrian Somers if (type < NCFTYPES) 78970ee81ffSBrian Somers snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes[type], length); 7909e836af5SBrian Somers else if (type > 128 && type < 128 + NCFTYPES128) 79170ee81ffSBrian Somers snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes128[type-128], length); 792af57ed9fSAtsushi Murai else 79370ee81ffSBrian Somers snprintf(tbuff, sizeof tbuff, " <%d>[%d] ", type, length); 794af57ed9fSAtsushi Murai 795af57ed9fSAtsushi Murai switch (type) { 796af57ed9fSAtsushi Murai case TY_IPADDR: /* RFC1332 */ 7979e8ec64bSBrian Somers memcpy(&ipaddr.s_addr, cp + 2, 4); 798dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 799af57ed9fSAtsushi Murai 8009780ef31SBrian Somers switch (mode_type) { 801af57ed9fSAtsushi Murai case MODE_REQ: 802503a7782SBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 803f5fb6bd0SBrian Somers if (ipaddr.s_addr == INADDR_ANY || 804503a7782SBrian Somers iplist_ip2pos(&ipcp->cfg.peer_list, ipaddr) < 0 || 80530c2f2ffSBrian Somers ipcp_SetIPaddress(fp->bundle, ipcp->cfg.my_range.ipaddr, 80630c2f2ffSBrian Somers ipaddr, 1)) { 807dd7e2610SBrian Somers log_Printf(LogIPCP, "%s: Address invalid or already in use\n", 808bcc332bdSBrian Somers inet_ntoa(ipaddr)); 8098390b576SBrian Somers if (iplist_ip2pos(&ipcp->cfg.peer_list, ipcp->peer_ifip) >= 0) 8108390b576SBrian Somers /* 8118390b576SBrian Somers * If we've already got a valid address configured for the peer 81281358fa3SBrian Somers * (in AUTO mode), try NAKing with that so that we don't 8138390b576SBrian Somers * have to upset things too much. 8148390b576SBrian Somers */ 8158390b576SBrian Somers ipcp->peer_ip = ipcp->peer_ifip; 8168390b576SBrian Somers else 8178390b576SBrian Somers /* Just pick an IP number from our list */ 818503a7782SBrian Somers ipcp->peer_ip = ChooseHisAddr 81930c2f2ffSBrian Somers (fp->bundle, ipcp->cfg.my_range.ipaddr); 8208390b576SBrian Somers 821503a7782SBrian Somers if (ipcp->peer_ip.s_addr == INADDR_ANY) { 82230c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 82330c2f2ffSBrian Somers dec->rejend += length; 824bcc332bdSBrian Somers } else { 82530c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 82630c2f2ffSBrian Somers memcpy(dec->nakend+2, &ipcp->peer_ip.s_addr, length - 2); 82730c2f2ffSBrian Somers dec->nakend += length; 828bcc332bdSBrian Somers } 829bcc332bdSBrian Somers break; 830bcc332bdSBrian Somers } 831503a7782SBrian Somers } else if (!AcceptableAddr(&ipcp->cfg.peer_range, ipaddr)) { 832af57ed9fSAtsushi Murai /* 8338390b576SBrian Somers * If destination address is not acceptable, NAK with what we 834944f7098SBrian Somers * want to use. 835af57ed9fSAtsushi Murai */ 83630c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 8378390b576SBrian Somers if ((ipcp->peer_ifip.s_addr & ipcp->cfg.peer_range.mask.s_addr) == 8388390b576SBrian Somers (ipcp->cfg.peer_range.ipaddr.s_addr & 8398390b576SBrian Somers ipcp->cfg.peer_range.mask.s_addr)) 8408390b576SBrian Somers /* We prefer the already-configured address */ 8418390b576SBrian Somers memcpy(dec->nakend+2, &ipcp->peer_ifip.s_addr, length - 2); 8428390b576SBrian Somers else 84330c2f2ffSBrian Somers memcpy(dec->nakend+2, &ipcp->peer_ip.s_addr, length - 2); 84430c2f2ffSBrian Somers dec->nakend += length; 845af57ed9fSAtsushi Murai break; 846af57ed9fSAtsushi Murai } 847503a7782SBrian Somers ipcp->peer_ip = ipaddr; 84830c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 84930c2f2ffSBrian Somers dec->ackend += length; 850af57ed9fSAtsushi Murai break; 851af57ed9fSAtsushi Murai case MODE_NAK: 852503a7782SBrian Somers if (AcceptableAddr(&ipcp->cfg.my_range, ipaddr)) { 853bcc332bdSBrian Somers /* Use address suggested by peer */ 85470ee81ffSBrian Somers snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s ", tbuff, 855503a7782SBrian Somers inet_ntoa(ipcp->my_ip)); 856dd7e2610SBrian Somers log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 857503a7782SBrian Somers ipcp->my_ip = ipaddr; 858bcc332bdSBrian Somers } else { 859dd7e2610SBrian Somers log_Printf(log_IsKept(LogIPCP) ? LogIPCP : LogPHASE, 8608390b576SBrian Somers "%s: Unacceptable address!\n", inet_ntoa(ipaddr)); 861dd7e2610SBrian Somers fsm_Close(&ipcp->fsm); 862af57ed9fSAtsushi Murai } 863af57ed9fSAtsushi Murai break; 864af57ed9fSAtsushi Murai case MODE_REJ: 865503a7782SBrian Somers ipcp->peer_reject |= (1 << type); 866af57ed9fSAtsushi Murai break; 867af57ed9fSAtsushi Murai } 868af57ed9fSAtsushi Murai break; 869af57ed9fSAtsushi Murai case TY_COMPPROTO: 8709e8ec64bSBrian Somers memcpy(&compproto, cp + 2, 4); 871dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto)); 872af57ed9fSAtsushi Murai 8739780ef31SBrian Somers switch (mode_type) { 874af57ed9fSAtsushi Murai case MODE_REQ: 8751342caedSBrian Somers if (!IsAccepted(ipcp->cfg.vj.neg)) { 87630c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 87730c2f2ffSBrian Somers dec->rejend += length; 878af57ed9fSAtsushi Murai } else { 879af57ed9fSAtsushi Murai pcomp = (struct compreq *) (cp + 2); 880af57ed9fSAtsushi Murai switch (length) { 881af57ed9fSAtsushi Murai case 4: /* RFC1172 */ 882af57ed9fSAtsushi Murai if (ntohs(pcomp->proto) == PROTO_VJCOMP) { 883dd7e2610SBrian Somers log_Printf(LogWARN, "Peer is speaking RFC1172 compression protocol !\n"); 88483d1af55SBrian Somers ipcp->heis1172 = 1; 885503a7782SBrian Somers ipcp->peer_compproto = compproto; 88630c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 88730c2f2ffSBrian Somers dec->ackend += length; 888af57ed9fSAtsushi Murai } else { 88930c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 890af57ed9fSAtsushi Murai pcomp->proto = htons(PROTO_VJCOMP); 89130c2f2ffSBrian Somers memcpy(dec->nakend+2, &pcomp, 2); 89230c2f2ffSBrian Somers dec->nakend += length; 893af57ed9fSAtsushi Murai } 894af57ed9fSAtsushi Murai break; 895af57ed9fSAtsushi Murai case 6: /* RFC1332 */ 896af57ed9fSAtsushi Murai if (ntohs(pcomp->proto) == PROTO_VJCOMP 897503a7782SBrian Somers && pcomp->slots <= MAX_VJ_STATES 898503a7782SBrian Somers && pcomp->slots >= MIN_VJ_STATES) { 899503a7782SBrian Somers ipcp->peer_compproto = compproto; 90083d1af55SBrian Somers ipcp->heis1172 = 0; 90130c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 90230c2f2ffSBrian Somers dec->ackend += length; 903af57ed9fSAtsushi Murai } else { 90430c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 905af57ed9fSAtsushi Murai pcomp->proto = htons(PROTO_VJCOMP); 906503a7782SBrian Somers pcomp->slots = DEF_VJ_STATES; 907af57ed9fSAtsushi Murai pcomp->compcid = 0; 90830c2f2ffSBrian Somers memcpy(dec->nakend+2, &pcomp, sizeof pcomp); 90930c2f2ffSBrian Somers dec->nakend += length; 910af57ed9fSAtsushi Murai } 911af57ed9fSAtsushi Murai break; 912af57ed9fSAtsushi Murai default: 91330c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 91430c2f2ffSBrian Somers dec->rejend += length; 915af57ed9fSAtsushi Murai break; 916af57ed9fSAtsushi Murai } 917af57ed9fSAtsushi Murai } 918af57ed9fSAtsushi Murai break; 919af57ed9fSAtsushi Murai case MODE_NAK: 920dd7e2610SBrian Somers log_Printf(LogIPCP, "%s changing compproto: %08x --> %08x\n", 921503a7782SBrian Somers tbuff, ipcp->my_compproto, compproto); 922503a7782SBrian Somers ipcp->my_compproto = compproto; 923af57ed9fSAtsushi Murai break; 924af57ed9fSAtsushi Murai case MODE_REJ: 925503a7782SBrian Somers ipcp->peer_reject |= (1 << type); 926af57ed9fSAtsushi Murai break; 927af57ed9fSAtsushi Murai } 928af57ed9fSAtsushi Murai break; 929af57ed9fSAtsushi Murai case TY_IPADDRS: /* RFC1172 */ 9309e8ec64bSBrian Somers memcpy(&ipaddr.s_addr, cp + 2, 4); 9319e8ec64bSBrian Somers memcpy(&dstipaddr.s_addr, cp + 6, 4); 93270ee81ffSBrian Somers snprintf(tbuff2, sizeof tbuff2, "%s %s,", tbuff, inet_ntoa(ipaddr)); 933dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr)); 934af57ed9fSAtsushi Murai 9359780ef31SBrian Somers switch (mode_type) { 936af57ed9fSAtsushi Murai case MODE_REQ: 937503a7782SBrian Somers ipcp->peer_ip = ipaddr; 938503a7782SBrian Somers ipcp->my_ip = dstipaddr; 93930c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 94030c2f2ffSBrian Somers dec->ackend += length; 941af57ed9fSAtsushi Murai break; 942af57ed9fSAtsushi Murai case MODE_NAK: 94370ee81ffSBrian Somers snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s", tbuff, 944503a7782SBrian Somers inet_ntoa(ipcp->my_ip)); 945dd7e2610SBrian Somers log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 946503a7782SBrian Somers ipcp->my_ip = ipaddr; 947503a7782SBrian Somers ipcp->peer_ip = dstipaddr; 948af57ed9fSAtsushi Murai break; 949af57ed9fSAtsushi Murai case MODE_REJ: 950503a7782SBrian Somers ipcp->peer_reject |= (1 << type); 951af57ed9fSAtsushi Murai break; 952af57ed9fSAtsushi Murai } 953af57ed9fSAtsushi Murai break; 954d8e55738SJordan K. Hubbard 9553edeb0c6SBrian Somers case TY_PRIMARY_DNS: /* DNS negotiation (rfc1877) */ 956d8e55738SJordan K. Hubbard case TY_SECONDARY_DNS: 9579e8ec64bSBrian Somers memcpy(&ipaddr.s_addr, cp + 2, 4); 958dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 9593edeb0c6SBrian Somers 9609780ef31SBrian Somers switch (mode_type) { 961d8e55738SJordan K. Hubbard case MODE_REQ: 9623edeb0c6SBrian Somers if (!IsAccepted(ipcp->cfg.ns.dns_neg)) { 9633edeb0c6SBrian Somers ipcp->my_reject |= (1 << (type - TY_ADJUST_NS)); 96430c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 96530c2f2ffSBrian Somers dec->rejend += length; 966d8e55738SJordan K. Hubbard break; 967d8e55738SJordan K. Hubbard } 9683edeb0c6SBrian Somers if (!gotdns) { 9693edeb0c6SBrian Somers dns[0] = ipcp->cfg.ns.dns[0]; 9703edeb0c6SBrian Somers dns[1] = ipcp->cfg.ns.dns[1]; 9713edeb0c6SBrian Somers if (dns[0].s_addr == INADDR_ANY && dns[1].s_addr == INADDR_ANY) 9723edeb0c6SBrian Somers getdns(ipcp, dns); 9733edeb0c6SBrian Somers gotdns = 1; 9743edeb0c6SBrian Somers } 9753edeb0c6SBrian Somers have_ip = dns[type == TY_PRIMARY_DNS ? 0 : 1]; 976944f7098SBrian Somers 9773edeb0c6SBrian Somers if (ipaddr.s_addr != have_ip.s_addr) { 9781ae349f5Scvs2svn /* 9793edeb0c6SBrian Somers * The client has got the DNS stuff wrong (first request) so 9801ae349f5Scvs2svn * we'll tell 'em how it is 9811ae349f5Scvs2svn */ 98230c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); /* copy first two (type/length) */ 9833edeb0c6SBrian Somers memcpy(dec->nakend + 2, &have_ip.s_addr, length - 2); 98430c2f2ffSBrian Somers dec->nakend += length; 9853edeb0c6SBrian Somers } else { 986d8e55738SJordan K. Hubbard /* 987944f7098SBrian Somers * Otherwise they have it right (this time) so we send a ack packet 988944f7098SBrian Somers * back confirming it... end of story 989d8e55738SJordan K. Hubbard */ 99030c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 99130c2f2ffSBrian Somers dec->ackend += length; 9923edeb0c6SBrian Somers } 993d8e55738SJordan K. Hubbard break; 994d8e55738SJordan K. Hubbard case MODE_NAK: /* what does this mean?? */ 9953edeb0c6SBrian Somers if (IsEnabled(ipcp->cfg.ns.dns_neg)) { 9963edeb0c6SBrian Somers gotdnsnak = 1; 9979e8ec64bSBrian Somers memcpy(&dnsnak[type == TY_PRIMARY_DNS ? 0 : 1].s_addr, cp + 2, 4); 9983edeb0c6SBrian Somers } 999d8e55738SJordan K. Hubbard break; 10003edeb0c6SBrian Somers case MODE_REJ: /* Can't do much, stop asking */ 10013edeb0c6SBrian Somers ipcp->peer_reject |= (1 << (type - TY_ADJUST_NS)); 1002d8e55738SJordan K. Hubbard break; 1003d8e55738SJordan K. Hubbard } 1004d8e55738SJordan K. Hubbard break; 1005d8e55738SJordan K. Hubbard 10063edeb0c6SBrian Somers case TY_PRIMARY_NBNS: /* M$ NetBIOS nameserver hack (rfc1877) */ 1007d8e55738SJordan K. Hubbard case TY_SECONDARY_NBNS: 10089e8ec64bSBrian Somers memcpy(&ipaddr.s_addr, cp + 2, 4); 1009dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 10103edeb0c6SBrian Somers 10119780ef31SBrian Somers switch (mode_type) { 1012d8e55738SJordan K. Hubbard case MODE_REQ: 10133edeb0c6SBrian Somers have_ip.s_addr = 10143edeb0c6SBrian Somers ipcp->cfg.ns.nbns[type == TY_PRIMARY_NBNS ? 0 : 1].s_addr; 10153edeb0c6SBrian Somers 10163edeb0c6SBrian Somers if (have_ip.s_addr == INADDR_ANY) { 1017dd7e2610SBrian Somers log_Printf(LogIPCP, "NBNS REQ - rejected - nbns not set\n"); 10183edeb0c6SBrian Somers ipcp->my_reject |= (1 << (type - TY_ADJUST_NS)); 101930c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 102030c2f2ffSBrian Somers dec->rejend += length; 1021d8e55738SJordan K. Hubbard break; 1022d8e55738SJordan K. Hubbard } 10233edeb0c6SBrian Somers 10243edeb0c6SBrian Somers if (ipaddr.s_addr != have_ip.s_addr) { 102530c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 10263edeb0c6SBrian Somers memcpy(dec->nakend+2, &have_ip.s_addr, length); 102730c2f2ffSBrian Somers dec->nakend += length; 10283edeb0c6SBrian Somers } else { 102930c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 103030c2f2ffSBrian Somers dec->ackend += length; 10313edeb0c6SBrian Somers } 1032d8e55738SJordan K. Hubbard break; 1033d8e55738SJordan K. Hubbard case MODE_NAK: 1034dd7e2610SBrian Somers log_Printf(LogIPCP, "MS NBNS req %d - NAK??\n", type); 1035d8e55738SJordan K. Hubbard break; 1036d8e55738SJordan K. Hubbard case MODE_REJ: 1037dd7e2610SBrian Somers log_Printf(LogIPCP, "MS NBNS req %d - REJ??\n", type); 1038d8e55738SJordan K. Hubbard break; 1039d8e55738SJordan K. Hubbard } 1040d8e55738SJordan K. Hubbard break; 1041d8e55738SJordan K. Hubbard 1042af57ed9fSAtsushi Murai default: 104330c2f2ffSBrian Somers if (mode_type != MODE_NOP) { 104483d1af55SBrian Somers ipcp->my_reject |= (1 << type); 104530c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 104630c2f2ffSBrian Somers dec->rejend += length; 104730c2f2ffSBrian Somers } 1048af57ed9fSAtsushi Murai break; 1049af57ed9fSAtsushi Murai } 1050af57ed9fSAtsushi Murai plen -= length; 1051af57ed9fSAtsushi Murai cp += length; 1052af57ed9fSAtsushi Murai } 10531342caedSBrian Somers 10543edeb0c6SBrian Somers if (gotdnsnak) 10553edeb0c6SBrian Somers if (!setdns(ipcp, dnsnak)) { 10563edeb0c6SBrian Somers ipcp->peer_reject |= (1 << (TY_PRIMARY_DNS - TY_ADJUST_NS)); 10573edeb0c6SBrian Somers ipcp->peer_reject |= (1 << (TY_SECONDARY_DNS - TY_ADJUST_NS)); 10583edeb0c6SBrian Somers } 10593edeb0c6SBrian Somers 1060e43ebac1SBrian Somers if (mode_type != MODE_NOP) { 10611342caedSBrian Somers if (dec->rejend != dec->rej) { 10621342caedSBrian Somers /* rejects are preferred */ 10631342caedSBrian Somers dec->ackend = dec->ack; 10641342caedSBrian Somers dec->nakend = dec->nak; 10651342caedSBrian Somers } else if (dec->nakend != dec->nak) 10661342caedSBrian Somers /* then NAKs */ 10671342caedSBrian Somers dec->ackend = dec->ack; 10681ae349f5Scvs2svn } 1069af57ed9fSAtsushi Murai } 1070af57ed9fSAtsushi Murai 1071af57ed9fSAtsushi Murai void 1072641684cdSBrian Somers ipcp_Input(struct ipcp *ipcp, struct bundle *bundle, struct mbuf *bp) 1073af57ed9fSAtsushi Murai { 10747308ec68SBrian Somers /* Got PROTO_IPCP from link */ 1075641684cdSBrian Somers if (bundle_Phase(bundle) == PHASE_NETWORK) 1076dd7e2610SBrian Somers fsm_Input(&ipcp->fsm, bp); 1077641684cdSBrian Somers else { 1078641684cdSBrian Somers if (bundle_Phase(bundle) < PHASE_NETWORK) 1079641684cdSBrian Somers log_Printf(LogIPCP, "%s: Error: Unexpected IPCP in phase %s (ignored)\n", 1080641684cdSBrian Somers ipcp->fsm.link->name, bundle_PhaseName(bundle)); 1081641684cdSBrian Somers mbuf_Free(bp); 1082641684cdSBrian Somers } 1083af57ed9fSAtsushi Murai } 10849c97abd8SBrian Somers 10859c97abd8SBrian Somers int 1086dd7e2610SBrian Somers ipcp_UseHisaddr(struct bundle *bundle, const char *hisaddr, int setaddr) 10879c97abd8SBrian Somers { 10885828db6dSBrian Somers struct ipcp *ipcp = &bundle->ncp.ipcp; 10895828db6dSBrian Somers 10907308ec68SBrian Somers /* Use `hisaddr' for the peers address (set iface if `setaddr') */ 10915828db6dSBrian Somers memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 10925828db6dSBrian Somers iplist_reset(&ipcp->cfg.peer_list); 10939c97abd8SBrian Somers if (strpbrk(hisaddr, ",-")) { 10945828db6dSBrian Somers iplist_setsrc(&ipcp->cfg.peer_list, hisaddr); 10955828db6dSBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 10965828db6dSBrian Somers iplist_setrandpos(&ipcp->cfg.peer_list); 109730c2f2ffSBrian Somers ipcp->peer_ip = ChooseHisAddr(bundle, ipcp->my_ip); 10985828db6dSBrian Somers if (ipcp->peer_ip.s_addr == INADDR_ANY) { 1099dd7e2610SBrian Somers log_Printf(LogWARN, "%s: None available !\n", ipcp->cfg.peer_list.src); 11009c97abd8SBrian Somers return(0); 11019c97abd8SBrian Somers } 11025828db6dSBrian Somers ipcp->cfg.peer_range.ipaddr.s_addr = ipcp->peer_ip.s_addr; 11035828db6dSBrian Somers ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 11045828db6dSBrian Somers ipcp->cfg.peer_range.width = 32; 11059c97abd8SBrian Somers } else { 1106dd7e2610SBrian Somers log_Printf(LogWARN, "%s: Invalid range !\n", hisaddr); 11079c97abd8SBrian Somers return 0; 11089c97abd8SBrian Somers } 11095828db6dSBrian Somers } else if (ParseAddr(ipcp, 1, &hisaddr, &ipcp->cfg.peer_range.ipaddr, 11105828db6dSBrian Somers &ipcp->cfg.peer_range.mask, 11115828db6dSBrian Somers &ipcp->cfg.peer_range.width) != 0) { 11125828db6dSBrian Somers ipcp->peer_ip.s_addr = ipcp->cfg.peer_range.ipaddr.s_addr; 11139c97abd8SBrian Somers 111430c2f2ffSBrian Somers if (setaddr && ipcp_SetIPaddress(bundle, ipcp->cfg.my_range.ipaddr, 111530c2f2ffSBrian Somers ipcp->cfg.peer_range.ipaddr, 0) < 0) { 11165828db6dSBrian Somers ipcp->cfg.my_range.ipaddr.s_addr = INADDR_ANY; 11175828db6dSBrian Somers ipcp->cfg.peer_range.ipaddr.s_addr = INADDR_ANY; 11189c97abd8SBrian Somers return 0; 11199c97abd8SBrian Somers } 11209c97abd8SBrian Somers } else 11219c97abd8SBrian Somers return 0; 11229c97abd8SBrian Somers 11239c97abd8SBrian Somers return 1; 11249c97abd8SBrian Somers } 1125