165309e5cSBrian Somers /*- 265309e5cSBrian Somers * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org> 365309e5cSBrian Somers * based on work by Toshiharu OHNO <tony-o@iij.ad.jp> 465309e5cSBrian Somers * Internet Initiative Japan, Inc (IIJ) 565309e5cSBrian Somers * All rights reserved. 6af57ed9fSAtsushi Murai * 765309e5cSBrian Somers * Redistribution and use in source and binary forms, with or without 865309e5cSBrian Somers * modification, are permitted provided that the following conditions 965309e5cSBrian Somers * are met: 1065309e5cSBrian Somers * 1. Redistributions of source code must retain the above copyright 1165309e5cSBrian Somers * notice, this list of conditions and the following disclaimer. 1265309e5cSBrian Somers * 2. Redistributions in binary form must reproduce the above copyright 1365309e5cSBrian Somers * notice, this list of conditions and the following disclaimer in the 1465309e5cSBrian Somers * documentation and/or other materials provided with the distribution. 15af57ed9fSAtsushi Murai * 1665309e5cSBrian Somers * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1765309e5cSBrian Somers * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1865309e5cSBrian Somers * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1965309e5cSBrian Somers * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2065309e5cSBrian Somers * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2165309e5cSBrian Somers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2265309e5cSBrian Somers * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2365309e5cSBrian Somers * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2465309e5cSBrian Somers * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2565309e5cSBrian Somers * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2665309e5cSBrian Somers * SUCH DAMAGE. 27af57ed9fSAtsushi Murai * 2897d92980SPeter Wemm * $FreeBSD$ 29af57ed9fSAtsushi Murai */ 3065309e5cSBrian Somers 3175240ed1SBrian Somers #include <sys/param.h> 325b4c5b00SBrian Somers #include <netinet/in_systm.h> 335b4c5b00SBrian Somers #include <netinet/in.h> 345b4c5b00SBrian Somers #include <netinet/ip.h> 355b4c5b00SBrian Somers #include <arpa/inet.h> 365b4c5b00SBrian Somers #include <sys/socket.h> 37448374baSBrian Somers #include <net/if.h> 383afe5ccbSBrian Somers #include <net/route.h> 3975240ed1SBrian Somers #include <netdb.h> 401fa665f5SBrian Somers #include <sys/un.h> 4175240ed1SBrian Somers 42119386a3SBrian Somers #include <errno.h> 433edeb0c6SBrian Somers #include <fcntl.h> 443edeb0c6SBrian Somers #include <resolv.h> 456eafd353SBrian Somers #include <stdarg.h> 46d1a3ea47SBrian Somers #include <stdlib.h> 4775240ed1SBrian Somers #include <string.h> 48d568d6c4SBrian Somers #include <sys/stat.h> 496140ba11SBrian Somers #include <termios.h> 5075240ed1SBrian Somers #include <unistd.h> 5175240ed1SBrian Somers 5267b072f7SBrian Somers #ifndef NONAT 5310e629b9SBrian Somers #ifdef LOCALNAT 547884358fSBrian Somers #include "alias.h" 5510e629b9SBrian Somers #else 5610e629b9SBrian Somers #include <alias.h> 571595bacdSBrian Somers #endif 581595bacdSBrian Somers #endif 5910e629b9SBrian Somers 605d9e6103SBrian Somers #include "layer.h" 619e8ec64bSBrian Somers #include "ua.h" 62c9e11a11SBrian Somers #include "defs.h" 63b6e82f33SBrian Somers #include "command.h" 6475240ed1SBrian Somers #include "mbuf.h" 6575240ed1SBrian Somers #include "log.h" 6675240ed1SBrian Somers #include "timer.h" 67af57ed9fSAtsushi Murai #include "fsm.h" 685d9e6103SBrian Somers #include "proto.h" 69bcc332bdSBrian Somers #include "iplist.h" 709a0b991fSBrian Somers #include "throughput.h" 711ae349f5Scvs2svn #include "slcompress.h" 725a72b6edSBrian Somers #include "lqr.h" 735a72b6edSBrian Somers #include "hdlc.h" 741038894eSBrian Somers #include "lcp.h" 7530949fd4SBrian Somers #include "ncpaddr.h" 7630949fd4SBrian Somers #include "ip.h" 77eaa4df37SBrian Somers #include "ipcp.h" 789c97abd8SBrian Somers #include "filter.h" 792f786681SBrian Somers #include "descriptor.h" 801ae349f5Scvs2svn #include "vjcomp.h" 816140ba11SBrian Somers #include "async.h" 823b0f8d2eSBrian Somers #include "ccp.h" 838c07a7b2SBrian Somers #include "link.h" 8463b73463SBrian Somers #include "physical.h" 853b0f8d2eSBrian Somers #include "mp.h" 86972a1bcfSBrian Somers #ifndef NORADIUS 87972a1bcfSBrian Somers #include "radius.h" 88972a1bcfSBrian Somers #endif 8930949fd4SBrian Somers #include "ipv6cp.h" 9030949fd4SBrian Somers #include "ncp.h" 913b0f8d2eSBrian Somers #include "bundle.h" 92455aabc3SBrian Somers #include "id.h" 93455aabc3SBrian Somers #include "arp.h" 94455aabc3SBrian Somers #include "systems.h" 9585b542cfSBrian Somers #include "prompt.h" 96610b185fSBrian Somers #include "route.h" 978fa6ebe4SBrian Somers #include "iface.h" 98af57ed9fSAtsushi Murai 99503a7782SBrian Somers #undef REJECTED 100503a7782SBrian Somers #define REJECTED(p, x) ((p)->peer_reject & (1<<(x))) 1013edeb0c6SBrian Somers #define issep(ch) ((ch) == ' ' || (ch) == '\t') 1023edeb0c6SBrian Somers #define isip(ch) (((ch) >= '0' && (ch) <= '9') || (ch) == '.') 103d8e55738SJordan K. Hubbard 10429e275ceSBrian Somers struct compreq { 10529e275ceSBrian Somers u_short proto; 10629e275ceSBrian Somers u_char slots; 10729e275ceSBrian Somers u_char compcid; 10829e275ceSBrian Somers }; 10975240ed1SBrian Somers 1106f384573SBrian Somers static int IpcpLayerUp(struct fsm *); 1111ae349f5Scvs2svn static void IpcpLayerDown(struct fsm *); 112927145beSBrian Somers static void IpcpLayerStart(struct fsm *); 113927145beSBrian Somers static void IpcpLayerFinish(struct fsm *); 114479508cfSBrian Somers static void IpcpInitRestartCounter(struct fsm *, int); 1157308ec68SBrian Somers static void IpcpSendConfigReq(struct fsm *); 1162267893fSBrian Somers static void IpcpSentTerminateReq(struct fsm *); 1172267893fSBrian Somers static void IpcpSendTerminateAck(struct fsm *, u_char); 118ff360cc9SBrian Somers static void IpcpDecodeConfig(struct fsm *, u_char *, u_char *, int, 11930c2f2ffSBrian Somers struct fsm_decode *); 120af57ed9fSAtsushi Murai 12183d1af55SBrian Somers static struct fsm_callbacks ipcp_Callbacks = { 122af57ed9fSAtsushi Murai IpcpLayerUp, 123af57ed9fSAtsushi Murai IpcpLayerDown, 124af57ed9fSAtsushi Murai IpcpLayerStart, 125af57ed9fSAtsushi Murai IpcpLayerFinish, 126af57ed9fSAtsushi Murai IpcpInitRestartCounter, 127af57ed9fSAtsushi Murai IpcpSendConfigReq, 1282267893fSBrian Somers IpcpSentTerminateReq, 129af57ed9fSAtsushi Murai IpcpSendTerminateAck, 130af57ed9fSAtsushi Murai IpcpDecodeConfig, 131dd7e2610SBrian Somers fsm_NullRecvResetReq, 132dd7e2610SBrian Somers fsm_NullRecvResetAck 133af57ed9fSAtsushi Murai }; 134af57ed9fSAtsushi Murai 135d6d3eeabSBrian Somers static const char * 136d6d3eeabSBrian Somers protoname(int proto) 137d6d3eeabSBrian Somers { 138d6d3eeabSBrian Somers static struct { 139d6d3eeabSBrian Somers int id; 140d6d3eeabSBrian Somers const char *txt; 141d6d3eeabSBrian Somers } cftypes[] = { 1429e836af5SBrian Somers /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */ 143d6d3eeabSBrian Somers { 1, "IPADDRS" }, /* IP-Addresses */ /* deprecated */ 144d6d3eeabSBrian Somers { 2, "COMPPROTO" }, /* IP-Compression-Protocol */ 145d6d3eeabSBrian Somers { 3, "IPADDR" }, /* IP-Address */ 146d6d3eeabSBrian Somers { 129, "PRIDNS" }, /* 129: Primary DNS Server Address */ 147d6d3eeabSBrian Somers { 130, "PRINBNS" }, /* 130: Primary NBNS Server Address */ 148d6d3eeabSBrian Somers { 131, "SECDNS" }, /* 131: Secondary DNS Server Address */ 149d6d3eeabSBrian Somers { 132, "SECNBNS" } /* 132: Secondary NBNS Server Address */ 150af57ed9fSAtsushi Murai }; 151057f1760SBrian Somers unsigned f; 152af57ed9fSAtsushi Murai 153d6d3eeabSBrian Somers for (f = 0; f < sizeof cftypes / sizeof *cftypes; f++) 154d6d3eeabSBrian Somers if (cftypes[f].id == proto) 155d6d3eeabSBrian Somers return cftypes[f].txt; 1569e836af5SBrian Somers 157d6d3eeabSBrian Somers return NumStr(proto, NULL, 0); 158d6d3eeabSBrian Somers } 1599e836af5SBrian Somers 1609a0b991fSBrian Somers void 1615828db6dSBrian Somers ipcp_AddInOctets(struct ipcp *ipcp, int n) 162af57ed9fSAtsushi Murai { 1635828db6dSBrian Somers throughput_addin(&ipcp->throughput, n); 164af57ed9fSAtsushi Murai } 165af57ed9fSAtsushi Murai 1669a0b991fSBrian Somers void 1675828db6dSBrian Somers ipcp_AddOutOctets(struct ipcp *ipcp, int n) 168af57ed9fSAtsushi Murai { 1695828db6dSBrian Somers throughput_addout(&ipcp->throughput, n); 1701ae349f5Scvs2svn } 1711ae349f5Scvs2svn 172d568d6c4SBrian Somers void 173d568d6c4SBrian Somers ipcp_LoadDNS(struct ipcp *ipcp) 1743edeb0c6SBrian Somers { 175d568d6c4SBrian Somers int fd; 1763edeb0c6SBrian Somers 177d568d6c4SBrian Somers ipcp->ns.dns[0].s_addr = ipcp->ns.dns[1].s_addr = INADDR_NONE; 178d568d6c4SBrian Somers 179d568d6c4SBrian Somers if (ipcp->ns.resolv != NULL) { 180d568d6c4SBrian Somers free(ipcp->ns.resolv); 181d568d6c4SBrian Somers ipcp->ns.resolv = NULL; 182d568d6c4SBrian Somers } 183d568d6c4SBrian Somers if (ipcp->ns.resolv_nons != NULL) { 184d568d6c4SBrian Somers free(ipcp->ns.resolv_nons); 185d568d6c4SBrian Somers ipcp->ns.resolv_nons = NULL; 186d568d6c4SBrian Somers } 187d568d6c4SBrian Somers ipcp->ns.resolver = 0; 188d568d6c4SBrian Somers 189d568d6c4SBrian Somers if ((fd = open(_PATH_RESCONF, O_RDONLY)) != -1) { 190d568d6c4SBrian Somers struct stat st; 191d568d6c4SBrian Somers 192d568d6c4SBrian Somers if (fstat(fd, &st) == 0) { 193d568d6c4SBrian Somers ssize_t got; 194d568d6c4SBrian Somers 195eb1ecbb2SBrian Somers /* 196eb1ecbb2SBrian Somers * Note, ns.resolv and ns.resolv_nons are assumed to always point to 197eb1ecbb2SBrian Somers * buffers of the same size! See the strcpy() below. 198eb1ecbb2SBrian Somers */ 199d568d6c4SBrian Somers if ((ipcp->ns.resolv_nons = (char *)malloc(st.st_size + 1)) == NULL) 200d568d6c4SBrian Somers log_Printf(LogERROR, "Failed to malloc %lu for %s: %s\n", 201d568d6c4SBrian Somers (unsigned long)st.st_size, _PATH_RESCONF, strerror(errno)); 202d568d6c4SBrian Somers else if ((ipcp->ns.resolv = (char *)malloc(st.st_size + 1)) == NULL) { 203d568d6c4SBrian Somers log_Printf(LogERROR, "Failed(2) to malloc %lu for %s: %s\n", 204d568d6c4SBrian Somers (unsigned long)st.st_size, _PATH_RESCONF, strerror(errno)); 205d568d6c4SBrian Somers free(ipcp->ns.resolv_nons); 206d568d6c4SBrian Somers ipcp->ns.resolv_nons = NULL; 207d568d6c4SBrian Somers } else if ((got = read(fd, ipcp->ns.resolv, st.st_size)) != st.st_size) { 208d568d6c4SBrian Somers if (got == -1) 209d568d6c4SBrian Somers log_Printf(LogERROR, "Failed to read %s: %s\n", 210d568d6c4SBrian Somers _PATH_RESCONF, strerror(errno)); 211d568d6c4SBrian Somers else 212d568d6c4SBrian Somers log_Printf(LogERROR, "Failed to read %s, got %lu not %lu\n", 213d568d6c4SBrian Somers _PATH_RESCONF, (unsigned long)got, 214d568d6c4SBrian Somers (unsigned long)st.st_size); 215d568d6c4SBrian Somers free(ipcp->ns.resolv_nons); 216d568d6c4SBrian Somers ipcp->ns.resolv_nons = NULL; 217d568d6c4SBrian Somers free(ipcp->ns.resolv); 218d568d6c4SBrian Somers ipcp->ns.resolv = NULL; 219d568d6c4SBrian Somers } else { 220d568d6c4SBrian Somers char *cp, *cp_nons, *ncp, ch; 2213edeb0c6SBrian Somers int n; 2223edeb0c6SBrian Somers 223d568d6c4SBrian Somers ipcp->ns.resolv[st.st_size] = '\0'; 224d568d6c4SBrian Somers ipcp->ns.resolver = 1; 225d568d6c4SBrian Somers 226d568d6c4SBrian Somers cp_nons = ipcp->ns.resolv_nons; 227d568d6c4SBrian Somers cp = ipcp->ns.resolv; 2283edeb0c6SBrian Somers n = 0; 229d568d6c4SBrian Somers 230d568d6c4SBrian Somers while ((ncp = strstr(cp, "nameserver")) != NULL) { 231d568d6c4SBrian Somers if (ncp != cp) { 232d568d6c4SBrian Somers memcpy(cp_nons, cp, ncp - cp); 233d568d6c4SBrian Somers cp_nons += ncp - cp; 2343edeb0c6SBrian Somers } 235d568d6c4SBrian Somers if ((ncp != cp && ncp[-1] != '\n') || !issep(ncp[10])) { 236d568d6c4SBrian Somers memcpy(cp_nons, ncp, 9); 237d568d6c4SBrian Somers cp_nons += 9; 238d568d6c4SBrian Somers cp = ncp + 9; /* Can't match "nameserver" at cp... */ 239d568d6c4SBrian Somers continue; 2403edeb0c6SBrian Somers } 241d568d6c4SBrian Somers 242d568d6c4SBrian Somers for (cp = ncp + 11; issep(*cp); cp++) /* Skip whitespace */ 243d568d6c4SBrian Somers ; 244d568d6c4SBrian Somers 245d568d6c4SBrian Somers for (ncp = cp; isip(*ncp); ncp++) /* Jump over IP */ 246d568d6c4SBrian Somers ; 247d568d6c4SBrian Somers 248d568d6c4SBrian Somers ch = *ncp; 249d568d6c4SBrian Somers *ncp = '\0'; 25030949fd4SBrian Somers if (n < 2 && inet_aton(cp, ipcp->ns.dns)) 251d568d6c4SBrian Somers n++; 252d568d6c4SBrian Somers *ncp = ch; 253d568d6c4SBrian Somers 254d568d6c4SBrian Somers if ((cp = strchr(ncp, '\n')) == NULL) /* Point at next line */ 255d568d6c4SBrian Somers cp = ncp + strlen(ncp); 256d568d6c4SBrian Somers else 257d568d6c4SBrian Somers cp++; 258d568d6c4SBrian Somers } 259eb1ecbb2SBrian Somers /* 260eb1ecbb2SBrian Somers * Note, cp_nons and cp always point to buffers of the same size, so 261eb1ecbb2SBrian Somers * strcpy is ok! 262eb1ecbb2SBrian Somers */ 263d568d6c4SBrian Somers strcpy(cp_nons, cp); /* Copy the end - including the NUL */ 264d568d6c4SBrian Somers cp_nons += strlen(cp_nons) - 1; 265d568d6c4SBrian Somers while (cp_nons >= ipcp->ns.resolv_nons && *cp_nons == '\n') 266d568d6c4SBrian Somers *cp_nons-- = '\0'; 267d568d6c4SBrian Somers if (n == 2 && ipcp->ns.dns[0].s_addr == INADDR_ANY) { 268d568d6c4SBrian Somers ipcp->ns.dns[0].s_addr = ipcp->ns.dns[1].s_addr; 269d568d6c4SBrian Somers ipcp->ns.dns[1].s_addr = INADDR_ANY; 270d568d6c4SBrian Somers } 27130949fd4SBrian Somers bundle_AdjustDNS(ipcp->fsm.bundle); 272d568d6c4SBrian Somers } 273d568d6c4SBrian Somers } else 274d568d6c4SBrian Somers log_Printf(LogERROR, "Failed to stat opened %s: %s\n", 275d568d6c4SBrian Somers _PATH_RESCONF, strerror(errno)); 276d568d6c4SBrian Somers 277d568d6c4SBrian Somers close(fd); 2783edeb0c6SBrian Somers } 2793edeb0c6SBrian Somers } 2803edeb0c6SBrian Somers 281d568d6c4SBrian Somers int 282d568d6c4SBrian Somers ipcp_WriteDNS(struct ipcp *ipcp) 2833edeb0c6SBrian Somers { 284d568d6c4SBrian Somers const char *paddr; 285d568d6c4SBrian Somers mode_t mask; 2863edeb0c6SBrian Somers FILE *fp; 2873edeb0c6SBrian Somers 288d568d6c4SBrian Somers if (ipcp->ns.dns[0].s_addr == INADDR_ANY && 289d568d6c4SBrian Somers ipcp->ns.dns[1].s_addr == INADDR_ANY) { 290d568d6c4SBrian Somers log_Printf(LogIPCP, "%s not modified: All nameservers NAKd\n", 2913edeb0c6SBrian Somers _PATH_RESCONF); 2923edeb0c6SBrian Somers return 0; 2933edeb0c6SBrian Somers } 2943edeb0c6SBrian Somers 295d568d6c4SBrian Somers if (ipcp->ns.dns[0].s_addr == INADDR_ANY) { 296d568d6c4SBrian Somers ipcp->ns.dns[0].s_addr = ipcp->ns.dns[1].s_addr; 297d568d6c4SBrian Somers ipcp->ns.dns[1].s_addr = INADDR_ANY; 298d568d6c4SBrian Somers } 2993edeb0c6SBrian Somers 3007fe0b592SBrian Somers mask = umask(022); 301d568d6c4SBrian Somers if ((fp = ID0fopen(_PATH_RESCONF, "w")) != NULL) { 302d568d6c4SBrian Somers umask(mask); 303682cb20fSBrian Somers if (ipcp->ns.resolv_nons) 304d568d6c4SBrian Somers fputs(ipcp->ns.resolv_nons, fp); 305d568d6c4SBrian Somers paddr = inet_ntoa(ipcp->ns.dns[0]); 306d568d6c4SBrian Somers log_Printf(LogIPCP, "Primary nameserver set to %s\n", paddr); 307d568d6c4SBrian Somers fprintf(fp, "\nnameserver %s\n", paddr); 308d568d6c4SBrian Somers if (ipcp->ns.dns[1].s_addr != INADDR_ANY && 309d568d6c4SBrian Somers ipcp->ns.dns[1].s_addr != INADDR_NONE && 310d568d6c4SBrian Somers ipcp->ns.dns[1].s_addr != ipcp->ns.dns[0].s_addr) { 311d568d6c4SBrian Somers paddr = inet_ntoa(ipcp->ns.dns[1]); 312d568d6c4SBrian Somers log_Printf(LogIPCP, "Secondary nameserver set to %s\n", paddr); 313d568d6c4SBrian Somers fprintf(fp, "nameserver %s\n", paddr); 314d568d6c4SBrian Somers } 315d568d6c4SBrian Somers if (fclose(fp) == EOF) { 316d568d6c4SBrian Somers log_Printf(LogERROR, "write(): Failed updating %s: %s\n", _PATH_RESCONF, 317d568d6c4SBrian Somers strerror(errno)); 3183edeb0c6SBrian Somers return 0; 3193edeb0c6SBrian Somers } 320d568d6c4SBrian Somers } else 321d568d6c4SBrian Somers umask(mask); 3223edeb0c6SBrian Somers 3233edeb0c6SBrian Somers return 1; 324af57ed9fSAtsushi Murai } 325af57ed9fSAtsushi Murai 326d568d6c4SBrian Somers void 327d568d6c4SBrian Somers ipcp_RestoreDNS(struct ipcp *ipcp) 328d568d6c4SBrian Somers { 329d568d6c4SBrian Somers if (ipcp->ns.resolver) { 330057f1760SBrian Somers ssize_t got, len; 331d568d6c4SBrian Somers int fd; 332d568d6c4SBrian Somers 333d568d6c4SBrian Somers if ((fd = ID0open(_PATH_RESCONF, O_WRONLY|O_TRUNC, 0644)) != -1) { 334d568d6c4SBrian Somers len = strlen(ipcp->ns.resolv); 335d568d6c4SBrian Somers if ((got = write(fd, ipcp->ns.resolv, len)) != len) { 336d568d6c4SBrian Somers if (got == -1) 337d568d6c4SBrian Somers log_Printf(LogERROR, "Failed rewriting %s: write: %s\n", 338d568d6c4SBrian Somers _PATH_RESCONF, strerror(errno)); 339d568d6c4SBrian Somers else 340057f1760SBrian Somers log_Printf(LogERROR, "Failed rewriting %s: wrote %ld of %ld\n", 341057f1760SBrian Somers _PATH_RESCONF, (long)got, (long)len); 342d568d6c4SBrian Somers } 343d568d6c4SBrian Somers close(fd); 344d568d6c4SBrian Somers } else 345d568d6c4SBrian Somers log_Printf(LogERROR, "Failed rewriting %s: open: %s\n", _PATH_RESCONF, 346d568d6c4SBrian Somers strerror(errno)); 347d568d6c4SBrian Somers } else if (remove(_PATH_RESCONF) == -1) 348d568d6c4SBrian Somers log_Printf(LogERROR, "Failed removing %s: %s\n", _PATH_RESCONF, 349d568d6c4SBrian Somers strerror(errno)); 350d568d6c4SBrian Somers 351d568d6c4SBrian Somers } 352d568d6c4SBrian Somers 353274e766cSBrian Somers int 354dd7e2610SBrian Somers ipcp_Show(struct cmdargs const *arg) 355af57ed9fSAtsushi Murai { 356610b185fSBrian Somers struct ipcp *ipcp = &arg->bundle->ncp.ipcp; 357af57ed9fSAtsushi Murai 358610b185fSBrian Somers prompt_Printf(arg->prompt, "%s [%s]\n", ipcp->fsm.name, 359610b185fSBrian Somers State2Nam(ipcp->fsm.state)); 360610b185fSBrian Somers if (ipcp->fsm.state == ST_OPENED) { 361b6217683SBrian Somers prompt_Printf(arg->prompt, " His side: %s, %s\n", 362610b185fSBrian Somers inet_ntoa(ipcp->peer_ip), vj2asc(ipcp->peer_compproto)); 363b6217683SBrian Somers prompt_Printf(arg->prompt, " My side: %s, %s\n", 364610b185fSBrian Somers inet_ntoa(ipcp->my_ip), vj2asc(ipcp->my_compproto)); 365209dc102SBrian Somers prompt_Printf(arg->prompt, " Queued packets: %lu\n", 36630949fd4SBrian Somers (unsigned long)ipcp_QueueLen(ipcp)); 3671ae349f5Scvs2svn } 368927145beSBrian Somers 369b6217683SBrian Somers prompt_Printf(arg->prompt, "\nDefaults:\n"); 370479508cfSBrian Somers prompt_Printf(arg->prompt, " FSM retry = %us, max %u Config" 371479508cfSBrian Somers " REQ%s, %u Term REQ%s\n", ipcp->cfg.fsm.timeout, 372479508cfSBrian Somers ipcp->cfg.fsm.maxreq, ipcp->cfg.fsm.maxreq == 1 ? "" : "s", 373479508cfSBrian Somers ipcp->cfg.fsm.maxtrm, ipcp->cfg.fsm.maxtrm == 1 ? "" : "s"); 37430949fd4SBrian Somers prompt_Printf(arg->prompt, " My Address: %s\n", 37530949fd4SBrian Somers ncprange_ntoa(&ipcp->cfg.my_range)); 376610b185fSBrian Somers if (ipcp->cfg.HaveTriggerAddress) 377bc76350eSBrian Somers prompt_Printf(arg->prompt, " Trigger address: %s\n", 378610b185fSBrian Somers inet_ntoa(ipcp->cfg.TriggerAddress)); 379bc76350eSBrian Somers 380bc76350eSBrian Somers prompt_Printf(arg->prompt, " VJ compression: %s (%d slots %s slot " 381610b185fSBrian Somers "compression)\n", command_ShowNegval(ipcp->cfg.vj.neg), 382610b185fSBrian Somers ipcp->cfg.vj.slots, ipcp->cfg.vj.slotcomp ? "with" : "without"); 38350abd4c8SBrian Somers 384610b185fSBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) 385b6217683SBrian Somers prompt_Printf(arg->prompt, " His Address: %s\n", 386610b185fSBrian Somers ipcp->cfg.peer_list.src); 3871ae349f5Scvs2svn else 38830949fd4SBrian Somers prompt_Printf(arg->prompt, " His Address: %s\n", 38930949fd4SBrian Somers ncprange_ntoa(&ipcp->cfg.peer_range)); 39050abd4c8SBrian Somers 391d568d6c4SBrian Somers prompt_Printf(arg->prompt, " DNS: %s", 392d568d6c4SBrian Somers ipcp->cfg.ns.dns[0].s_addr == INADDR_NONE ? 393d568d6c4SBrian Somers "none" : inet_ntoa(ipcp->cfg.ns.dns[0])); 394d568d6c4SBrian Somers if (ipcp->cfg.ns.dns[1].s_addr != INADDR_NONE) 39530949fd4SBrian Somers prompt_Printf(arg->prompt, ", %s", 39630949fd4SBrian Somers inet_ntoa(ipcp->cfg.ns.dns[1])); 397d568d6c4SBrian Somers prompt_Printf(arg->prompt, ", %s\n", 398610b185fSBrian Somers command_ShowNegval(ipcp->cfg.ns.dns_neg)); 399d568d6c4SBrian Somers prompt_Printf(arg->prompt, " Resolver DNS: %s", 400d568d6c4SBrian Somers ipcp->ns.dns[0].s_addr == INADDR_NONE ? 401d568d6c4SBrian Somers "none" : inet_ntoa(ipcp->ns.dns[0])); 402d568d6c4SBrian Somers if (ipcp->ns.dns[1].s_addr != INADDR_NONE && 403d568d6c4SBrian Somers ipcp->ns.dns[1].s_addr != ipcp->ns.dns[0].s_addr) 40430949fd4SBrian Somers prompt_Printf(arg->prompt, ", %s", 40530949fd4SBrian Somers inet_ntoa(ipcp->ns.dns[1])); 406d568d6c4SBrian Somers prompt_Printf(arg->prompt, "\n NetBIOS NS: %s, ", 407610b185fSBrian Somers inet_ntoa(ipcp->cfg.ns.nbns[0])); 408ad1f9eaeSBrian Somers prompt_Printf(arg->prompt, "%s\n\n", 40930949fd4SBrian Somers inet_ntoa(ipcp->cfg.ns.nbns[1])); 410442f8495SBrian Somers 411610b185fSBrian Somers throughput_disp(&ipcp->throughput, arg->prompt); 4129a0b991fSBrian Somers 413927145beSBrian Somers return 0; 414af57ed9fSAtsushi Murai } 415af57ed9fSAtsushi Murai 416d1a3ea47SBrian Somers int 417dd7e2610SBrian Somers ipcp_vjset(struct cmdargs const *arg) 418d1a3ea47SBrian Somers { 41925092092SBrian Somers if (arg->argc != arg->argn+2) 420d1a3ea47SBrian Somers return -1; 42125092092SBrian Somers if (!strcasecmp(arg->argv[arg->argn], "slots")) { 422d1a3ea47SBrian Somers int slots; 423d1a3ea47SBrian Somers 42425092092SBrian Somers slots = atoi(arg->argv[arg->argn+1]); 425d1a3ea47SBrian Somers if (slots < 4 || slots > 16) 426d1a3ea47SBrian Somers return 1; 4271342caedSBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slots = slots; 428d1a3ea47SBrian Somers return 0; 42925092092SBrian Somers } else if (!strcasecmp(arg->argv[arg->argn], "slotcomp")) { 43025092092SBrian Somers if (!strcasecmp(arg->argv[arg->argn+1], "on")) 4311342caedSBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 1; 43225092092SBrian Somers else if (!strcasecmp(arg->argv[arg->argn+1], "off")) 4331342caedSBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 0; 434d1a3ea47SBrian Somers else 435d1a3ea47SBrian Somers return 2; 436d1a3ea47SBrian Somers return 0; 437d1a3ea47SBrian Somers } 438d1a3ea47SBrian Somers return -1; 439d1a3ea47SBrian Somers } 440d1a3ea47SBrian Somers 4411ae349f5Scvs2svn void 4426d666775SBrian Somers ipcp_Init(struct ipcp *ipcp, struct bundle *bundle, struct link *l, 4436d666775SBrian Somers const struct fsm_parent *parent) 444d1a3ea47SBrian Somers { 445503a7782SBrian Somers struct hostent *hp; 44630949fd4SBrian Somers struct in_addr host; 44726e6a622SBrian Somers char name[MAXHOSTNAMELEN]; 448182c898aSBrian Somers static const char * const timer_names[] = 4493b0f8d2eSBrian Somers {"IPCP restart", "IPCP openmode", "IPCP stopped"}; 45029e275ceSBrian Somers 451479508cfSBrian Somers fsm_Init(&ipcp->fsm, "IPCP", PROTO_IPCP, 1, IPCP_MAXCODE, LogIPCP, 4523b0f8d2eSBrian Somers bundle, l, parent, &ipcp_Callbacks, timer_names); 453503a7782SBrian Somers 4541342caedSBrian Somers ipcp->cfg.vj.slots = DEF_VJ_STATES; 4551342caedSBrian Somers ipcp->cfg.vj.slotcomp = 1; 456503a7782SBrian Somers memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range); 45730949fd4SBrian Somers 45830949fd4SBrian Somers host.s_addr = htonl(INADDR_LOOPBACK); 45930949fd4SBrian Somers ipcp->cfg.netmask.s_addr = INADDR_ANY; 460503a7782SBrian Somers if (gethostname(name, sizeof name) == 0) { 461503a7782SBrian Somers hp = gethostbyname(name); 46230949fd4SBrian Somers if (hp && hp->h_addrtype == AF_INET && hp->h_length == sizeof host.s_addr) 46330949fd4SBrian Somers memcpy(&host.s_addr, hp->h_addr, sizeof host.s_addr); 464503a7782SBrian Somers } 46530949fd4SBrian Somers ncprange_setip4(&ipcp->cfg.my_range, host, ipcp->cfg.netmask); 46630949fd4SBrian Somers ncprange_setip4(&ipcp->cfg.peer_range, ipcp->cfg.netmask, ipcp->cfg.netmask); 46730949fd4SBrian Somers 468503a7782SBrian Somers iplist_setsrc(&ipcp->cfg.peer_list, ""); 469503a7782SBrian Somers ipcp->cfg.HaveTriggerAddress = 0; 470503a7782SBrian Somers 471d568d6c4SBrian Somers ipcp->cfg.ns.dns[0].s_addr = INADDR_NONE; 472d568d6c4SBrian Somers ipcp->cfg.ns.dns[1].s_addr = INADDR_NONE; 4733edeb0c6SBrian Somers ipcp->cfg.ns.dns_neg = 0; 4743edeb0c6SBrian Somers ipcp->cfg.ns.nbns[0].s_addr = INADDR_ANY; 4753edeb0c6SBrian Somers ipcp->cfg.ns.nbns[1].s_addr = INADDR_ANY; 476cd9647a1SBrian Somers 477479508cfSBrian Somers ipcp->cfg.fsm.timeout = DEF_FSMRETRY; 478479508cfSBrian Somers ipcp->cfg.fsm.maxreq = DEF_FSMTRIES; 479479508cfSBrian Somers ipcp->cfg.fsm.maxtrm = DEF_FSMTRIES; 4801342caedSBrian Somers ipcp->cfg.vj.neg = NEG_ENABLED|NEG_ACCEPTED; 481503a7782SBrian Somers 482eaa4df37SBrian Somers memset(&ipcp->vj, '\0', sizeof ipcp->vj); 483eaa4df37SBrian Somers 484d568d6c4SBrian Somers ipcp->ns.resolv = NULL; 485d568d6c4SBrian Somers ipcp->ns.resolv_nons = NULL; 486d568d6c4SBrian Somers ipcp->ns.writable = 1; 487d568d6c4SBrian Somers ipcp_LoadDNS(ipcp); 488d568d6c4SBrian Somers 489ab2de065SBrian Somers throughput_init(&ipcp->throughput, SAMPLE_PERIOD); 4905a72b6edSBrian Somers memset(ipcp->Queue, '\0', sizeof ipcp->Queue); 491972a1bcfSBrian Somers ipcp_Setup(ipcp, INADDR_NONE); 492d1a3ea47SBrian Somers } 493d1a3ea47SBrian Somers 494af57ed9fSAtsushi Murai void 495442f8495SBrian Somers ipcp_Destroy(struct ipcp *ipcp) 496442f8495SBrian Somers { 49730949fd4SBrian Somers throughput_destroy(&ipcp->throughput); 49830949fd4SBrian Somers 499d568d6c4SBrian Somers if (ipcp->ns.resolv != NULL) { 500d568d6c4SBrian Somers free(ipcp->ns.resolv); 501d568d6c4SBrian Somers ipcp->ns.resolv = NULL; 502d568d6c4SBrian Somers } 503d568d6c4SBrian Somers if (ipcp->ns.resolv_nons != NULL) { 504d568d6c4SBrian Somers free(ipcp->ns.resolv_nons); 505d568d6c4SBrian Somers ipcp->ns.resolv_nons = NULL; 506d568d6c4SBrian Somers } 507442f8495SBrian Somers } 508442f8495SBrian Somers 509442f8495SBrian Somers void 510ce828a6eSBrian Somers ipcp_SetLink(struct ipcp *ipcp, struct link *l) 511af57ed9fSAtsushi Murai { 512ce828a6eSBrian Somers ipcp->fsm.link = l; 513af57ed9fSAtsushi Murai } 514549d663dSAtsushi Murai 515ce828a6eSBrian Somers void 516972a1bcfSBrian Somers ipcp_Setup(struct ipcp *ipcp, u_int32_t mask) 517503a7782SBrian Somers { 5188fa6ebe4SBrian Somers struct iface *iface = ipcp->fsm.bundle->iface; 51930949fd4SBrian Somers struct ncpaddr ipaddr; 52030949fd4SBrian Somers struct in_addr peer; 521057f1760SBrian Somers int pos; 522057f1760SBrian Somers unsigned n; 523503a7782SBrian Somers 524503a7782SBrian Somers ipcp->fsm.open_mode = 0; 525972a1bcfSBrian Somers ipcp->ifmask.s_addr = mask == INADDR_NONE ? ipcp->cfg.netmask.s_addr : mask; 526503a7782SBrian Somers 527503a7782SBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 5288fa6ebe4SBrian Somers /* Try to give the peer a previously configured IP address */ 52930949fd4SBrian Somers for (n = 0; n < iface->addrs; n++) { 53030949fd4SBrian Somers if (!ncpaddr_getip4(&iface->addr[n].peer, &peer)) 53130949fd4SBrian Somers continue; 53230949fd4SBrian Somers if ((pos = iplist_ip2pos(&ipcp->cfg.peer_list, peer)) != -1) { 53330949fd4SBrian Somers ncpaddr_setip4(&ipaddr, iplist_setcurpos(&ipcp->cfg.peer_list, pos)); 5348fa6ebe4SBrian Somers break; 5358fa6ebe4SBrian Somers } 5368fa6ebe4SBrian Somers } 53730949fd4SBrian Somers if (n == iface->addrs) 5388fa6ebe4SBrian Somers /* Ok, so none of 'em fit.... pick a random one */ 53930949fd4SBrian Somers ncpaddr_setip4(&ipaddr, iplist_setrandpos(&ipcp->cfg.peer_list)); 5408fa6ebe4SBrian Somers 54130949fd4SBrian Somers ncprange_sethost(&ipcp->cfg.peer_range, &ipaddr); 542503a7782SBrian Somers } 543503a7782SBrian Somers 544503a7782SBrian Somers ipcp->heis1172 = 0; 5455e3b2d68SBrian Somers ipcp->peer_req = 0; 54630949fd4SBrian Somers ncprange_getip4addr(&ipcp->cfg.peer_range, &ipcp->peer_ip); 547503a7782SBrian Somers ipcp->peer_compproto = 0; 5481ae349f5Scvs2svn 5498390b576SBrian Somers if (ipcp->cfg.HaveTriggerAddress) { 550549d663dSAtsushi Murai /* 5515b4c5b00SBrian Somers * Some implementations of PPP require that we send a 5525b4c5b00SBrian Somers * *special* value as our address, even though the rfc specifies 5535b4c5b00SBrian Somers * full negotiation (e.g. "0.0.0.0" or Not "0.0.0.0"). 554549d663dSAtsushi Murai */ 555503a7782SBrian Somers ipcp->my_ip = ipcp->cfg.TriggerAddress; 556dd7e2610SBrian Somers log_Printf(LogIPCP, "Using trigger address %s\n", 557503a7782SBrian Somers inet_ntoa(ipcp->cfg.TriggerAddress)); 5588fa6ebe4SBrian Somers } else { 5598390b576SBrian Somers /* 5608fa6ebe4SBrian Somers * Otherwise, if we've used an IP number before and it's still within 5618fa6ebe4SBrian Somers * the network specified on the ``set ifaddr'' line, we really 5628fa6ebe4SBrian Somers * want to keep that IP number so that we can keep any existing 56330949fd4SBrian Somers * connections that are bound to that IP. 5648390b576SBrian Somers */ 56530949fd4SBrian Somers for (n = 0; n < iface->addrs; n++) { 56630949fd4SBrian Somers ncprange_getaddr(&iface->addr[n].ifa, &ipaddr); 56730949fd4SBrian Somers if (ncprange_contains(&ipcp->cfg.my_range, &ipaddr)) { 56830949fd4SBrian Somers ncpaddr_getip4(&ipaddr, &ipcp->my_ip); 5698fa6ebe4SBrian Somers break; 5708fa6ebe4SBrian Somers } 57130949fd4SBrian Somers } 57230949fd4SBrian Somers if (n == iface->addrs) 57330949fd4SBrian Somers ncprange_getip4addr(&ipcp->cfg.my_range, &ipcp->my_ip); 5748fa6ebe4SBrian Somers } 57529e275ceSBrian Somers 576972a1bcfSBrian Somers if (IsEnabled(ipcp->cfg.vj.neg) 577972a1bcfSBrian Somers #ifndef NORADIUS 578972a1bcfSBrian Somers || (ipcp->fsm.bundle->radius.valid && ipcp->fsm.bundle->radius.vj) 579972a1bcfSBrian Somers #endif 580972a1bcfSBrian Somers ) 581503a7782SBrian Somers ipcp->my_compproto = (PROTO_VJCOMP << 16) + 5821342caedSBrian Somers ((ipcp->cfg.vj.slots - 1) << 8) + 5831342caedSBrian Somers ipcp->cfg.vj.slotcomp; 5841ae349f5Scvs2svn else 585503a7782SBrian Somers ipcp->my_compproto = 0; 5861342caedSBrian Somers sl_compress_init(&ipcp->vj.cslc, ipcp->cfg.vj.slots - 1); 58729e275ceSBrian Somers 588503a7782SBrian Somers ipcp->peer_reject = 0; 589503a7782SBrian Somers ipcp->my_reject = 0; 590d568d6c4SBrian Somers 59130949fd4SBrian Somers /* Copy startup values into ipcp->ns.dns */ 592d568d6c4SBrian Somers if (ipcp->cfg.ns.dns[0].s_addr != INADDR_NONE) 59330949fd4SBrian Somers memcpy(ipcp->ns.dns, ipcp->cfg.ns.dns, sizeof ipcp->ns.dns); 5941ae349f5Scvs2svn } 5951ae349f5Scvs2svn 596455aabc3SBrian Somers static int 59730949fd4SBrian Somers numaddresses(struct in_addr mask) 5983afe5ccbSBrian Somers { 59930949fd4SBrian Somers u_int32_t bit, haddr; 60030949fd4SBrian Somers int n; 6013afe5ccbSBrian Somers 60230949fd4SBrian Somers haddr = ntohl(mask.s_addr); 60330949fd4SBrian Somers bit = 1; 60430949fd4SBrian Somers n = 1; 60530949fd4SBrian Somers 60630949fd4SBrian Somers do { 60730949fd4SBrian Somers if (!(haddr & bit)) 60830949fd4SBrian Somers n <<= 1; 60930949fd4SBrian Somers } while (bit <<= 1); 61030949fd4SBrian Somers 61130949fd4SBrian Somers return n; 6123afe5ccbSBrian Somers } 6133afe5ccbSBrian Somers 61430949fd4SBrian Somers static int 61530949fd4SBrian Somers ipcp_proxyarp(struct ipcp *ipcp, 616057f1760SBrian Somers int (*proxyfun)(struct bundle *, struct in_addr), 61730949fd4SBrian Somers const struct iface_addr *addr) 61830949fd4SBrian Somers { 61930949fd4SBrian Somers struct bundle *bundle = ipcp->fsm.bundle; 62030949fd4SBrian Somers struct in_addr peer, mask, ip; 621057f1760SBrian Somers int n, ret; 62230949fd4SBrian Somers 62330949fd4SBrian Somers if (!ncpaddr_getip4(&addr->peer, &peer)) { 62430949fd4SBrian Somers log_Printf(LogERROR, "Oops, ipcp_proxyarp() called with unexpected addr\n"); 6253afe5ccbSBrian Somers return 0; 6263afe5ccbSBrian Somers } 6273afe5ccbSBrian Somers 62830949fd4SBrian Somers ret = 0; 62930949fd4SBrian Somers 63030949fd4SBrian Somers if (Enabled(bundle, OPT_PROXYALL)) { 63130949fd4SBrian Somers ncprange_getip4mask(&addr->ifa, &mask); 63230949fd4SBrian Somers if ((n = numaddresses(mask)) > 256) { 63330949fd4SBrian Somers log_Printf(LogWARN, "%s: Too many addresses for proxyall\n", 63430949fd4SBrian Somers ncprange_ntoa(&addr->ifa)); 63530949fd4SBrian Somers return 0; 63630949fd4SBrian Somers } 63730949fd4SBrian Somers ip.s_addr = peer.s_addr & mask.s_addr; 63830949fd4SBrian Somers if (n >= 4) { 63930949fd4SBrian Somers ip.s_addr = htonl(ntohl(ip.s_addr) + 1); 64030949fd4SBrian Somers n -= 2; 64130949fd4SBrian Somers } 64230949fd4SBrian Somers while (n) { 64330949fd4SBrian Somers if (!((ip.s_addr ^ peer.s_addr) & mask.s_addr)) { 644057f1760SBrian Somers if (!(ret = (*proxyfun)(bundle, ip))) 64530949fd4SBrian Somers break; 64630949fd4SBrian Somers n--; 64730949fd4SBrian Somers } 64830949fd4SBrian Somers ip.s_addr = htonl(ntohl(ip.s_addr) + 1); 64930949fd4SBrian Somers } 65030949fd4SBrian Somers ret = !n; 65130949fd4SBrian Somers } else if (Enabled(bundle, OPT_PROXY)) 652057f1760SBrian Somers ret = (*proxyfun)(bundle, peer); 65330949fd4SBrian Somers 65430949fd4SBrian Somers return ret; 65530949fd4SBrian Somers } 65630949fd4SBrian Somers 6573afe5ccbSBrian Somers static int 65830949fd4SBrian Somers ipcp_SetIPaddress(struct ipcp *ipcp, struct in_addr myaddr, 65930949fd4SBrian Somers struct in_addr hisaddr) 660455aabc3SBrian Somers { 66130949fd4SBrian Somers struct bundle *bundle = ipcp->fsm.bundle; 66230949fd4SBrian Somers struct ncpaddr myncpaddr, hisncpaddr; 6635ae08329SBrian Somers struct ncprange myrange; 66430949fd4SBrian Somers struct in_addr mask; 6655ae08329SBrian Somers struct sockaddr_storage ssdst, ssgw, ssmask; 6665ae08329SBrian Somers struct sockaddr *sadst, *sagw, *samask; 6675ae08329SBrian Somers 6685ae08329SBrian Somers sadst = (struct sockaddr *)&ssdst; 6695ae08329SBrian Somers sagw = (struct sockaddr *)&ssgw; 6705ae08329SBrian Somers samask = (struct sockaddr *)&ssmask; 67130949fd4SBrian Somers 67230949fd4SBrian Somers ncpaddr_setip4(&hisncpaddr, hisaddr); 67330949fd4SBrian Somers ncpaddr_setip4(&myncpaddr, myaddr); 67430949fd4SBrian Somers ncprange_sethost(&myrange, &myncpaddr); 675455aabc3SBrian Somers 676bc76350eSBrian Somers mask = addr2mask(myaddr); 677455aabc3SBrian Somers 67830949fd4SBrian Somers if (ipcp->ifmask.s_addr != INADDR_ANY && 67930949fd4SBrian Somers (ipcp->ifmask.s_addr & mask.s_addr) == mask.s_addr) 68030949fd4SBrian Somers ncprange_setip4mask(&myrange, ipcp->ifmask); 681455aabc3SBrian Somers 68230949fd4SBrian Somers if (!iface_Add(bundle->iface, &bundle->ncp, &myrange, &hisncpaddr, 68330949fd4SBrian Somers IFACE_ADD_FIRST|IFACE_FORCE_ADD|IFACE_SYSTEM)) 68430949fd4SBrian Somers return 0; 685455aabc3SBrian Somers 68630949fd4SBrian Somers if (!Enabled(bundle, OPT_IFACEALIAS)) 68730949fd4SBrian Somers iface_Clear(bundle->iface, &bundle->ncp, AF_INET, 68830949fd4SBrian Somers IFACE_CLEAR_ALIASES|IFACE_SYSTEM); 689455aabc3SBrian Somers 69030949fd4SBrian Somers if (bundle->ncp.cfg.sendpipe > 0 || bundle->ncp.cfg.recvpipe > 0) { 6915ae08329SBrian Somers ncprange_getsa(&myrange, &ssgw, &ssmask); 6925ae08329SBrian Somers ncpaddr_getsa(&hisncpaddr, &ssdst); 6935ae08329SBrian Somers rt_Update(bundle, sadst, sagw, samask); 69430949fd4SBrian Somers } 6953afe5ccbSBrian Somers 696610b185fSBrian Somers if (Enabled(bundle, OPT_SROUTES)) 69730949fd4SBrian Somers route_Change(bundle, bundle->ncp.route, &myncpaddr, &hisncpaddr); 698610b185fSBrian Somers 699972a1bcfSBrian Somers #ifndef NORADIUS 700972a1bcfSBrian Somers if (bundle->radius.valid) 70130949fd4SBrian Somers route_Change(bundle, bundle->radius.routes, &myncpaddr, &hisncpaddr); 702972a1bcfSBrian Somers #endif 703972a1bcfSBrian Somers 70430949fd4SBrian Somers return 1; /* Ok */ 705455aabc3SBrian Somers } 706455aabc3SBrian Somers 707455aabc3SBrian Somers static struct in_addr 7088fa6ebe4SBrian Somers ChooseHisAddr(struct bundle *bundle, struct in_addr gw) 709455aabc3SBrian Somers { 710455aabc3SBrian Somers struct in_addr try; 7113a2e4f62SBrian Somers u_long f; 712455aabc3SBrian Somers 7135828db6dSBrian Somers for (f = 0; f < bundle->ncp.ipcp.cfg.peer_list.nItems; f++) { 7145828db6dSBrian Somers try = iplist_next(&bundle->ncp.ipcp.cfg.peer_list); 7153a2e4f62SBrian Somers log_Printf(LogDEBUG, "ChooseHisAddr: Check item %ld (%s)\n", 716455aabc3SBrian Somers f, inet_ntoa(try)); 71730949fd4SBrian Somers if (ipcp_SetIPaddress(&bundle->ncp.ipcp, gw, try)) { 718dd7e2610SBrian Somers log_Printf(LogIPCP, "Selected IP address %s\n", inet_ntoa(try)); 719455aabc3SBrian Somers break; 720455aabc3SBrian Somers } 721455aabc3SBrian Somers } 722455aabc3SBrian Somers 7235828db6dSBrian Somers if (f == bundle->ncp.ipcp.cfg.peer_list.nItems) { 724dd7e2610SBrian Somers log_Printf(LogDEBUG, "ChooseHisAddr: All addresses in use !\n"); 725455aabc3SBrian Somers try.s_addr = INADDR_ANY; 726455aabc3SBrian Somers } 727455aabc3SBrian Somers 728455aabc3SBrian Somers return try; 729af57ed9fSAtsushi Murai } 730af57ed9fSAtsushi Murai 731af57ed9fSAtsushi Murai static void 732479508cfSBrian Somers IpcpInitRestartCounter(struct fsm *fp, int what) 733af57ed9fSAtsushi Murai { 7347308ec68SBrian Somers /* Set fsm timer load */ 735cd9647a1SBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 736cd9647a1SBrian Somers 737479508cfSBrian Somers fp->FsmTimer.load = ipcp->cfg.fsm.timeout * SECTICKS; 738479508cfSBrian Somers switch (what) { 739479508cfSBrian Somers case FSM_REQ_TIMER: 740479508cfSBrian Somers fp->restart = ipcp->cfg.fsm.maxreq; 741479508cfSBrian Somers break; 742479508cfSBrian Somers case FSM_TRM_TIMER: 743479508cfSBrian Somers fp->restart = ipcp->cfg.fsm.maxtrm; 744479508cfSBrian Somers break; 745479508cfSBrian Somers default: 746479508cfSBrian Somers fp->restart = 1; 747479508cfSBrian Somers break; 748479508cfSBrian Somers } 749af57ed9fSAtsushi Murai } 750af57ed9fSAtsushi Murai 751af57ed9fSAtsushi Murai static void 752944f7098SBrian Somers IpcpSendConfigReq(struct fsm *fp) 753af57ed9fSAtsushi Murai { 7547308ec68SBrian Somers /* Send config REQ please */ 7558c07a7b2SBrian Somers struct physical *p = link2physical(fp->link); 756aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 757eb1ecbb2SBrian Somers u_char buff[MAX_FSM_OPT_LEN]; 758ff360cc9SBrian Somers struct fsm_opt *o; 759af57ed9fSAtsushi Murai 760ff360cc9SBrian Somers o = (struct fsm_opt *)buff; 76130c2f2ffSBrian Somers 762dd7e2610SBrian Somers if ((p && !physical_IsSync(p)) || !REJECTED(ipcp, TY_IPADDR)) { 7639e8ec64bSBrian Somers memcpy(o->data, &ipcp->my_ip.s_addr, 4); 764ff360cc9SBrian Somers INC_FSM_OPT(TY_IPADDR, 6, o); 7650053cc58SBrian Somers } 7660053cc58SBrian Somers 767e43ebac1SBrian Somers if (ipcp->my_compproto && !REJECTED(ipcp, TY_COMPPROTO)) { 76883d1af55SBrian Somers if (ipcp->heis1172) { 7699e8ec64bSBrian Somers u_int16_t proto = PROTO_VJCOMP; 7709e8ec64bSBrian Somers 7719e8ec64bSBrian Somers ua_htons(&proto, o->data); 772ff360cc9SBrian Somers INC_FSM_OPT(TY_COMPPROTO, 4, o); 7730053cc58SBrian Somers } else { 7747686a200SBrian Somers struct compreq req; 7757686a200SBrian Somers 7767686a200SBrian Somers req.proto = htons(ipcp->my_compproto >> 16); 7777686a200SBrian Somers req.slots = (ipcp->my_compproto >> 8) & 255; 7787686a200SBrian Somers req.compcid = ipcp->my_compproto & 1; 7797686a200SBrian Somers memcpy(o->data, &req, 4); 780ff360cc9SBrian Somers INC_FSM_OPT(TY_COMPPROTO, 6, o); 7810053cc58SBrian Somers } 782af57ed9fSAtsushi Murai } 7832267893fSBrian Somers 78430949fd4SBrian Somers if (IsEnabled(ipcp->cfg.ns.dns_neg)) { 78530949fd4SBrian Somers if (!REJECTED(ipcp, TY_PRIMARY_DNS - TY_ADJUST_NS)) { 78630949fd4SBrian Somers memcpy(o->data, &ipcp->ns.dns[0].s_addr, 4); 787ff360cc9SBrian Somers INC_FSM_OPT(TY_PRIMARY_DNS, 6, o); 7887d39b1e3SBrian Somers } 7897d39b1e3SBrian Somers 79030949fd4SBrian Somers if (!REJECTED(ipcp, TY_SECONDARY_DNS - TY_ADJUST_NS)) { 79130949fd4SBrian Somers memcpy(o->data, &ipcp->ns.dns[1].s_addr, 4); 792ff360cc9SBrian Somers INC_FSM_OPT(TY_SECONDARY_DNS, 6, o); 7933edeb0c6SBrian Somers } 79430949fd4SBrian Somers } 7953edeb0c6SBrian Somers 796411675baSBrian Somers fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff, 797411675baSBrian Somers MB_IPCPOUT); 798af57ed9fSAtsushi Murai } 799af57ed9fSAtsushi Murai 800af57ed9fSAtsushi Murai static void 801057f1760SBrian Somers IpcpSentTerminateReq(struct fsm *fp __unused) 802af57ed9fSAtsushi Murai { 8037308ec68SBrian Somers /* Term REQ just sent by FSM */ 804af57ed9fSAtsushi Murai } 805af57ed9fSAtsushi Murai 806af57ed9fSAtsushi Murai static void 8072267893fSBrian Somers IpcpSendTerminateAck(struct fsm *fp, u_char id) 808af57ed9fSAtsushi Murai { 8097308ec68SBrian Somers /* Send Term ACK please */ 810411675baSBrian Somers fsm_Output(fp, CODE_TERMACK, id, NULL, 0, MB_IPCPOUT); 811af57ed9fSAtsushi Murai } 812af57ed9fSAtsushi Murai 813af57ed9fSAtsushi Murai static void 814944f7098SBrian Somers IpcpLayerStart(struct fsm *fp) 815af57ed9fSAtsushi Murai { 8167308ec68SBrian Somers /* We're about to start up ! */ 817897f9429SBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 818897f9429SBrian Somers 8193a2e4f62SBrian Somers log_Printf(LogIPCP, "%s: LayerStart.\n", fp->link->name); 820897f9429SBrian Somers throughput_start(&ipcp->throughput, "IPCP throughput", 821897f9429SBrian Somers Enabled(fp->bundle, OPT_THROUGHPUT)); 822479508cfSBrian Somers fp->more.reqs = fp->more.naks = fp->more.rejs = ipcp->cfg.fsm.maxreq * 3; 8235e3b2d68SBrian Somers ipcp->peer_req = 0; 824af57ed9fSAtsushi Murai } 825af57ed9fSAtsushi Murai 826af57ed9fSAtsushi Murai static void 827944f7098SBrian Somers IpcpLayerFinish(struct fsm *fp) 828af57ed9fSAtsushi Murai { 8297308ec68SBrian Somers /* We're now down */ 830897f9429SBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 831897f9429SBrian Somers 8323a2e4f62SBrian Somers log_Printf(LogIPCP, "%s: LayerFinish.\n", fp->link->name); 833897f9429SBrian Somers throughput_stop(&ipcp->throughput); 834897f9429SBrian Somers throughput_log(&ipcp->throughput, LogIPCP, NULL); 8351ae349f5Scvs2svn } 8361ae349f5Scvs2svn 83730949fd4SBrian Somers /* 83830949fd4SBrian Somers * Called from iface_Add() via ncp_IfaceAddrAdded() 83930949fd4SBrian Somers */ 84068a0f0ccSBrian Somers void 84130949fd4SBrian Somers ipcp_IfaceAddrAdded(struct ipcp *ipcp, const struct iface_addr *addr) 84268a0f0ccSBrian Somers { 84330949fd4SBrian Somers struct bundle *bundle = ipcp->fsm.bundle; 84468a0f0ccSBrian Somers 84530949fd4SBrian Somers if (Enabled(bundle, OPT_PROXY) || Enabled(bundle, OPT_PROXYALL)) 84630949fd4SBrian Somers ipcp_proxyarp(ipcp, arp_SetProxy, addr); 84768a0f0ccSBrian Somers } 84868a0f0ccSBrian Somers 84930949fd4SBrian Somers /* 85030949fd4SBrian Somers * Called from iface_Clear() and iface_Delete() via ncp_IfaceAddrDeleted() 85130949fd4SBrian Somers */ 85230949fd4SBrian Somers void 85330949fd4SBrian Somers ipcp_IfaceAddrDeleted(struct ipcp *ipcp, const struct iface_addr *addr) 85430949fd4SBrian Somers { 85530949fd4SBrian Somers struct bundle *bundle = ipcp->fsm.bundle; 85630949fd4SBrian Somers 85730949fd4SBrian Somers if (Enabled(bundle, OPT_PROXY) || Enabled(bundle, OPT_PROXYALL)) 85830949fd4SBrian Somers ipcp_proxyarp(ipcp, arp_ClearProxy, addr); 859af57ed9fSAtsushi Murai } 860af57ed9fSAtsushi Murai 861af57ed9fSAtsushi Murai static void 862944f7098SBrian Somers IpcpLayerDown(struct fsm *fp) 863af57ed9fSAtsushi Murai { 8647308ec68SBrian Somers /* About to come down */ 865aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 86630949fd4SBrian Somers static int recursing; 86730949fd4SBrian Somers char addr[16]; 868455aabc3SBrian Somers 869aa857470SBrian Somers if (!recursing++) { 87030949fd4SBrian Somers snprintf(addr, sizeof addr, "%s", inet_ntoa(ipcp->my_ip)); 87130949fd4SBrian Somers log_Printf(LogIPCP, "%s: LayerDown: %s\n", fp->link->name, addr); 872455aabc3SBrian Somers 873794c9bbcSBrian Somers #ifndef NORADIUS 874794c9bbcSBrian Somers radius_Account(&fp->bundle->radius, &fp->bundle->radacct, 875cf7c10d0SHajimu UMEMOTO fp->bundle->links, RAD_STOP, &ipcp->throughput); 876635ad5f0SBrian Somers 877635ad5f0SBrian Somers if (fp->bundle->radius.cfg.file && fp->bundle->radius.filterid) 878635ad5f0SBrian Somers system_Select(fp->bundle, fp->bundle->radius.filterid, LINKDOWNFILE, 879635ad5f0SBrian Somers NULL, NULL); 880e715b13bSBrian Somers radius_StopTimer(&fp->bundle->radius); 881794c9bbcSBrian Somers #endif 882794c9bbcSBrian Somers 883455aabc3SBrian Somers /* 884455aabc3SBrian Somers * XXX this stuff should really live in the FSM. Our config should 885455aabc3SBrian Somers * associate executable sections in files with events. 886455aabc3SBrian Somers */ 88730949fd4SBrian Somers if (system_Select(fp->bundle, addr, LINKDOWNFILE, NULL, NULL) < 0) { 88849052c95SBrian Somers if (bundle_GetLabel(fp->bundle)) { 889dd7e2610SBrian Somers if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle), 89030291ffbSBrian Somers LINKDOWNFILE, NULL, NULL) < 0) 89130291ffbSBrian Somers system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL); 892455aabc3SBrian Somers } else 89330291ffbSBrian Somers system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL); 894af57ed9fSAtsushi Murai } 895af57ed9fSAtsushi Murai 896972a1bcfSBrian Somers ipcp_Setup(ipcp, INADDR_NONE); 8971ae349f5Scvs2svn } 898aa857470SBrian Somers recursing--; 899aa857470SBrian Somers } 9001ae349f5Scvs2svn 901dd0645c5SBrian Somers int 902dd0645c5SBrian Somers ipcp_InterfaceUp(struct ipcp *ipcp) 903dd0645c5SBrian Somers { 90430949fd4SBrian Somers if (!ipcp_SetIPaddress(ipcp, ipcp->my_ip, ipcp->peer_ip)) { 905a33b2ef7SBrian Somers log_Printf(LogERROR, "ipcp_InterfaceUp: unable to set ip address\n"); 906dd0645c5SBrian Somers return 0; 907dd0645c5SBrian Somers } 908dd0645c5SBrian Somers 909448374baSBrian Somers if (!iface_SetFlags(ipcp->fsm.bundle->iface->name, IFF_UP)) { 910448374baSBrian Somers log_Printf(LogERROR, "ipcp_InterfaceUp: Can't set the IFF_UP flag on %s\n", 911448374baSBrian Somers ipcp->fsm.bundle->iface->name); 912448374baSBrian Somers return 0; 913448374baSBrian Somers } 914448374baSBrian Somers 91567b072f7SBrian Somers #ifndef NONAT 91667b072f7SBrian Somers if (ipcp->fsm.bundle->NatEnabled) 917615ad4f9SBrian Somers PacketAliasSetAddress(ipcp->my_ip); 918dd0645c5SBrian Somers #endif 919dd0645c5SBrian Somers 920dd0645c5SBrian Somers return 1; 921dd0645c5SBrian Somers } 922dd0645c5SBrian Somers 9236f384573SBrian Somers static int 924944f7098SBrian Somers IpcpLayerUp(struct fsm *fp) 925af57ed9fSAtsushi Murai { 9267308ec68SBrian Somers /* We're now up */ 927aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 9288fa6ebe4SBrian Somers char tbuff[16]; 929af57ed9fSAtsushi Murai 9303a2e4f62SBrian Somers log_Printf(LogIPCP, "%s: LayerUp.\n", fp->link->name); 9318fa6ebe4SBrian Somers snprintf(tbuff, sizeof tbuff, "%s", inet_ntoa(ipcp->my_ip)); 9328fa6ebe4SBrian Somers log_Printf(LogIPCP, "myaddr %s hisaddr = %s\n", 9338fa6ebe4SBrian Somers tbuff, inet_ntoa(ipcp->peer_ip)); 93403604f35SBrian Somers 935503a7782SBrian Somers if (ipcp->peer_compproto >> 16 == PROTO_VJCOMP) 936eaa4df37SBrian Somers sl_compress_init(&ipcp->vj.cslc, (ipcp->peer_compproto >> 8) & 255); 93703604f35SBrian Somers 938dd0645c5SBrian Somers if (!ipcp_InterfaceUp(ipcp)) 9396f384573SBrian Somers return 0; 940455aabc3SBrian Somers 941794c9bbcSBrian Somers #ifndef NORADIUS 942cf7c10d0SHajimu UMEMOTO radius_Account_Set_Ip(&fp->bundle->radacct, &ipcp->peer_ip, &ipcp->ifmask); 943794c9bbcSBrian Somers radius_Account(&fp->bundle->radius, &fp->bundle->radacct, fp->bundle->links, 944cf7c10d0SHajimu UMEMOTO RAD_START, &ipcp->throughput); 945635ad5f0SBrian Somers 946635ad5f0SBrian Somers if (fp->bundle->radius.cfg.file && fp->bundle->radius.filterid) 947635ad5f0SBrian Somers system_Select(fp->bundle, fp->bundle->radius.filterid, LINKUPFILE, 948635ad5f0SBrian Somers NULL, NULL); 949e715b13bSBrian Somers radius_StartTimer(fp->bundle); 950794c9bbcSBrian Somers #endif 951794c9bbcSBrian Somers 952455aabc3SBrian Somers /* 953455aabc3SBrian Somers * XXX this stuff should really live in the FSM. Our config should 954455aabc3SBrian Somers * associate executable sections in files with events. 955455aabc3SBrian Somers */ 9568fa6ebe4SBrian Somers if (system_Select(fp->bundle, tbuff, LINKUPFILE, NULL, NULL) < 0) { 95749052c95SBrian Somers if (bundle_GetLabel(fp->bundle)) { 958dd7e2610SBrian Somers if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle), 95930291ffbSBrian Somers LINKUPFILE, NULL, NULL) < 0) 96030291ffbSBrian Somers system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL); 961455aabc3SBrian Somers } else 96230291ffbSBrian Somers system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL); 963af57ed9fSAtsushi Murai } 964af57ed9fSAtsushi Murai 965479508cfSBrian Somers fp->more.reqs = fp->more.naks = fp->more.rejs = ipcp->cfg.fsm.maxreq * 3; 9660f2f3eb3SBrian Somers log_DisplayPrompts(); 967479508cfSBrian Somers 9686f384573SBrian Somers return 1; 969af57ed9fSAtsushi Murai } 970af57ed9fSAtsushi Murai 971af57ed9fSAtsushi Murai static void 9725f73635bSBrian Somers ipcp_ValidateReq(struct ipcp *ipcp, struct in_addr ip, struct fsm_decode *dec) 9735f73635bSBrian Somers { 9745f73635bSBrian Somers struct bundle *bundle = ipcp->fsm.bundle; 9755f73635bSBrian Somers struct iface *iface = bundle->iface; 97630949fd4SBrian Somers struct in_addr myaddr, peer; 977057f1760SBrian Somers unsigned n; 9785f73635bSBrian Somers 9795f73635bSBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 98030949fd4SBrian Somers ncprange_getip4addr(&ipcp->cfg.my_range, &myaddr); 9815f73635bSBrian Somers if (ip.s_addr == INADDR_ANY || 9825f73635bSBrian Somers iplist_ip2pos(&ipcp->cfg.peer_list, ip) < 0 || 98330949fd4SBrian Somers !ipcp_SetIPaddress(ipcp, myaddr, ip)) { 9845f73635bSBrian Somers log_Printf(LogIPCP, "%s: Address invalid or already in use\n", 9855f73635bSBrian Somers inet_ntoa(ip)); 9865f73635bSBrian Somers /* 9875f73635bSBrian Somers * If we've already had a valid address configured for the peer, 9885f73635bSBrian Somers * try NAKing with that so that we don't have to upset things 9895f73635bSBrian Somers * too much. 9905f73635bSBrian Somers */ 99130949fd4SBrian Somers for (n = 0; n < iface->addrs; n++) { 99230949fd4SBrian Somers if (!ncpaddr_getip4(&iface->addr[n].peer, &peer)) 99330949fd4SBrian Somers continue; 99430949fd4SBrian Somers if (iplist_ip2pos(&ipcp->cfg.peer_list, peer) >= 0) { 99530949fd4SBrian Somers ipcp->peer_ip = peer; 9965f73635bSBrian Somers break; 9975f73635bSBrian Somers } 99830949fd4SBrian Somers } 9995f73635bSBrian Somers 100030949fd4SBrian Somers if (n == iface->addrs) { 10015f73635bSBrian Somers /* Just pick an IP number from our list */ 100230949fd4SBrian Somers ipcp->peer_ip = ChooseHisAddr(bundle, myaddr); 100330949fd4SBrian Somers } 10045f73635bSBrian Somers 10055f73635bSBrian Somers if (ipcp->peer_ip.s_addr == INADDR_ANY) { 10065f73635bSBrian Somers *dec->rejend++ = TY_IPADDR; 10075f73635bSBrian Somers *dec->rejend++ = 6; 10085f73635bSBrian Somers memcpy(dec->rejend, &ip.s_addr, 4); 10095f73635bSBrian Somers dec->rejend += 4; 10105f73635bSBrian Somers } else { 10115f73635bSBrian Somers *dec->nakend++ = TY_IPADDR; 10125f73635bSBrian Somers *dec->nakend++ = 6; 10135f73635bSBrian Somers memcpy(dec->nakend, &ipcp->peer_ip.s_addr, 4); 10145f73635bSBrian Somers dec->nakend += 4; 10155f73635bSBrian Somers } 10165f73635bSBrian Somers return; 10175f73635bSBrian Somers } 10183c34956aSBrian Somers } else if (ip.s_addr == INADDR_ANY || 10193c34956aSBrian Somers !ncprange_containsip4(&ipcp->cfg.peer_range, ip)) { 10205f73635bSBrian Somers /* 10215f73635bSBrian Somers * If the destination address is not acceptable, NAK with what we 10225f73635bSBrian Somers * want to use. 10235f73635bSBrian Somers */ 10245f73635bSBrian Somers *dec->nakend++ = TY_IPADDR; 10255f73635bSBrian Somers *dec->nakend++ = 6; 102630949fd4SBrian Somers for (n = 0; n < iface->addrs; n++) 102730949fd4SBrian Somers if (ncprange_contains(&ipcp->cfg.peer_range, &iface->addr[n].peer)) { 10285f73635bSBrian Somers /* We prefer the already-configured address */ 102930949fd4SBrian Somers ncpaddr_getip4addr(&iface->addr[n].peer, (u_int32_t *)dec->nakend); 10305f73635bSBrian Somers break; 10315f73635bSBrian Somers } 10325f73635bSBrian Somers 103330949fd4SBrian Somers if (n == iface->addrs) 10345f73635bSBrian Somers memcpy(dec->nakend, &ipcp->peer_ip.s_addr, 4); 10355f73635bSBrian Somers 10365f73635bSBrian Somers dec->nakend += 4; 10375f73635bSBrian Somers return; 10385f73635bSBrian Somers } 10395f73635bSBrian Somers 10405f73635bSBrian Somers ipcp->peer_ip = ip; 10415f73635bSBrian Somers *dec->ackend++ = TY_IPADDR; 10425f73635bSBrian Somers *dec->ackend++ = 6; 10435f73635bSBrian Somers memcpy(dec->ackend, &ip.s_addr, 4); 10445f73635bSBrian Somers dec->ackend += 4; 10455f73635bSBrian Somers } 10465f73635bSBrian Somers 10475f73635bSBrian Somers static void 1048ff360cc9SBrian Somers IpcpDecodeConfig(struct fsm *fp, u_char *cp, u_char *end, int mode_type, 104930c2f2ffSBrian Somers struct fsm_decode *dec) 1050af57ed9fSAtsushi Murai { 10517308ec68SBrian Somers /* Deal with incoming PROTO_IPCP */ 105230949fd4SBrian Somers struct ncpaddr ncpaddr; 1053aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 1054ff360cc9SBrian Somers int gotdnsnak; 1055fe3125a0SBrian Somers u_int32_t compproto; 1056eb1ecbb2SBrian Somers struct compreq pcomp; 1057d568d6c4SBrian Somers struct in_addr ipaddr, dstipaddr, have_ip; 105830c2f2ffSBrian Somers char tbuff[100], tbuff2[100]; 1059ff360cc9SBrian Somers struct fsm_opt *opt, nak; 1060af57ed9fSAtsushi Murai 10613edeb0c6SBrian Somers gotdnsnak = 0; 1062af57ed9fSAtsushi Murai 1063057f1760SBrian Somers while (end - cp >= (int)sizeof(opt->hdr)) { 1064ff360cc9SBrian Somers if ((opt = fsm_readopt(&cp)) == NULL) 1065d47dceb8SBrian Somers break; 1066d47dceb8SBrian Somers 1067ff360cc9SBrian Somers snprintf(tbuff, sizeof tbuff, " %s[%d]", protoname(opt->hdr.id), 1068ff360cc9SBrian Somers opt->hdr.len); 1069af57ed9fSAtsushi Murai 1070ff360cc9SBrian Somers switch (opt->hdr.id) { 1071af57ed9fSAtsushi Murai case TY_IPADDR: /* RFC1332 */ 1072ff360cc9SBrian Somers memcpy(&ipaddr.s_addr, opt->data, 4); 1073dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 1074af57ed9fSAtsushi Murai 10759780ef31SBrian Somers switch (mode_type) { 1076af57ed9fSAtsushi Murai case MODE_REQ: 10775e3b2d68SBrian Somers ipcp->peer_req = 1; 10785f73635bSBrian Somers ipcp_ValidateReq(ipcp, ipaddr, dec); 1079af57ed9fSAtsushi Murai break; 10808fa6ebe4SBrian Somers 1081af57ed9fSAtsushi Murai case MODE_NAK: 108230949fd4SBrian Somers if (ncprange_containsip4(&ipcp->cfg.my_range, ipaddr)) { 1083bcc332bdSBrian Somers /* Use address suggested by peer */ 108470ee81ffSBrian Somers snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s ", tbuff, 1085503a7782SBrian Somers inet_ntoa(ipcp->my_ip)); 1086dd7e2610SBrian Somers log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 1087503a7782SBrian Somers ipcp->my_ip = ipaddr; 108830949fd4SBrian Somers ncpaddr_setip4(&ncpaddr, ipcp->my_ip); 108930949fd4SBrian Somers bundle_AdjustFilters(fp->bundle, &ncpaddr, NULL); 1090bcc332bdSBrian Somers } else { 1091dd7e2610SBrian Somers log_Printf(log_IsKept(LogIPCP) ? LogIPCP : LogPHASE, 10928390b576SBrian Somers "%s: Unacceptable address!\n", inet_ntoa(ipaddr)); 1093dd7e2610SBrian Somers fsm_Close(&ipcp->fsm); 1094af57ed9fSAtsushi Murai } 1095af57ed9fSAtsushi Murai break; 10968fa6ebe4SBrian Somers 1097af57ed9fSAtsushi Murai case MODE_REJ: 1098ff360cc9SBrian Somers ipcp->peer_reject |= (1 << opt->hdr.id); 1099af57ed9fSAtsushi Murai break; 1100af57ed9fSAtsushi Murai } 1101af57ed9fSAtsushi Murai break; 11028fa6ebe4SBrian Somers 1103af57ed9fSAtsushi Murai case TY_COMPPROTO: 1104eb1ecbb2SBrian Somers memcpy(&pcomp, opt->data, sizeof pcomp); 1105eb1ecbb2SBrian Somers compproto = (ntohs(pcomp.proto) << 16) + ((int)pcomp.slots << 8) + 1106eb1ecbb2SBrian Somers pcomp.compcid; 1107dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto)); 1108af57ed9fSAtsushi Murai 11099780ef31SBrian Somers switch (mode_type) { 1110af57ed9fSAtsushi Murai case MODE_REQ: 1111ff360cc9SBrian Somers if (!IsAccepted(ipcp->cfg.vj.neg)) 1112ff360cc9SBrian Somers fsm_rej(dec, opt); 1113ff360cc9SBrian Somers else { 1114ff360cc9SBrian Somers switch (opt->hdr.len) { 1115af57ed9fSAtsushi Murai case 4: /* RFC1172 */ 1116eb1ecbb2SBrian Somers if (ntohs(pcomp.proto) == PROTO_VJCOMP) { 11177686a200SBrian Somers log_Printf(LogWARN, "Peer is speaking RFC1172 compression " 11187686a200SBrian Somers "protocol !\n"); 111983d1af55SBrian Somers ipcp->heis1172 = 1; 1120503a7782SBrian Somers ipcp->peer_compproto = compproto; 1121ff360cc9SBrian Somers fsm_ack(dec, opt); 1122af57ed9fSAtsushi Murai } else { 1123eb1ecbb2SBrian Somers pcomp.proto = htons(PROTO_VJCOMP); 1124ff360cc9SBrian Somers nak.hdr.id = TY_COMPPROTO; 1125ff360cc9SBrian Somers nak.hdr.len = 4; 1126ff360cc9SBrian Somers memcpy(nak.data, &pcomp, 2); 1127ff360cc9SBrian Somers fsm_nak(dec, &nak); 1128af57ed9fSAtsushi Murai } 1129af57ed9fSAtsushi Murai break; 1130af57ed9fSAtsushi Murai case 6: /* RFC1332 */ 1131eb1ecbb2SBrian Somers if (ntohs(pcomp.proto) == PROTO_VJCOMP) { 1132eb1ecbb2SBrian Somers /* We know pcomp.slots' max value == MAX_VJ_STATES */ 1133eb1ecbb2SBrian Somers if (pcomp.slots >= MIN_VJ_STATES) { 11347686a200SBrian Somers /* Ok, we can do that */ 1135503a7782SBrian Somers ipcp->peer_compproto = compproto; 113683d1af55SBrian Somers ipcp->heis1172 = 0; 1137ff360cc9SBrian Somers fsm_ack(dec, opt); 1138af57ed9fSAtsushi Murai } else { 11397686a200SBrian Somers /* Get as close as we can to what he wants */ 11407686a200SBrian Somers ipcp->heis1172 = 0; 1141eb1ecbb2SBrian Somers pcomp.slots = MIN_VJ_STATES; 1142ff360cc9SBrian Somers nak.hdr.id = TY_COMPPROTO; 1143ff360cc9SBrian Somers nak.hdr.len = 4; 1144ff360cc9SBrian Somers memcpy(nak.data, &pcomp, 2); 1145ff360cc9SBrian Somers fsm_nak(dec, &nak); 11467686a200SBrian Somers } 11477686a200SBrian Somers } else { 11487686a200SBrian Somers /* What we really want */ 1149eb1ecbb2SBrian Somers pcomp.proto = htons(PROTO_VJCOMP); 1150eb1ecbb2SBrian Somers pcomp.slots = DEF_VJ_STATES; 1151eb1ecbb2SBrian Somers pcomp.compcid = 1; 1152ff360cc9SBrian Somers nak.hdr.id = TY_COMPPROTO; 1153ff360cc9SBrian Somers nak.hdr.len = 6; 1154ff360cc9SBrian Somers memcpy(nak.data, &pcomp, sizeof pcomp); 1155ff360cc9SBrian Somers fsm_nak(dec, &nak); 1156af57ed9fSAtsushi Murai } 1157af57ed9fSAtsushi Murai break; 1158af57ed9fSAtsushi Murai default: 1159ff360cc9SBrian Somers fsm_rej(dec, opt); 1160af57ed9fSAtsushi Murai break; 1161af57ed9fSAtsushi Murai } 1162af57ed9fSAtsushi Murai } 1163af57ed9fSAtsushi Murai break; 11648fa6ebe4SBrian Somers 1165af57ed9fSAtsushi Murai case MODE_NAK: 1166eb1ecbb2SBrian Somers if (ntohs(pcomp.proto) == PROTO_VJCOMP) { 1167eb1ecbb2SBrian Somers /* We know pcomp.slots' max value == MAX_VJ_STATES */ 1168eb1ecbb2SBrian Somers if (pcomp.slots < MIN_VJ_STATES) 1169eb1ecbb2SBrian Somers pcomp.slots = MIN_VJ_STATES; 1170eb1ecbb2SBrian Somers compproto = (ntohs(pcomp.proto) << 16) + (pcomp.slots << 8) + 1171eb1ecbb2SBrian Somers pcomp.compcid; 11727686a200SBrian Somers } else 11737686a200SBrian Somers compproto = 0; 1174dd7e2610SBrian Somers log_Printf(LogIPCP, "%s changing compproto: %08x --> %08x\n", 1175503a7782SBrian Somers tbuff, ipcp->my_compproto, compproto); 1176503a7782SBrian Somers ipcp->my_compproto = compproto; 1177af57ed9fSAtsushi Murai break; 11788fa6ebe4SBrian Somers 1179af57ed9fSAtsushi Murai case MODE_REJ: 1180ff360cc9SBrian Somers ipcp->peer_reject |= (1 << opt->hdr.id); 1181af57ed9fSAtsushi Murai break; 1182af57ed9fSAtsushi Murai } 1183af57ed9fSAtsushi Murai break; 11848fa6ebe4SBrian Somers 1185af57ed9fSAtsushi Murai case TY_IPADDRS: /* RFC1172 */ 1186ff360cc9SBrian Somers memcpy(&ipaddr.s_addr, opt->data, 4); 1187ff360cc9SBrian Somers memcpy(&dstipaddr.s_addr, opt->data + 4, 4); 118870ee81ffSBrian Somers snprintf(tbuff2, sizeof tbuff2, "%s %s,", tbuff, inet_ntoa(ipaddr)); 1189dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr)); 1190af57ed9fSAtsushi Murai 11919780ef31SBrian Somers switch (mode_type) { 1192af57ed9fSAtsushi Murai case MODE_REQ: 1193ff360cc9SBrian Somers fsm_rej(dec, opt); 1194af57ed9fSAtsushi Murai break; 11958fa6ebe4SBrian Somers 1196af57ed9fSAtsushi Murai case MODE_NAK: 1197af57ed9fSAtsushi Murai case MODE_REJ: 1198af57ed9fSAtsushi Murai break; 1199af57ed9fSAtsushi Murai } 1200af57ed9fSAtsushi Murai break; 1201d8e55738SJordan K. Hubbard 12023edeb0c6SBrian Somers case TY_PRIMARY_DNS: /* DNS negotiation (rfc1877) */ 1203d8e55738SJordan K. Hubbard case TY_SECONDARY_DNS: 1204ff360cc9SBrian Somers memcpy(&ipaddr.s_addr, opt->data, 4); 1205dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 12063edeb0c6SBrian Somers 12079780ef31SBrian Somers switch (mode_type) { 1208d8e55738SJordan K. Hubbard case MODE_REQ: 12093edeb0c6SBrian Somers if (!IsAccepted(ipcp->cfg.ns.dns_neg)) { 1210ff360cc9SBrian Somers ipcp->my_reject |= (1 << (opt->hdr.id - TY_ADJUST_NS)); 1211ff360cc9SBrian Somers fsm_rej(dec, opt); 1212d8e55738SJordan K. Hubbard break; 1213d8e55738SJordan K. Hubbard } 1214ff360cc9SBrian Somers have_ip = ipcp->ns.dns[opt->hdr.id == TY_PRIMARY_DNS ? 0 : 1]; 1215d568d6c4SBrian Somers 1216ff360cc9SBrian Somers if (opt->hdr.id == TY_PRIMARY_DNS && ipaddr.s_addr != have_ip.s_addr && 121730949fd4SBrian Somers ipaddr.s_addr == ipcp->ns.dns[1].s_addr) { 1218d568d6c4SBrian Somers /* Swap 'em 'round */ 121930949fd4SBrian Somers ipcp->ns.dns[0] = ipcp->ns.dns[1]; 122030949fd4SBrian Somers ipcp->ns.dns[1] = have_ip; 122130949fd4SBrian Somers have_ip = ipcp->ns.dns[0]; 12223edeb0c6SBrian Somers } 1223944f7098SBrian Somers 12243edeb0c6SBrian Somers if (ipaddr.s_addr != have_ip.s_addr) { 12251ae349f5Scvs2svn /* 12263edeb0c6SBrian Somers * The client has got the DNS stuff wrong (first request) so 12271ae349f5Scvs2svn * we'll tell 'em how it is 12281ae349f5Scvs2svn */ 1229ff360cc9SBrian Somers nak.hdr.id = opt->hdr.id; 1230ff360cc9SBrian Somers nak.hdr.len = 6; 1231ff360cc9SBrian Somers memcpy(nak.data, &have_ip.s_addr, 4); 1232ff360cc9SBrian Somers fsm_nak(dec, &nak); 12333edeb0c6SBrian Somers } else { 1234d8e55738SJordan K. Hubbard /* 12359d5abbddSJens Schweikhardt * Otherwise they have it right (this time) so we send an ack packet 1236944f7098SBrian Somers * back confirming it... end of story 1237d8e55738SJordan K. Hubbard */ 1238ff360cc9SBrian Somers fsm_ack(dec, opt); 12393edeb0c6SBrian Somers } 1240d8e55738SJordan K. Hubbard break; 12418fa6ebe4SBrian Somers 1242d568d6c4SBrian Somers case MODE_NAK: 12433edeb0c6SBrian Somers if (IsEnabled(ipcp->cfg.ns.dns_neg)) { 12443edeb0c6SBrian Somers gotdnsnak = 1; 1245ff360cc9SBrian Somers memcpy(&ipcp->ns.dns[opt->hdr.id == TY_PRIMARY_DNS ? 0 : 1].s_addr, 1246ff360cc9SBrian Somers opt->data, 4); 12473edeb0c6SBrian Somers } 1248d8e55738SJordan K. Hubbard break; 12498fa6ebe4SBrian Somers 12503edeb0c6SBrian Somers case MODE_REJ: /* Can't do much, stop asking */ 1251ff360cc9SBrian Somers ipcp->peer_reject |= (1 << (opt->hdr.id - TY_ADJUST_NS)); 1252d8e55738SJordan K. Hubbard break; 1253d8e55738SJordan K. Hubbard } 1254d8e55738SJordan K. Hubbard break; 1255d8e55738SJordan K. Hubbard 12563edeb0c6SBrian Somers case TY_PRIMARY_NBNS: /* M$ NetBIOS nameserver hack (rfc1877) */ 1257d8e55738SJordan K. Hubbard case TY_SECONDARY_NBNS: 1258ff360cc9SBrian Somers memcpy(&ipaddr.s_addr, opt->data, 4); 1259dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 12603edeb0c6SBrian Somers 12619780ef31SBrian Somers switch (mode_type) { 1262d8e55738SJordan K. Hubbard case MODE_REQ: 12633edeb0c6SBrian Somers have_ip.s_addr = 1264ff360cc9SBrian Somers ipcp->cfg.ns.nbns[opt->hdr.id == TY_PRIMARY_NBNS ? 0 : 1].s_addr; 12653edeb0c6SBrian Somers 12663edeb0c6SBrian Somers if (have_ip.s_addr == INADDR_ANY) { 1267dd7e2610SBrian Somers log_Printf(LogIPCP, "NBNS REQ - rejected - nbns not set\n"); 1268ff360cc9SBrian Somers ipcp->my_reject |= (1 << (opt->hdr.id - TY_ADJUST_NS)); 1269ff360cc9SBrian Somers fsm_rej(dec, opt); 1270d8e55738SJordan K. Hubbard break; 1271d8e55738SJordan K. Hubbard } 12723edeb0c6SBrian Somers 12733edeb0c6SBrian Somers if (ipaddr.s_addr != have_ip.s_addr) { 1274ff360cc9SBrian Somers nak.hdr.id = opt->hdr.id; 1275ff360cc9SBrian Somers nak.hdr.len = 6; 1276ff360cc9SBrian Somers memcpy(nak.data, &have_ip.s_addr, 4); 1277ff360cc9SBrian Somers fsm_nak(dec, &nak); 1278ff360cc9SBrian Somers } else 1279ff360cc9SBrian Somers fsm_ack(dec, opt); 1280d8e55738SJordan K. Hubbard break; 12818fa6ebe4SBrian Somers 1282d8e55738SJordan K. Hubbard case MODE_NAK: 1283ff360cc9SBrian Somers log_Printf(LogIPCP, "MS NBNS req %d - NAK??\n", opt->hdr.id); 1284d8e55738SJordan K. Hubbard break; 12858fa6ebe4SBrian Somers 1286d8e55738SJordan K. Hubbard case MODE_REJ: 1287ff360cc9SBrian Somers log_Printf(LogIPCP, "MS NBNS req %d - REJ??\n", opt->hdr.id); 1288d8e55738SJordan K. Hubbard break; 1289d8e55738SJordan K. Hubbard } 1290d8e55738SJordan K. Hubbard break; 1291d8e55738SJordan K. Hubbard 1292af57ed9fSAtsushi Murai default: 129330c2f2ffSBrian Somers if (mode_type != MODE_NOP) { 1294ff360cc9SBrian Somers ipcp->my_reject |= (1 << opt->hdr.id); 1295ff360cc9SBrian Somers fsm_rej(dec, opt); 129630c2f2ffSBrian Somers } 1297af57ed9fSAtsushi Murai break; 1298af57ed9fSAtsushi Murai } 1299af57ed9fSAtsushi Murai } 13001342caedSBrian Somers 1301d568d6c4SBrian Somers if (gotdnsnak) { 1302d568d6c4SBrian Somers if (ipcp->ns.writable) { 1303d568d6c4SBrian Somers log_Printf(LogDEBUG, "Updating resolver\n"); 1304d568d6c4SBrian Somers if (!ipcp_WriteDNS(ipcp)) { 13053edeb0c6SBrian Somers ipcp->peer_reject |= (1 << (TY_PRIMARY_DNS - TY_ADJUST_NS)); 13063edeb0c6SBrian Somers ipcp->peer_reject |= (1 << (TY_SECONDARY_DNS - TY_ADJUST_NS)); 1307d568d6c4SBrian Somers } else 130830949fd4SBrian Somers bundle_AdjustDNS(fp->bundle); 1309d568d6c4SBrian Somers } else { 1310d568d6c4SBrian Somers log_Printf(LogDEBUG, "Not updating resolver (readonly)\n"); 131130949fd4SBrian Somers bundle_AdjustDNS(fp->bundle); 1312d568d6c4SBrian Somers } 13133edeb0c6SBrian Somers } 13143edeb0c6SBrian Somers 1315e43ebac1SBrian Somers if (mode_type != MODE_NOP) { 13165e3b2d68SBrian Somers if (mode_type == MODE_REQ && !ipcp->peer_req) { 13175e3b2d68SBrian Somers if (dec->rejend == dec->rej && dec->nakend == dec->nak) { 13185e3b2d68SBrian Somers /* 13195e3b2d68SBrian Somers * Pretend the peer has requested an IP. 13205e3b2d68SBrian Somers * We do this to ensure that we only send one NAK if the only 13215e3b2d68SBrian Somers * reason for the NAK is because the peer isn't sending a 13225e3b2d68SBrian Somers * TY_IPADDR REQ. This stops us from repeatedly trying to tell 13235e3b2d68SBrian Somers * the peer that we have to have an IP address on their end. 13245e3b2d68SBrian Somers */ 13255e3b2d68SBrian Somers ipcp->peer_req = 1; 13265e3b2d68SBrian Somers } 13275f73635bSBrian Somers ipaddr.s_addr = INADDR_ANY; 13285f73635bSBrian Somers ipcp_ValidateReq(ipcp, ipaddr, dec); 13295f73635bSBrian Somers } 1330ff360cc9SBrian Somers fsm_opt_normalise(dec); 13311ae349f5Scvs2svn } 1332af57ed9fSAtsushi Murai } 1333af57ed9fSAtsushi Murai 13345d9e6103SBrian Somers extern struct mbuf * 13355d9e6103SBrian Somers ipcp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 1336af57ed9fSAtsushi Murai { 13377308ec68SBrian Somers /* Got PROTO_IPCP from link */ 133826af0ae9SBrian Somers m_settype(bp, MB_IPCPIN); 1339641684cdSBrian Somers if (bundle_Phase(bundle) == PHASE_NETWORK) 13405d9e6103SBrian Somers fsm_Input(&bundle->ncp.ipcp.fsm, bp); 1341641684cdSBrian Somers else { 1342641684cdSBrian Somers if (bundle_Phase(bundle) < PHASE_NETWORK) 1343641684cdSBrian Somers log_Printf(LogIPCP, "%s: Error: Unexpected IPCP in phase %s (ignored)\n", 13445d9e6103SBrian Somers l->name, bundle_PhaseName(bundle)); 134526af0ae9SBrian Somers m_freem(bp); 1346641684cdSBrian Somers } 13475d9e6103SBrian Somers return NULL; 1348af57ed9fSAtsushi Murai } 13499c97abd8SBrian Somers 13509c97abd8SBrian Somers int 1351972a1bcfSBrian Somers ipcp_UseHisIPaddr(struct bundle *bundle, struct in_addr hisaddr) 1352972a1bcfSBrian Somers { 1353972a1bcfSBrian Somers struct ipcp *ipcp = &bundle->ncp.ipcp; 135430949fd4SBrian Somers struct in_addr myaddr; 1355972a1bcfSBrian Somers 1356972a1bcfSBrian Somers memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 1357972a1bcfSBrian Somers iplist_reset(&ipcp->cfg.peer_list); 135830949fd4SBrian Somers ipcp->peer_ip = hisaddr; 135930949fd4SBrian Somers ncprange_setip4host(&ipcp->cfg.peer_range, hisaddr); 136030949fd4SBrian Somers ncprange_getip4addr(&ipcp->cfg.my_range, &myaddr); 1361972a1bcfSBrian Somers 136230949fd4SBrian Somers return ipcp_SetIPaddress(ipcp, myaddr, hisaddr); 1363972a1bcfSBrian Somers } 1364972a1bcfSBrian Somers 1365972a1bcfSBrian Somers int 1366dd7e2610SBrian Somers ipcp_UseHisaddr(struct bundle *bundle, const char *hisaddr, int setaddr) 13679c97abd8SBrian Somers { 136830949fd4SBrian Somers struct in_addr myaddr; 136930949fd4SBrian Somers struct ncp *ncp = &bundle->ncp; 137030949fd4SBrian Somers struct ipcp *ipcp = &ncp->ipcp; 137130949fd4SBrian Somers struct ncpaddr ncpaddr; 13725828db6dSBrian Somers 13737308ec68SBrian Somers /* Use `hisaddr' for the peers address (set iface if `setaddr') */ 13745828db6dSBrian Somers memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 13755828db6dSBrian Somers iplist_reset(&ipcp->cfg.peer_list); 13769c97abd8SBrian Somers if (strpbrk(hisaddr, ",-")) { 13775828db6dSBrian Somers iplist_setsrc(&ipcp->cfg.peer_list, hisaddr); 13785828db6dSBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 13795828db6dSBrian Somers iplist_setrandpos(&ipcp->cfg.peer_list); 138030c2f2ffSBrian Somers ipcp->peer_ip = ChooseHisAddr(bundle, ipcp->my_ip); 13815828db6dSBrian Somers if (ipcp->peer_ip.s_addr == INADDR_ANY) { 1382dd7e2610SBrian Somers log_Printf(LogWARN, "%s: None available !\n", ipcp->cfg.peer_list.src); 13831d1fc017SBrian Somers return 0; 13849c97abd8SBrian Somers } 138530949fd4SBrian Somers ncprange_setip4host(&ipcp->cfg.peer_range, ipcp->peer_ip); 13869c97abd8SBrian Somers } else { 1387dd7e2610SBrian Somers log_Printf(LogWARN, "%s: Invalid range !\n", hisaddr); 13889c97abd8SBrian Somers return 0; 13899c97abd8SBrian Somers } 139030949fd4SBrian Somers } else if (ncprange_aton(&ipcp->cfg.peer_range, ncp, hisaddr) != 0) { 139130949fd4SBrian Somers if (ncprange_family(&ipcp->cfg.my_range) != AF_INET) { 139230949fd4SBrian Somers log_Printf(LogWARN, "%s: Not an AF_INET address !\n", hisaddr); 139330949fd4SBrian Somers return 0; 139430949fd4SBrian Somers } 139530949fd4SBrian Somers ncprange_getip4addr(&ipcp->cfg.my_range, &myaddr); 139630949fd4SBrian Somers ncprange_getip4addr(&ipcp->cfg.peer_range, &ipcp->peer_ip); 13979c97abd8SBrian Somers 139830949fd4SBrian Somers if (setaddr && !ipcp_SetIPaddress(ipcp, myaddr, ipcp->peer_ip)) 13999c97abd8SBrian Somers return 0; 14009c97abd8SBrian Somers } else 14019c97abd8SBrian Somers return 0; 14029c97abd8SBrian Somers 140330949fd4SBrian Somers ncpaddr_setip4(&ncpaddr, ipcp->peer_ip); 140430949fd4SBrian Somers bundle_AdjustFilters(bundle, NULL, &ncpaddr); 14051d1fc017SBrian Somers 14061d1fc017SBrian Somers return 1; /* Ok */ 14079c97abd8SBrian Somers } 1408bc76350eSBrian Somers 1409bc76350eSBrian Somers struct in_addr 1410bc76350eSBrian Somers addr2mask(struct in_addr addr) 1411bc76350eSBrian Somers { 1412bc76350eSBrian Somers u_int32_t haddr = ntohl(addr.s_addr); 1413bc76350eSBrian Somers 1414bc76350eSBrian Somers haddr = IN_CLASSA(haddr) ? IN_CLASSA_NET : 1415bc76350eSBrian Somers IN_CLASSB(haddr) ? IN_CLASSB_NET : 1416bc76350eSBrian Somers IN_CLASSC_NET; 1417bc76350eSBrian Somers addr.s_addr = htonl(haddr); 1418bc76350eSBrian Somers 1419bc76350eSBrian Somers return addr; 1420bc76350eSBrian Somers } 142130949fd4SBrian Somers 142230949fd4SBrian Somers size_t 142330949fd4SBrian Somers ipcp_QueueLen(struct ipcp *ipcp) 142430949fd4SBrian Somers { 142530949fd4SBrian Somers struct mqueue *q; 142630949fd4SBrian Somers size_t result; 142730949fd4SBrian Somers 142830949fd4SBrian Somers result = 0; 142930949fd4SBrian Somers for (q = ipcp->Queue; q < ipcp->Queue + IPCP_QUEUES(ipcp); q++) 143030949fd4SBrian Somers result += q->len; 143130949fd4SBrian Somers 143230949fd4SBrian Somers return result; 143330949fd4SBrian Somers } 143430949fd4SBrian Somers 143530949fd4SBrian Somers int 143630949fd4SBrian Somers ipcp_PushPacket(struct ipcp *ipcp, struct link *l) 143730949fd4SBrian Somers { 143830949fd4SBrian Somers struct bundle *bundle = ipcp->fsm.bundle; 143930949fd4SBrian Somers struct mqueue *queue; 144030949fd4SBrian Somers struct mbuf *bp; 144130949fd4SBrian Somers int m_len; 144230949fd4SBrian Somers u_int32_t secs = 0; 144330949fd4SBrian Somers unsigned alivesecs = 0; 144430949fd4SBrian Somers 144530949fd4SBrian Somers if (ipcp->fsm.state != ST_OPENED) 144630949fd4SBrian Somers return 0; 144730949fd4SBrian Somers 144830949fd4SBrian Somers /* 144930949fd4SBrian Somers * If ccp is not open but is required, do nothing. 145030949fd4SBrian Somers */ 145130949fd4SBrian Somers if (l->ccp.fsm.state != ST_OPENED && ccp_Required(&l->ccp)) { 145230949fd4SBrian Somers log_Printf(LogPHASE, "%s: Not transmitting... waiting for CCP\n", l->name); 145330949fd4SBrian Somers return 0; 145430949fd4SBrian Somers } 145530949fd4SBrian Somers 145630949fd4SBrian Somers queue = ipcp->Queue + IPCP_QUEUES(ipcp) - 1; 145730949fd4SBrian Somers do { 145830949fd4SBrian Somers if (queue->top) { 145930949fd4SBrian Somers bp = m_dequeue(queue); 146030949fd4SBrian Somers bp = mbuf_Read(bp, &secs, sizeof secs); 146130949fd4SBrian Somers bp = m_pullup(bp); 146230949fd4SBrian Somers m_len = m_length(bp); 146330949fd4SBrian Somers if (!FilterCheck(MBUF_CTOP(bp), AF_INET, &bundle->filter.alive, 146430949fd4SBrian Somers &alivesecs)) { 146530949fd4SBrian Somers if (secs == 0) 146630949fd4SBrian Somers secs = alivesecs; 146730949fd4SBrian Somers bundle_StartIdleTimer(bundle, secs); 146830949fd4SBrian Somers } 146930949fd4SBrian Somers link_PushPacket(l, bp, bundle, 0, PROTO_IP); 147030949fd4SBrian Somers ipcp_AddOutOctets(ipcp, m_len); 147130949fd4SBrian Somers return 1; 147230949fd4SBrian Somers } 147330949fd4SBrian Somers } while (queue-- != ipcp->Queue); 147430949fd4SBrian Somers 147530949fd4SBrian Somers return 0; 147630949fd4SBrian Somers } 1477