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 121a5625ae7SPaolo Pisati extern struct libalias *la; 122a5625ae7SPaolo Pisati 12383d1af55SBrian Somers static struct fsm_callbacks ipcp_Callbacks = { 124af57ed9fSAtsushi Murai IpcpLayerUp, 125af57ed9fSAtsushi Murai IpcpLayerDown, 126af57ed9fSAtsushi Murai IpcpLayerStart, 127af57ed9fSAtsushi Murai IpcpLayerFinish, 128af57ed9fSAtsushi Murai IpcpInitRestartCounter, 129af57ed9fSAtsushi Murai IpcpSendConfigReq, 1302267893fSBrian Somers IpcpSentTerminateReq, 131af57ed9fSAtsushi Murai IpcpSendTerminateAck, 132af57ed9fSAtsushi Murai IpcpDecodeConfig, 133dd7e2610SBrian Somers fsm_NullRecvResetReq, 134dd7e2610SBrian Somers fsm_NullRecvResetAck 135af57ed9fSAtsushi Murai }; 136af57ed9fSAtsushi Murai 137d6d3eeabSBrian Somers static const char * 138d6d3eeabSBrian Somers protoname(int proto) 139d6d3eeabSBrian Somers { 140d6d3eeabSBrian Somers static struct { 141d6d3eeabSBrian Somers int id; 142d6d3eeabSBrian Somers const char *txt; 143d6d3eeabSBrian Somers } cftypes[] = { 1449e836af5SBrian Somers /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */ 145d6d3eeabSBrian Somers { 1, "IPADDRS" }, /* IP-Addresses */ /* deprecated */ 146d6d3eeabSBrian Somers { 2, "COMPPROTO" }, /* IP-Compression-Protocol */ 147d6d3eeabSBrian Somers { 3, "IPADDR" }, /* IP-Address */ 148d6d3eeabSBrian Somers { 129, "PRIDNS" }, /* 129: Primary DNS Server Address */ 149d6d3eeabSBrian Somers { 130, "PRINBNS" }, /* 130: Primary NBNS Server Address */ 150d6d3eeabSBrian Somers { 131, "SECDNS" }, /* 131: Secondary DNS Server Address */ 151d6d3eeabSBrian Somers { 132, "SECNBNS" } /* 132: Secondary NBNS Server Address */ 152af57ed9fSAtsushi Murai }; 153057f1760SBrian Somers unsigned f; 154af57ed9fSAtsushi Murai 155d6d3eeabSBrian Somers for (f = 0; f < sizeof cftypes / sizeof *cftypes; f++) 156d6d3eeabSBrian Somers if (cftypes[f].id == proto) 157d6d3eeabSBrian Somers return cftypes[f].txt; 1589e836af5SBrian Somers 159d6d3eeabSBrian Somers return NumStr(proto, NULL, 0); 160d6d3eeabSBrian Somers } 1619e836af5SBrian Somers 1629a0b991fSBrian Somers void 1635828db6dSBrian Somers ipcp_AddInOctets(struct ipcp *ipcp, int n) 164af57ed9fSAtsushi Murai { 1655828db6dSBrian Somers throughput_addin(&ipcp->throughput, n); 166af57ed9fSAtsushi Murai } 167af57ed9fSAtsushi Murai 1689a0b991fSBrian Somers void 1695828db6dSBrian Somers ipcp_AddOutOctets(struct ipcp *ipcp, int n) 170af57ed9fSAtsushi Murai { 1715828db6dSBrian Somers throughput_addout(&ipcp->throughput, n); 1721ae349f5Scvs2svn } 1731ae349f5Scvs2svn 174d568d6c4SBrian Somers void 175d568d6c4SBrian Somers ipcp_LoadDNS(struct ipcp *ipcp) 1763edeb0c6SBrian Somers { 177d568d6c4SBrian Somers int fd; 1783edeb0c6SBrian Somers 179d568d6c4SBrian Somers ipcp->ns.dns[0].s_addr = ipcp->ns.dns[1].s_addr = INADDR_NONE; 180d568d6c4SBrian Somers 181d568d6c4SBrian Somers if (ipcp->ns.resolv != NULL) { 182d568d6c4SBrian Somers free(ipcp->ns.resolv); 183d568d6c4SBrian Somers ipcp->ns.resolv = NULL; 184d568d6c4SBrian Somers } 185d568d6c4SBrian Somers if (ipcp->ns.resolv_nons != NULL) { 186d568d6c4SBrian Somers free(ipcp->ns.resolv_nons); 187d568d6c4SBrian Somers ipcp->ns.resolv_nons = NULL; 188d568d6c4SBrian Somers } 189d568d6c4SBrian Somers ipcp->ns.resolver = 0; 190d568d6c4SBrian Somers 191d568d6c4SBrian Somers if ((fd = open(_PATH_RESCONF, O_RDONLY)) != -1) { 192d568d6c4SBrian Somers struct stat st; 193d568d6c4SBrian Somers 194d568d6c4SBrian Somers if (fstat(fd, &st) == 0) { 195d568d6c4SBrian Somers ssize_t got; 196d568d6c4SBrian Somers 197eb1ecbb2SBrian Somers /* 198eb1ecbb2SBrian Somers * Note, ns.resolv and ns.resolv_nons are assumed to always point to 199eb1ecbb2SBrian Somers * buffers of the same size! See the strcpy() below. 200eb1ecbb2SBrian Somers */ 201d568d6c4SBrian Somers if ((ipcp->ns.resolv_nons = (char *)malloc(st.st_size + 1)) == NULL) 202d568d6c4SBrian Somers log_Printf(LogERROR, "Failed to malloc %lu for %s: %s\n", 203d568d6c4SBrian Somers (unsigned long)st.st_size, _PATH_RESCONF, strerror(errno)); 204d568d6c4SBrian Somers else if ((ipcp->ns.resolv = (char *)malloc(st.st_size + 1)) == NULL) { 205d568d6c4SBrian Somers log_Printf(LogERROR, "Failed(2) to malloc %lu for %s: %s\n", 206d568d6c4SBrian Somers (unsigned long)st.st_size, _PATH_RESCONF, strerror(errno)); 207d568d6c4SBrian Somers free(ipcp->ns.resolv_nons); 208d568d6c4SBrian Somers ipcp->ns.resolv_nons = NULL; 209d568d6c4SBrian Somers } else if ((got = read(fd, ipcp->ns.resolv, st.st_size)) != st.st_size) { 210d568d6c4SBrian Somers if (got == -1) 211d568d6c4SBrian Somers log_Printf(LogERROR, "Failed to read %s: %s\n", 212d568d6c4SBrian Somers _PATH_RESCONF, strerror(errno)); 213d568d6c4SBrian Somers else 214d568d6c4SBrian Somers log_Printf(LogERROR, "Failed to read %s, got %lu not %lu\n", 215d568d6c4SBrian Somers _PATH_RESCONF, (unsigned long)got, 216d568d6c4SBrian Somers (unsigned long)st.st_size); 217d568d6c4SBrian Somers free(ipcp->ns.resolv_nons); 218d568d6c4SBrian Somers ipcp->ns.resolv_nons = NULL; 219d568d6c4SBrian Somers free(ipcp->ns.resolv); 220d568d6c4SBrian Somers ipcp->ns.resolv = NULL; 221d568d6c4SBrian Somers } else { 222d568d6c4SBrian Somers char *cp, *cp_nons, *ncp, ch; 2233edeb0c6SBrian Somers int n; 2243edeb0c6SBrian Somers 225d568d6c4SBrian Somers ipcp->ns.resolv[st.st_size] = '\0'; 226d568d6c4SBrian Somers ipcp->ns.resolver = 1; 227d568d6c4SBrian Somers 228d568d6c4SBrian Somers cp_nons = ipcp->ns.resolv_nons; 229d568d6c4SBrian Somers cp = ipcp->ns.resolv; 2303edeb0c6SBrian Somers n = 0; 231d568d6c4SBrian Somers 232d568d6c4SBrian Somers while ((ncp = strstr(cp, "nameserver")) != NULL) { 233d568d6c4SBrian Somers if (ncp != cp) { 234d568d6c4SBrian Somers memcpy(cp_nons, cp, ncp - cp); 235d568d6c4SBrian Somers cp_nons += ncp - cp; 2363edeb0c6SBrian Somers } 237d568d6c4SBrian Somers if ((ncp != cp && ncp[-1] != '\n') || !issep(ncp[10])) { 238d568d6c4SBrian Somers memcpy(cp_nons, ncp, 9); 239d568d6c4SBrian Somers cp_nons += 9; 240d568d6c4SBrian Somers cp = ncp + 9; /* Can't match "nameserver" at cp... */ 241d568d6c4SBrian Somers continue; 2423edeb0c6SBrian Somers } 243d568d6c4SBrian Somers 244d568d6c4SBrian Somers for (cp = ncp + 11; issep(*cp); cp++) /* Skip whitespace */ 245d568d6c4SBrian Somers ; 246d568d6c4SBrian Somers 247d568d6c4SBrian Somers for (ncp = cp; isip(*ncp); ncp++) /* Jump over IP */ 248d568d6c4SBrian Somers ; 249d568d6c4SBrian Somers 250d568d6c4SBrian Somers ch = *ncp; 251d568d6c4SBrian Somers *ncp = '\0'; 25230949fd4SBrian Somers if (n < 2 && inet_aton(cp, ipcp->ns.dns)) 253d568d6c4SBrian Somers n++; 254d568d6c4SBrian Somers *ncp = ch; 255d568d6c4SBrian Somers 256d568d6c4SBrian Somers if ((cp = strchr(ncp, '\n')) == NULL) /* Point at next line */ 257d568d6c4SBrian Somers cp = ncp + strlen(ncp); 258d568d6c4SBrian Somers else 259d568d6c4SBrian Somers cp++; 260d568d6c4SBrian Somers } 261eb1ecbb2SBrian Somers /* 262eb1ecbb2SBrian Somers * Note, cp_nons and cp always point to buffers of the same size, so 263eb1ecbb2SBrian Somers * strcpy is ok! 264eb1ecbb2SBrian Somers */ 265d568d6c4SBrian Somers strcpy(cp_nons, cp); /* Copy the end - including the NUL */ 266d568d6c4SBrian Somers cp_nons += strlen(cp_nons) - 1; 267d568d6c4SBrian Somers while (cp_nons >= ipcp->ns.resolv_nons && *cp_nons == '\n') 268d568d6c4SBrian Somers *cp_nons-- = '\0'; 269d568d6c4SBrian Somers if (n == 2 && ipcp->ns.dns[0].s_addr == INADDR_ANY) { 270d568d6c4SBrian Somers ipcp->ns.dns[0].s_addr = ipcp->ns.dns[1].s_addr; 271d568d6c4SBrian Somers ipcp->ns.dns[1].s_addr = INADDR_ANY; 272d568d6c4SBrian Somers } 27330949fd4SBrian Somers bundle_AdjustDNS(ipcp->fsm.bundle); 274d568d6c4SBrian Somers } 275d568d6c4SBrian Somers } else 276d568d6c4SBrian Somers log_Printf(LogERROR, "Failed to stat opened %s: %s\n", 277d568d6c4SBrian Somers _PATH_RESCONF, strerror(errno)); 278d568d6c4SBrian Somers 279d568d6c4SBrian Somers close(fd); 2803edeb0c6SBrian Somers } 2813edeb0c6SBrian Somers } 2823edeb0c6SBrian Somers 283d568d6c4SBrian Somers int 284d568d6c4SBrian Somers ipcp_WriteDNS(struct ipcp *ipcp) 2853edeb0c6SBrian Somers { 286d568d6c4SBrian Somers const char *paddr; 287d568d6c4SBrian Somers mode_t mask; 2883edeb0c6SBrian Somers FILE *fp; 2893edeb0c6SBrian Somers 290d568d6c4SBrian Somers if (ipcp->ns.dns[0].s_addr == INADDR_ANY && 291d568d6c4SBrian Somers ipcp->ns.dns[1].s_addr == INADDR_ANY) { 292d568d6c4SBrian Somers log_Printf(LogIPCP, "%s not modified: All nameservers NAKd\n", 2933edeb0c6SBrian Somers _PATH_RESCONF); 2943edeb0c6SBrian Somers return 0; 2953edeb0c6SBrian Somers } 2963edeb0c6SBrian Somers 297d568d6c4SBrian Somers if (ipcp->ns.dns[0].s_addr == INADDR_ANY) { 298d568d6c4SBrian Somers ipcp->ns.dns[0].s_addr = ipcp->ns.dns[1].s_addr; 299d568d6c4SBrian Somers ipcp->ns.dns[1].s_addr = INADDR_ANY; 300d568d6c4SBrian Somers } 3013edeb0c6SBrian Somers 3027fe0b592SBrian Somers mask = umask(022); 303d568d6c4SBrian Somers if ((fp = ID0fopen(_PATH_RESCONF, "w")) != NULL) { 304d568d6c4SBrian Somers umask(mask); 305682cb20fSBrian Somers if (ipcp->ns.resolv_nons) 306d568d6c4SBrian Somers fputs(ipcp->ns.resolv_nons, fp); 307d568d6c4SBrian Somers paddr = inet_ntoa(ipcp->ns.dns[0]); 308d568d6c4SBrian Somers log_Printf(LogIPCP, "Primary nameserver set to %s\n", paddr); 309d568d6c4SBrian Somers fprintf(fp, "\nnameserver %s\n", paddr); 310d568d6c4SBrian Somers if (ipcp->ns.dns[1].s_addr != INADDR_ANY && 311d568d6c4SBrian Somers ipcp->ns.dns[1].s_addr != INADDR_NONE && 312d568d6c4SBrian Somers ipcp->ns.dns[1].s_addr != ipcp->ns.dns[0].s_addr) { 313d568d6c4SBrian Somers paddr = inet_ntoa(ipcp->ns.dns[1]); 314d568d6c4SBrian Somers log_Printf(LogIPCP, "Secondary nameserver set to %s\n", paddr); 315d568d6c4SBrian Somers fprintf(fp, "nameserver %s\n", paddr); 316d568d6c4SBrian Somers } 317d568d6c4SBrian Somers if (fclose(fp) == EOF) { 318d568d6c4SBrian Somers log_Printf(LogERROR, "write(): Failed updating %s: %s\n", _PATH_RESCONF, 319d568d6c4SBrian Somers strerror(errno)); 3203edeb0c6SBrian Somers return 0; 3213edeb0c6SBrian Somers } 322d568d6c4SBrian Somers } else 323d568d6c4SBrian Somers umask(mask); 3243edeb0c6SBrian Somers 3253edeb0c6SBrian Somers return 1; 326af57ed9fSAtsushi Murai } 327af57ed9fSAtsushi Murai 328d568d6c4SBrian Somers void 329d568d6c4SBrian Somers ipcp_RestoreDNS(struct ipcp *ipcp) 330d568d6c4SBrian Somers { 331d568d6c4SBrian Somers if (ipcp->ns.resolver) { 332057f1760SBrian Somers ssize_t got, len; 333d568d6c4SBrian Somers int fd; 334d568d6c4SBrian Somers 335d568d6c4SBrian Somers if ((fd = ID0open(_PATH_RESCONF, O_WRONLY|O_TRUNC, 0644)) != -1) { 336d568d6c4SBrian Somers len = strlen(ipcp->ns.resolv); 337d568d6c4SBrian Somers if ((got = write(fd, ipcp->ns.resolv, len)) != len) { 338d568d6c4SBrian Somers if (got == -1) 339d568d6c4SBrian Somers log_Printf(LogERROR, "Failed rewriting %s: write: %s\n", 340d568d6c4SBrian Somers _PATH_RESCONF, strerror(errno)); 341d568d6c4SBrian Somers else 342057f1760SBrian Somers log_Printf(LogERROR, "Failed rewriting %s: wrote %ld of %ld\n", 343057f1760SBrian Somers _PATH_RESCONF, (long)got, (long)len); 344d568d6c4SBrian Somers } 345d568d6c4SBrian Somers close(fd); 346d568d6c4SBrian Somers } else 347d568d6c4SBrian Somers log_Printf(LogERROR, "Failed rewriting %s: open: %s\n", _PATH_RESCONF, 348d568d6c4SBrian Somers strerror(errno)); 349d568d6c4SBrian Somers } else if (remove(_PATH_RESCONF) == -1) 350d568d6c4SBrian Somers log_Printf(LogERROR, "Failed removing %s: %s\n", _PATH_RESCONF, 351d568d6c4SBrian Somers strerror(errno)); 352d568d6c4SBrian Somers 353d568d6c4SBrian Somers } 354d568d6c4SBrian Somers 355274e766cSBrian Somers int 356dd7e2610SBrian Somers ipcp_Show(struct cmdargs const *arg) 357af57ed9fSAtsushi Murai { 358610b185fSBrian Somers struct ipcp *ipcp = &arg->bundle->ncp.ipcp; 359af57ed9fSAtsushi Murai 360610b185fSBrian Somers prompt_Printf(arg->prompt, "%s [%s]\n", ipcp->fsm.name, 361610b185fSBrian Somers State2Nam(ipcp->fsm.state)); 362610b185fSBrian Somers if (ipcp->fsm.state == ST_OPENED) { 363b6217683SBrian Somers prompt_Printf(arg->prompt, " His side: %s, %s\n", 364610b185fSBrian Somers inet_ntoa(ipcp->peer_ip), vj2asc(ipcp->peer_compproto)); 365b6217683SBrian Somers prompt_Printf(arg->prompt, " My side: %s, %s\n", 366610b185fSBrian Somers inet_ntoa(ipcp->my_ip), vj2asc(ipcp->my_compproto)); 367209dc102SBrian Somers prompt_Printf(arg->prompt, " Queued packets: %lu\n", 36830949fd4SBrian Somers (unsigned long)ipcp_QueueLen(ipcp)); 3691ae349f5Scvs2svn } 370927145beSBrian Somers 371b6217683SBrian Somers prompt_Printf(arg->prompt, "\nDefaults:\n"); 372479508cfSBrian Somers prompt_Printf(arg->prompt, " FSM retry = %us, max %u Config" 373479508cfSBrian Somers " REQ%s, %u Term REQ%s\n", ipcp->cfg.fsm.timeout, 374479508cfSBrian Somers ipcp->cfg.fsm.maxreq, ipcp->cfg.fsm.maxreq == 1 ? "" : "s", 375479508cfSBrian Somers ipcp->cfg.fsm.maxtrm, ipcp->cfg.fsm.maxtrm == 1 ? "" : "s"); 37630949fd4SBrian Somers prompt_Printf(arg->prompt, " My Address: %s\n", 37730949fd4SBrian Somers ncprange_ntoa(&ipcp->cfg.my_range)); 378610b185fSBrian Somers if (ipcp->cfg.HaveTriggerAddress) 379bc76350eSBrian Somers prompt_Printf(arg->prompt, " Trigger address: %s\n", 380610b185fSBrian Somers inet_ntoa(ipcp->cfg.TriggerAddress)); 381bc76350eSBrian Somers 382bc76350eSBrian Somers prompt_Printf(arg->prompt, " VJ compression: %s (%d slots %s slot " 383610b185fSBrian Somers "compression)\n", command_ShowNegval(ipcp->cfg.vj.neg), 384610b185fSBrian Somers ipcp->cfg.vj.slots, ipcp->cfg.vj.slotcomp ? "with" : "without"); 38550abd4c8SBrian Somers 386610b185fSBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) 387b6217683SBrian Somers prompt_Printf(arg->prompt, " His Address: %s\n", 388610b185fSBrian Somers ipcp->cfg.peer_list.src); 3891ae349f5Scvs2svn else 39030949fd4SBrian Somers prompt_Printf(arg->prompt, " His Address: %s\n", 39130949fd4SBrian Somers ncprange_ntoa(&ipcp->cfg.peer_range)); 39250abd4c8SBrian Somers 393d568d6c4SBrian Somers prompt_Printf(arg->prompt, " DNS: %s", 394d568d6c4SBrian Somers ipcp->cfg.ns.dns[0].s_addr == INADDR_NONE ? 395d568d6c4SBrian Somers "none" : inet_ntoa(ipcp->cfg.ns.dns[0])); 396d568d6c4SBrian Somers if (ipcp->cfg.ns.dns[1].s_addr != INADDR_NONE) 39730949fd4SBrian Somers prompt_Printf(arg->prompt, ", %s", 39830949fd4SBrian Somers inet_ntoa(ipcp->cfg.ns.dns[1])); 399d568d6c4SBrian Somers prompt_Printf(arg->prompt, ", %s\n", 400610b185fSBrian Somers command_ShowNegval(ipcp->cfg.ns.dns_neg)); 401d568d6c4SBrian Somers prompt_Printf(arg->prompt, " Resolver DNS: %s", 402d568d6c4SBrian Somers ipcp->ns.dns[0].s_addr == INADDR_NONE ? 403d568d6c4SBrian Somers "none" : inet_ntoa(ipcp->ns.dns[0])); 404d568d6c4SBrian Somers if (ipcp->ns.dns[1].s_addr != INADDR_NONE && 405d568d6c4SBrian Somers ipcp->ns.dns[1].s_addr != ipcp->ns.dns[0].s_addr) 40630949fd4SBrian Somers prompt_Printf(arg->prompt, ", %s", 40730949fd4SBrian Somers inet_ntoa(ipcp->ns.dns[1])); 408d568d6c4SBrian Somers prompt_Printf(arg->prompt, "\n NetBIOS NS: %s, ", 409610b185fSBrian Somers inet_ntoa(ipcp->cfg.ns.nbns[0])); 410ad1f9eaeSBrian Somers prompt_Printf(arg->prompt, "%s\n\n", 41130949fd4SBrian Somers inet_ntoa(ipcp->cfg.ns.nbns[1])); 412442f8495SBrian Somers 413610b185fSBrian Somers throughput_disp(&ipcp->throughput, arg->prompt); 4149a0b991fSBrian Somers 415927145beSBrian Somers return 0; 416af57ed9fSAtsushi Murai } 417af57ed9fSAtsushi Murai 418d1a3ea47SBrian Somers int 419dd7e2610SBrian Somers ipcp_vjset(struct cmdargs const *arg) 420d1a3ea47SBrian Somers { 42125092092SBrian Somers if (arg->argc != arg->argn+2) 422d1a3ea47SBrian Somers return -1; 42325092092SBrian Somers if (!strcasecmp(arg->argv[arg->argn], "slots")) { 424d1a3ea47SBrian Somers int slots; 425d1a3ea47SBrian Somers 42625092092SBrian Somers slots = atoi(arg->argv[arg->argn+1]); 427d1a3ea47SBrian Somers if (slots < 4 || slots > 16) 428d1a3ea47SBrian Somers return 1; 4291342caedSBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slots = slots; 430d1a3ea47SBrian Somers return 0; 43125092092SBrian Somers } else if (!strcasecmp(arg->argv[arg->argn], "slotcomp")) { 43225092092SBrian Somers if (!strcasecmp(arg->argv[arg->argn+1], "on")) 4331342caedSBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 1; 43425092092SBrian Somers else if (!strcasecmp(arg->argv[arg->argn+1], "off")) 4351342caedSBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 0; 436d1a3ea47SBrian Somers else 437d1a3ea47SBrian Somers return 2; 438d1a3ea47SBrian Somers return 0; 439d1a3ea47SBrian Somers } 440d1a3ea47SBrian Somers return -1; 441d1a3ea47SBrian Somers } 442d1a3ea47SBrian Somers 4431ae349f5Scvs2svn void 4446d666775SBrian Somers ipcp_Init(struct ipcp *ipcp, struct bundle *bundle, struct link *l, 4456d666775SBrian Somers const struct fsm_parent *parent) 446d1a3ea47SBrian Somers { 447503a7782SBrian Somers struct hostent *hp; 44830949fd4SBrian Somers struct in_addr host; 44926e6a622SBrian Somers char name[MAXHOSTNAMELEN]; 450182c898aSBrian Somers static const char * const timer_names[] = 4513b0f8d2eSBrian Somers {"IPCP restart", "IPCP openmode", "IPCP stopped"}; 45229e275ceSBrian Somers 453479508cfSBrian Somers fsm_Init(&ipcp->fsm, "IPCP", PROTO_IPCP, 1, IPCP_MAXCODE, LogIPCP, 4543b0f8d2eSBrian Somers bundle, l, parent, &ipcp_Callbacks, timer_names); 455503a7782SBrian Somers 4561342caedSBrian Somers ipcp->cfg.vj.slots = DEF_VJ_STATES; 4571342caedSBrian Somers ipcp->cfg.vj.slotcomp = 1; 458503a7782SBrian Somers memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range); 45930949fd4SBrian Somers 46030949fd4SBrian Somers host.s_addr = htonl(INADDR_LOOPBACK); 46130949fd4SBrian Somers ipcp->cfg.netmask.s_addr = INADDR_ANY; 462503a7782SBrian Somers if (gethostname(name, sizeof name) == 0) { 463503a7782SBrian Somers hp = gethostbyname(name); 46430949fd4SBrian Somers if (hp && hp->h_addrtype == AF_INET && hp->h_length == sizeof host.s_addr) 46530949fd4SBrian Somers memcpy(&host.s_addr, hp->h_addr, sizeof host.s_addr); 466503a7782SBrian Somers } 46730949fd4SBrian Somers ncprange_setip4(&ipcp->cfg.my_range, host, ipcp->cfg.netmask); 46830949fd4SBrian Somers ncprange_setip4(&ipcp->cfg.peer_range, ipcp->cfg.netmask, ipcp->cfg.netmask); 46930949fd4SBrian Somers 470503a7782SBrian Somers iplist_setsrc(&ipcp->cfg.peer_list, ""); 471503a7782SBrian Somers ipcp->cfg.HaveTriggerAddress = 0; 472503a7782SBrian Somers 473d568d6c4SBrian Somers ipcp->cfg.ns.dns[0].s_addr = INADDR_NONE; 474d568d6c4SBrian Somers ipcp->cfg.ns.dns[1].s_addr = INADDR_NONE; 4753edeb0c6SBrian Somers ipcp->cfg.ns.dns_neg = 0; 4763edeb0c6SBrian Somers ipcp->cfg.ns.nbns[0].s_addr = INADDR_ANY; 4773edeb0c6SBrian Somers ipcp->cfg.ns.nbns[1].s_addr = INADDR_ANY; 478cd9647a1SBrian Somers 479479508cfSBrian Somers ipcp->cfg.fsm.timeout = DEF_FSMRETRY; 480479508cfSBrian Somers ipcp->cfg.fsm.maxreq = DEF_FSMTRIES; 481479508cfSBrian Somers ipcp->cfg.fsm.maxtrm = DEF_FSMTRIES; 4821342caedSBrian Somers ipcp->cfg.vj.neg = NEG_ENABLED|NEG_ACCEPTED; 483503a7782SBrian Somers 484eaa4df37SBrian Somers memset(&ipcp->vj, '\0', sizeof ipcp->vj); 485eaa4df37SBrian Somers 486d568d6c4SBrian Somers ipcp->ns.resolv = NULL; 487d568d6c4SBrian Somers ipcp->ns.resolv_nons = NULL; 488d568d6c4SBrian Somers ipcp->ns.writable = 1; 489d568d6c4SBrian Somers ipcp_LoadDNS(ipcp); 490d568d6c4SBrian Somers 491ab2de065SBrian Somers throughput_init(&ipcp->throughput, SAMPLE_PERIOD); 4925a72b6edSBrian Somers memset(ipcp->Queue, '\0', sizeof ipcp->Queue); 493972a1bcfSBrian Somers ipcp_Setup(ipcp, INADDR_NONE); 494d1a3ea47SBrian Somers } 495d1a3ea47SBrian Somers 496af57ed9fSAtsushi Murai void 497442f8495SBrian Somers ipcp_Destroy(struct ipcp *ipcp) 498442f8495SBrian Somers { 49930949fd4SBrian Somers throughput_destroy(&ipcp->throughput); 50030949fd4SBrian Somers 501d568d6c4SBrian Somers if (ipcp->ns.resolv != NULL) { 502d568d6c4SBrian Somers free(ipcp->ns.resolv); 503d568d6c4SBrian Somers ipcp->ns.resolv = NULL; 504d568d6c4SBrian Somers } 505d568d6c4SBrian Somers if (ipcp->ns.resolv_nons != NULL) { 506d568d6c4SBrian Somers free(ipcp->ns.resolv_nons); 507d568d6c4SBrian Somers ipcp->ns.resolv_nons = NULL; 508d568d6c4SBrian Somers } 509442f8495SBrian Somers } 510442f8495SBrian Somers 511442f8495SBrian Somers void 512ce828a6eSBrian Somers ipcp_SetLink(struct ipcp *ipcp, struct link *l) 513af57ed9fSAtsushi Murai { 514ce828a6eSBrian Somers ipcp->fsm.link = l; 515af57ed9fSAtsushi Murai } 516549d663dSAtsushi Murai 517ce828a6eSBrian Somers void 518972a1bcfSBrian Somers ipcp_Setup(struct ipcp *ipcp, u_int32_t mask) 519503a7782SBrian Somers { 5208fa6ebe4SBrian Somers struct iface *iface = ipcp->fsm.bundle->iface; 52130949fd4SBrian Somers struct ncpaddr ipaddr; 52230949fd4SBrian Somers struct in_addr peer; 523057f1760SBrian Somers int pos; 524057f1760SBrian Somers unsigned n; 525503a7782SBrian Somers 526503a7782SBrian Somers ipcp->fsm.open_mode = 0; 527972a1bcfSBrian Somers ipcp->ifmask.s_addr = mask == INADDR_NONE ? ipcp->cfg.netmask.s_addr : mask; 528503a7782SBrian Somers 529503a7782SBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 5308fa6ebe4SBrian Somers /* Try to give the peer a previously configured IP address */ 53130949fd4SBrian Somers for (n = 0; n < iface->addrs; n++) { 53230949fd4SBrian Somers if (!ncpaddr_getip4(&iface->addr[n].peer, &peer)) 53330949fd4SBrian Somers continue; 53430949fd4SBrian Somers if ((pos = iplist_ip2pos(&ipcp->cfg.peer_list, peer)) != -1) { 53530949fd4SBrian Somers ncpaddr_setip4(&ipaddr, iplist_setcurpos(&ipcp->cfg.peer_list, pos)); 5368fa6ebe4SBrian Somers break; 5378fa6ebe4SBrian Somers } 5388fa6ebe4SBrian Somers } 53930949fd4SBrian Somers if (n == iface->addrs) 5408fa6ebe4SBrian Somers /* Ok, so none of 'em fit.... pick a random one */ 54130949fd4SBrian Somers ncpaddr_setip4(&ipaddr, iplist_setrandpos(&ipcp->cfg.peer_list)); 5428fa6ebe4SBrian Somers 54330949fd4SBrian Somers ncprange_sethost(&ipcp->cfg.peer_range, &ipaddr); 544503a7782SBrian Somers } 545503a7782SBrian Somers 546503a7782SBrian Somers ipcp->heis1172 = 0; 5475e3b2d68SBrian Somers ipcp->peer_req = 0; 54830949fd4SBrian Somers ncprange_getip4addr(&ipcp->cfg.peer_range, &ipcp->peer_ip); 549503a7782SBrian Somers ipcp->peer_compproto = 0; 5501ae349f5Scvs2svn 5518390b576SBrian Somers if (ipcp->cfg.HaveTriggerAddress) { 552549d663dSAtsushi Murai /* 5535b4c5b00SBrian Somers * Some implementations of PPP require that we send a 5545b4c5b00SBrian Somers * *special* value as our address, even though the rfc specifies 5555b4c5b00SBrian Somers * full negotiation (e.g. "0.0.0.0" or Not "0.0.0.0"). 556549d663dSAtsushi Murai */ 557503a7782SBrian Somers ipcp->my_ip = ipcp->cfg.TriggerAddress; 558dd7e2610SBrian Somers log_Printf(LogIPCP, "Using trigger address %s\n", 559503a7782SBrian Somers inet_ntoa(ipcp->cfg.TriggerAddress)); 5608fa6ebe4SBrian Somers } else { 5618390b576SBrian Somers /* 5628fa6ebe4SBrian Somers * Otherwise, if we've used an IP number before and it's still within 5638fa6ebe4SBrian Somers * the network specified on the ``set ifaddr'' line, we really 5648fa6ebe4SBrian Somers * want to keep that IP number so that we can keep any existing 56530949fd4SBrian Somers * connections that are bound to that IP. 5668390b576SBrian Somers */ 56730949fd4SBrian Somers for (n = 0; n < iface->addrs; n++) { 56830949fd4SBrian Somers ncprange_getaddr(&iface->addr[n].ifa, &ipaddr); 56930949fd4SBrian Somers if (ncprange_contains(&ipcp->cfg.my_range, &ipaddr)) { 57030949fd4SBrian Somers ncpaddr_getip4(&ipaddr, &ipcp->my_ip); 5718fa6ebe4SBrian Somers break; 5728fa6ebe4SBrian Somers } 57330949fd4SBrian Somers } 57430949fd4SBrian Somers if (n == iface->addrs) 57530949fd4SBrian Somers ncprange_getip4addr(&ipcp->cfg.my_range, &ipcp->my_ip); 5768fa6ebe4SBrian Somers } 57729e275ceSBrian Somers 578972a1bcfSBrian Somers if (IsEnabled(ipcp->cfg.vj.neg) 579972a1bcfSBrian Somers #ifndef NORADIUS 580972a1bcfSBrian Somers || (ipcp->fsm.bundle->radius.valid && ipcp->fsm.bundle->radius.vj) 581972a1bcfSBrian Somers #endif 582972a1bcfSBrian Somers ) 583503a7782SBrian Somers ipcp->my_compproto = (PROTO_VJCOMP << 16) + 5841342caedSBrian Somers ((ipcp->cfg.vj.slots - 1) << 8) + 5851342caedSBrian Somers ipcp->cfg.vj.slotcomp; 5861ae349f5Scvs2svn else 587503a7782SBrian Somers ipcp->my_compproto = 0; 5881342caedSBrian Somers sl_compress_init(&ipcp->vj.cslc, ipcp->cfg.vj.slots - 1); 58929e275ceSBrian Somers 590503a7782SBrian Somers ipcp->peer_reject = 0; 591503a7782SBrian Somers ipcp->my_reject = 0; 592d568d6c4SBrian Somers 59330949fd4SBrian Somers /* Copy startup values into ipcp->ns.dns */ 594d568d6c4SBrian Somers if (ipcp->cfg.ns.dns[0].s_addr != INADDR_NONE) 59530949fd4SBrian Somers memcpy(ipcp->ns.dns, ipcp->cfg.ns.dns, sizeof ipcp->ns.dns); 5961ae349f5Scvs2svn } 5971ae349f5Scvs2svn 598455aabc3SBrian Somers static int 59930949fd4SBrian Somers numaddresses(struct in_addr mask) 6003afe5ccbSBrian Somers { 60130949fd4SBrian Somers u_int32_t bit, haddr; 60230949fd4SBrian Somers int n; 6033afe5ccbSBrian Somers 60430949fd4SBrian Somers haddr = ntohl(mask.s_addr); 60530949fd4SBrian Somers bit = 1; 60630949fd4SBrian Somers n = 1; 60730949fd4SBrian Somers 60830949fd4SBrian Somers do { 60930949fd4SBrian Somers if (!(haddr & bit)) 61030949fd4SBrian Somers n <<= 1; 61130949fd4SBrian Somers } while (bit <<= 1); 61230949fd4SBrian Somers 61330949fd4SBrian Somers return n; 6143afe5ccbSBrian Somers } 6153afe5ccbSBrian Somers 61630949fd4SBrian Somers static int 61730949fd4SBrian Somers ipcp_proxyarp(struct ipcp *ipcp, 618057f1760SBrian Somers int (*proxyfun)(struct bundle *, struct in_addr), 61930949fd4SBrian Somers const struct iface_addr *addr) 62030949fd4SBrian Somers { 62130949fd4SBrian Somers struct bundle *bundle = ipcp->fsm.bundle; 62230949fd4SBrian Somers struct in_addr peer, mask, ip; 623057f1760SBrian Somers int n, ret; 62430949fd4SBrian Somers 62530949fd4SBrian Somers if (!ncpaddr_getip4(&addr->peer, &peer)) { 62630949fd4SBrian Somers log_Printf(LogERROR, "Oops, ipcp_proxyarp() called with unexpected addr\n"); 6273afe5ccbSBrian Somers return 0; 6283afe5ccbSBrian Somers } 6293afe5ccbSBrian Somers 63030949fd4SBrian Somers ret = 0; 63130949fd4SBrian Somers 63230949fd4SBrian Somers if (Enabled(bundle, OPT_PROXYALL)) { 63330949fd4SBrian Somers ncprange_getip4mask(&addr->ifa, &mask); 63430949fd4SBrian Somers if ((n = numaddresses(mask)) > 256) { 63530949fd4SBrian Somers log_Printf(LogWARN, "%s: Too many addresses for proxyall\n", 63630949fd4SBrian Somers ncprange_ntoa(&addr->ifa)); 63730949fd4SBrian Somers return 0; 63830949fd4SBrian Somers } 63930949fd4SBrian Somers ip.s_addr = peer.s_addr & mask.s_addr; 64030949fd4SBrian Somers if (n >= 4) { 64130949fd4SBrian Somers ip.s_addr = htonl(ntohl(ip.s_addr) + 1); 64230949fd4SBrian Somers n -= 2; 64330949fd4SBrian Somers } 64430949fd4SBrian Somers while (n) { 64530949fd4SBrian Somers if (!((ip.s_addr ^ peer.s_addr) & mask.s_addr)) { 646057f1760SBrian Somers if (!(ret = (*proxyfun)(bundle, ip))) 64730949fd4SBrian Somers break; 64830949fd4SBrian Somers n--; 64930949fd4SBrian Somers } 65030949fd4SBrian Somers ip.s_addr = htonl(ntohl(ip.s_addr) + 1); 65130949fd4SBrian Somers } 65230949fd4SBrian Somers ret = !n; 65330949fd4SBrian Somers } else if (Enabled(bundle, OPT_PROXY)) 654057f1760SBrian Somers ret = (*proxyfun)(bundle, peer); 65530949fd4SBrian Somers 65630949fd4SBrian Somers return ret; 65730949fd4SBrian Somers } 65830949fd4SBrian Somers 6593afe5ccbSBrian Somers static int 66030949fd4SBrian Somers ipcp_SetIPaddress(struct ipcp *ipcp, struct in_addr myaddr, 66130949fd4SBrian Somers struct in_addr hisaddr) 662455aabc3SBrian Somers { 66330949fd4SBrian Somers struct bundle *bundle = ipcp->fsm.bundle; 66430949fd4SBrian Somers struct ncpaddr myncpaddr, hisncpaddr; 6655ae08329SBrian Somers struct ncprange myrange; 66630949fd4SBrian Somers struct in_addr mask; 6675ae08329SBrian Somers struct sockaddr_storage ssdst, ssgw, ssmask; 6685ae08329SBrian Somers struct sockaddr *sadst, *sagw, *samask; 6695ae08329SBrian Somers 6705ae08329SBrian Somers sadst = (struct sockaddr *)&ssdst; 6715ae08329SBrian Somers sagw = (struct sockaddr *)&ssgw; 6725ae08329SBrian Somers samask = (struct sockaddr *)&ssmask; 67330949fd4SBrian Somers 67430949fd4SBrian Somers ncpaddr_setip4(&hisncpaddr, hisaddr); 67530949fd4SBrian Somers ncpaddr_setip4(&myncpaddr, myaddr); 67630949fd4SBrian Somers ncprange_sethost(&myrange, &myncpaddr); 677455aabc3SBrian Somers 678bc76350eSBrian Somers mask = addr2mask(myaddr); 679455aabc3SBrian Somers 68030949fd4SBrian Somers if (ipcp->ifmask.s_addr != INADDR_ANY && 68130949fd4SBrian Somers (ipcp->ifmask.s_addr & mask.s_addr) == mask.s_addr) 68230949fd4SBrian Somers ncprange_setip4mask(&myrange, ipcp->ifmask); 683455aabc3SBrian Somers 68430949fd4SBrian Somers if (!iface_Add(bundle->iface, &bundle->ncp, &myrange, &hisncpaddr, 68530949fd4SBrian Somers IFACE_ADD_FIRST|IFACE_FORCE_ADD|IFACE_SYSTEM)) 68630949fd4SBrian Somers return 0; 687455aabc3SBrian Somers 68830949fd4SBrian Somers if (!Enabled(bundle, OPT_IFACEALIAS)) 68930949fd4SBrian Somers iface_Clear(bundle->iface, &bundle->ncp, AF_INET, 69030949fd4SBrian Somers IFACE_CLEAR_ALIASES|IFACE_SYSTEM); 691455aabc3SBrian Somers 69230949fd4SBrian Somers if (bundle->ncp.cfg.sendpipe > 0 || bundle->ncp.cfg.recvpipe > 0) { 6935ae08329SBrian Somers ncprange_getsa(&myrange, &ssgw, &ssmask); 6945ae08329SBrian Somers ncpaddr_getsa(&hisncpaddr, &ssdst); 6950e81959dSBjoern A. Zeeb rt_Update(bundle, sadst, sagw, samask, NULL, NULL); 69630949fd4SBrian Somers } 6973afe5ccbSBrian Somers 698610b185fSBrian Somers if (Enabled(bundle, OPT_SROUTES)) 69930949fd4SBrian Somers route_Change(bundle, bundle->ncp.route, &myncpaddr, &hisncpaddr); 700610b185fSBrian Somers 701972a1bcfSBrian Somers #ifndef NORADIUS 702972a1bcfSBrian Somers if (bundle->radius.valid) 70330949fd4SBrian Somers route_Change(bundle, bundle->radius.routes, &myncpaddr, &hisncpaddr); 704972a1bcfSBrian Somers #endif 705972a1bcfSBrian Somers 70630949fd4SBrian Somers return 1; /* Ok */ 707455aabc3SBrian Somers } 708455aabc3SBrian Somers 709455aabc3SBrian Somers static struct in_addr 7108fa6ebe4SBrian Somers ChooseHisAddr(struct bundle *bundle, struct in_addr gw) 711455aabc3SBrian Somers { 712455aabc3SBrian Somers struct in_addr try; 7133a2e4f62SBrian Somers u_long f; 714455aabc3SBrian Somers 7155828db6dSBrian Somers for (f = 0; f < bundle->ncp.ipcp.cfg.peer_list.nItems; f++) { 7165828db6dSBrian Somers try = iplist_next(&bundle->ncp.ipcp.cfg.peer_list); 7173a2e4f62SBrian Somers log_Printf(LogDEBUG, "ChooseHisAddr: Check item %ld (%s)\n", 718455aabc3SBrian Somers f, inet_ntoa(try)); 71930949fd4SBrian Somers if (ipcp_SetIPaddress(&bundle->ncp.ipcp, gw, try)) { 720dd7e2610SBrian Somers log_Printf(LogIPCP, "Selected IP address %s\n", inet_ntoa(try)); 721455aabc3SBrian Somers break; 722455aabc3SBrian Somers } 723455aabc3SBrian Somers } 724455aabc3SBrian Somers 7255828db6dSBrian Somers if (f == bundle->ncp.ipcp.cfg.peer_list.nItems) { 726dd7e2610SBrian Somers log_Printf(LogDEBUG, "ChooseHisAddr: All addresses in use !\n"); 727455aabc3SBrian Somers try.s_addr = INADDR_ANY; 728455aabc3SBrian Somers } 729455aabc3SBrian Somers 730455aabc3SBrian Somers return try; 731af57ed9fSAtsushi Murai } 732af57ed9fSAtsushi Murai 733af57ed9fSAtsushi Murai static void 734479508cfSBrian Somers IpcpInitRestartCounter(struct fsm *fp, int what) 735af57ed9fSAtsushi Murai { 7367308ec68SBrian Somers /* Set fsm timer load */ 737cd9647a1SBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 738cd9647a1SBrian Somers 739479508cfSBrian Somers fp->FsmTimer.load = ipcp->cfg.fsm.timeout * SECTICKS; 740479508cfSBrian Somers switch (what) { 741479508cfSBrian Somers case FSM_REQ_TIMER: 742479508cfSBrian Somers fp->restart = ipcp->cfg.fsm.maxreq; 743479508cfSBrian Somers break; 744479508cfSBrian Somers case FSM_TRM_TIMER: 745479508cfSBrian Somers fp->restart = ipcp->cfg.fsm.maxtrm; 746479508cfSBrian Somers break; 747479508cfSBrian Somers default: 748479508cfSBrian Somers fp->restart = 1; 749479508cfSBrian Somers break; 750479508cfSBrian Somers } 751af57ed9fSAtsushi Murai } 752af57ed9fSAtsushi Murai 753af57ed9fSAtsushi Murai static void 754944f7098SBrian Somers IpcpSendConfigReq(struct fsm *fp) 755af57ed9fSAtsushi Murai { 7567308ec68SBrian Somers /* Send config REQ please */ 7578c07a7b2SBrian Somers struct physical *p = link2physical(fp->link); 758aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 759eb1ecbb2SBrian Somers u_char buff[MAX_FSM_OPT_LEN]; 760ff360cc9SBrian Somers struct fsm_opt *o; 761af57ed9fSAtsushi Murai 762ff360cc9SBrian Somers o = (struct fsm_opt *)buff; 76330c2f2ffSBrian Somers 764dd7e2610SBrian Somers if ((p && !physical_IsSync(p)) || !REJECTED(ipcp, TY_IPADDR)) { 7659e8ec64bSBrian Somers memcpy(o->data, &ipcp->my_ip.s_addr, 4); 766ff360cc9SBrian Somers INC_FSM_OPT(TY_IPADDR, 6, o); 7670053cc58SBrian Somers } 7680053cc58SBrian Somers 769e43ebac1SBrian Somers if (ipcp->my_compproto && !REJECTED(ipcp, TY_COMPPROTO)) { 77083d1af55SBrian Somers if (ipcp->heis1172) { 7719e8ec64bSBrian Somers u_int16_t proto = PROTO_VJCOMP; 7729e8ec64bSBrian Somers 7739e8ec64bSBrian Somers ua_htons(&proto, o->data); 774ff360cc9SBrian Somers INC_FSM_OPT(TY_COMPPROTO, 4, o); 7750053cc58SBrian Somers } else { 7767686a200SBrian Somers struct compreq req; 7777686a200SBrian Somers 7787686a200SBrian Somers req.proto = htons(ipcp->my_compproto >> 16); 7797686a200SBrian Somers req.slots = (ipcp->my_compproto >> 8) & 255; 7807686a200SBrian Somers req.compcid = ipcp->my_compproto & 1; 7817686a200SBrian Somers memcpy(o->data, &req, 4); 782ff360cc9SBrian Somers INC_FSM_OPT(TY_COMPPROTO, 6, o); 7830053cc58SBrian Somers } 784af57ed9fSAtsushi Murai } 7852267893fSBrian Somers 78630949fd4SBrian Somers if (IsEnabled(ipcp->cfg.ns.dns_neg)) { 78730949fd4SBrian Somers if (!REJECTED(ipcp, TY_PRIMARY_DNS - TY_ADJUST_NS)) { 78830949fd4SBrian Somers memcpy(o->data, &ipcp->ns.dns[0].s_addr, 4); 789ff360cc9SBrian Somers INC_FSM_OPT(TY_PRIMARY_DNS, 6, o); 7907d39b1e3SBrian Somers } 7917d39b1e3SBrian Somers 79230949fd4SBrian Somers if (!REJECTED(ipcp, TY_SECONDARY_DNS - TY_ADJUST_NS)) { 79330949fd4SBrian Somers memcpy(o->data, &ipcp->ns.dns[1].s_addr, 4); 794ff360cc9SBrian Somers INC_FSM_OPT(TY_SECONDARY_DNS, 6, o); 7953edeb0c6SBrian Somers } 79630949fd4SBrian Somers } 7973edeb0c6SBrian Somers 798411675baSBrian Somers fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff, 799411675baSBrian Somers MB_IPCPOUT); 800af57ed9fSAtsushi Murai } 801af57ed9fSAtsushi Murai 802af57ed9fSAtsushi Murai static void 803057f1760SBrian Somers IpcpSentTerminateReq(struct fsm *fp __unused) 804af57ed9fSAtsushi Murai { 8057308ec68SBrian Somers /* Term REQ just sent by FSM */ 806af57ed9fSAtsushi Murai } 807af57ed9fSAtsushi Murai 808af57ed9fSAtsushi Murai static void 8092267893fSBrian Somers IpcpSendTerminateAck(struct fsm *fp, u_char id) 810af57ed9fSAtsushi Murai { 8117308ec68SBrian Somers /* Send Term ACK please */ 812411675baSBrian Somers fsm_Output(fp, CODE_TERMACK, id, NULL, 0, MB_IPCPOUT); 813af57ed9fSAtsushi Murai } 814af57ed9fSAtsushi Murai 815af57ed9fSAtsushi Murai static void 816944f7098SBrian Somers IpcpLayerStart(struct fsm *fp) 817af57ed9fSAtsushi Murai { 8187308ec68SBrian Somers /* We're about to start up ! */ 819897f9429SBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 820897f9429SBrian Somers 8213a2e4f62SBrian Somers log_Printf(LogIPCP, "%s: LayerStart.\n", fp->link->name); 822897f9429SBrian Somers throughput_start(&ipcp->throughput, "IPCP throughput", 823897f9429SBrian Somers Enabled(fp->bundle, OPT_THROUGHPUT)); 824479508cfSBrian Somers fp->more.reqs = fp->more.naks = fp->more.rejs = ipcp->cfg.fsm.maxreq * 3; 8255e3b2d68SBrian Somers ipcp->peer_req = 0; 826af57ed9fSAtsushi Murai } 827af57ed9fSAtsushi Murai 828af57ed9fSAtsushi Murai static void 829944f7098SBrian Somers IpcpLayerFinish(struct fsm *fp) 830af57ed9fSAtsushi Murai { 8317308ec68SBrian Somers /* We're now down */ 832897f9429SBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 833897f9429SBrian Somers 8343a2e4f62SBrian Somers log_Printf(LogIPCP, "%s: LayerFinish.\n", fp->link->name); 835897f9429SBrian Somers throughput_stop(&ipcp->throughput); 836897f9429SBrian Somers throughput_log(&ipcp->throughput, LogIPCP, NULL); 8371ae349f5Scvs2svn } 8381ae349f5Scvs2svn 83930949fd4SBrian Somers /* 84030949fd4SBrian Somers * Called from iface_Add() via ncp_IfaceAddrAdded() 84130949fd4SBrian Somers */ 84268a0f0ccSBrian Somers void 84330949fd4SBrian Somers ipcp_IfaceAddrAdded(struct ipcp *ipcp, const struct iface_addr *addr) 84468a0f0ccSBrian Somers { 84530949fd4SBrian Somers struct bundle *bundle = ipcp->fsm.bundle; 84668a0f0ccSBrian Somers 84730949fd4SBrian Somers if (Enabled(bundle, OPT_PROXY) || Enabled(bundle, OPT_PROXYALL)) 84830949fd4SBrian Somers ipcp_proxyarp(ipcp, arp_SetProxy, addr); 84968a0f0ccSBrian Somers } 85068a0f0ccSBrian Somers 85130949fd4SBrian Somers /* 85230949fd4SBrian Somers * Called from iface_Clear() and iface_Delete() via ncp_IfaceAddrDeleted() 85330949fd4SBrian Somers */ 85430949fd4SBrian Somers void 85530949fd4SBrian Somers ipcp_IfaceAddrDeleted(struct ipcp *ipcp, const struct iface_addr *addr) 85630949fd4SBrian Somers { 85730949fd4SBrian Somers struct bundle *bundle = ipcp->fsm.bundle; 85830949fd4SBrian Somers 85930949fd4SBrian Somers if (Enabled(bundle, OPT_PROXY) || Enabled(bundle, OPT_PROXYALL)) 86030949fd4SBrian Somers ipcp_proxyarp(ipcp, arp_ClearProxy, addr); 861af57ed9fSAtsushi Murai } 862af57ed9fSAtsushi Murai 863af57ed9fSAtsushi Murai static void 864944f7098SBrian Somers IpcpLayerDown(struct fsm *fp) 865af57ed9fSAtsushi Murai { 8667308ec68SBrian Somers /* About to come down */ 867aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 86830949fd4SBrian Somers static int recursing; 86930949fd4SBrian Somers char addr[16]; 870455aabc3SBrian Somers 871aa857470SBrian Somers if (!recursing++) { 87230949fd4SBrian Somers snprintf(addr, sizeof addr, "%s", inet_ntoa(ipcp->my_ip)); 87330949fd4SBrian Somers log_Printf(LogIPCP, "%s: LayerDown: %s\n", fp->link->name, addr); 874455aabc3SBrian Somers 875794c9bbcSBrian Somers #ifndef NORADIUS 87688044778SBrian Somers radius_Flush(&fp->bundle->radius); 877794c9bbcSBrian Somers radius_Account(&fp->bundle->radius, &fp->bundle->radacct, 878cf7c10d0SHajimu UMEMOTO fp->bundle->links, RAD_STOP, &ipcp->throughput); 879635ad5f0SBrian Somers 880635ad5f0SBrian Somers if (fp->bundle->radius.cfg.file && fp->bundle->radius.filterid) 881635ad5f0SBrian Somers system_Select(fp->bundle, fp->bundle->radius.filterid, LINKDOWNFILE, 882635ad5f0SBrian Somers NULL, NULL); 883e715b13bSBrian Somers radius_StopTimer(&fp->bundle->radius); 884794c9bbcSBrian Somers #endif 885794c9bbcSBrian Somers 886455aabc3SBrian Somers /* 887455aabc3SBrian Somers * XXX this stuff should really live in the FSM. Our config should 888455aabc3SBrian Somers * associate executable sections in files with events. 889455aabc3SBrian Somers */ 89030949fd4SBrian Somers if (system_Select(fp->bundle, addr, LINKDOWNFILE, NULL, NULL) < 0) { 89149052c95SBrian Somers if (bundle_GetLabel(fp->bundle)) { 892dd7e2610SBrian Somers if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle), 89330291ffbSBrian Somers LINKDOWNFILE, NULL, NULL) < 0) 89430291ffbSBrian Somers system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL); 895455aabc3SBrian Somers } else 89630291ffbSBrian Somers system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL); 897af57ed9fSAtsushi Murai } 898af57ed9fSAtsushi Murai 899972a1bcfSBrian Somers ipcp_Setup(ipcp, INADDR_NONE); 9001ae349f5Scvs2svn } 901aa857470SBrian Somers recursing--; 902aa857470SBrian Somers } 9031ae349f5Scvs2svn 904dd0645c5SBrian Somers int 905dd0645c5SBrian Somers ipcp_InterfaceUp(struct ipcp *ipcp) 906dd0645c5SBrian Somers { 90730949fd4SBrian Somers if (!ipcp_SetIPaddress(ipcp, ipcp->my_ip, ipcp->peer_ip)) { 908a33b2ef7SBrian Somers log_Printf(LogERROR, "ipcp_InterfaceUp: unable to set ip address\n"); 909dd0645c5SBrian Somers return 0; 910dd0645c5SBrian Somers } 911dd0645c5SBrian Somers 912448374baSBrian Somers if (!iface_SetFlags(ipcp->fsm.bundle->iface->name, IFF_UP)) { 913448374baSBrian Somers log_Printf(LogERROR, "ipcp_InterfaceUp: Can't set the IFF_UP flag on %s\n", 914448374baSBrian Somers ipcp->fsm.bundle->iface->name); 915448374baSBrian Somers return 0; 916448374baSBrian Somers } 917448374baSBrian Somers 91867b072f7SBrian Somers #ifndef NONAT 91967b072f7SBrian Somers if (ipcp->fsm.bundle->NatEnabled) 920a5625ae7SPaolo Pisati LibAliasSetAddress(la, ipcp->my_ip); 921dd0645c5SBrian Somers #endif 922dd0645c5SBrian Somers 923dd0645c5SBrian Somers return 1; 924dd0645c5SBrian Somers } 925dd0645c5SBrian Somers 9266f384573SBrian Somers static int 927944f7098SBrian Somers IpcpLayerUp(struct fsm *fp) 928af57ed9fSAtsushi Murai { 9297308ec68SBrian Somers /* We're now up */ 930aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 9318fa6ebe4SBrian Somers char tbuff[16]; 932af57ed9fSAtsushi Murai 9333a2e4f62SBrian Somers log_Printf(LogIPCP, "%s: LayerUp.\n", fp->link->name); 9348fa6ebe4SBrian Somers snprintf(tbuff, sizeof tbuff, "%s", inet_ntoa(ipcp->my_ip)); 9358fa6ebe4SBrian Somers log_Printf(LogIPCP, "myaddr %s hisaddr = %s\n", 9368fa6ebe4SBrian Somers tbuff, inet_ntoa(ipcp->peer_ip)); 93703604f35SBrian Somers 938503a7782SBrian Somers if (ipcp->peer_compproto >> 16 == PROTO_VJCOMP) 939eaa4df37SBrian Somers sl_compress_init(&ipcp->vj.cslc, (ipcp->peer_compproto >> 8) & 255); 94003604f35SBrian Somers 941dd0645c5SBrian Somers if (!ipcp_InterfaceUp(ipcp)) 9426f384573SBrian Somers return 0; 943455aabc3SBrian Somers 944794c9bbcSBrian Somers #ifndef NORADIUS 945cf7c10d0SHajimu UMEMOTO radius_Account_Set_Ip(&fp->bundle->radacct, &ipcp->peer_ip, &ipcp->ifmask); 946794c9bbcSBrian Somers radius_Account(&fp->bundle->radius, &fp->bundle->radacct, fp->bundle->links, 947cf7c10d0SHajimu UMEMOTO RAD_START, &ipcp->throughput); 948635ad5f0SBrian Somers 949635ad5f0SBrian Somers if (fp->bundle->radius.cfg.file && fp->bundle->radius.filterid) 950635ad5f0SBrian Somers system_Select(fp->bundle, fp->bundle->radius.filterid, LINKUPFILE, 951635ad5f0SBrian Somers NULL, NULL); 952e715b13bSBrian Somers radius_StartTimer(fp->bundle); 953794c9bbcSBrian Somers #endif 954794c9bbcSBrian Somers 955455aabc3SBrian Somers /* 956455aabc3SBrian Somers * XXX this stuff should really live in the FSM. Our config should 957455aabc3SBrian Somers * associate executable sections in files with events. 958455aabc3SBrian Somers */ 9598fa6ebe4SBrian Somers if (system_Select(fp->bundle, tbuff, LINKUPFILE, NULL, NULL) < 0) { 96049052c95SBrian Somers if (bundle_GetLabel(fp->bundle)) { 961dd7e2610SBrian Somers if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle), 96230291ffbSBrian Somers LINKUPFILE, NULL, NULL) < 0) 96330291ffbSBrian Somers system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL); 964455aabc3SBrian Somers } else 96530291ffbSBrian Somers system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL); 966af57ed9fSAtsushi Murai } 967af57ed9fSAtsushi Murai 968479508cfSBrian Somers fp->more.reqs = fp->more.naks = fp->more.rejs = ipcp->cfg.fsm.maxreq * 3; 9690f2f3eb3SBrian Somers log_DisplayPrompts(); 970479508cfSBrian Somers 9716f384573SBrian Somers return 1; 972af57ed9fSAtsushi Murai } 973af57ed9fSAtsushi Murai 974af57ed9fSAtsushi Murai static void 9755f73635bSBrian Somers ipcp_ValidateReq(struct ipcp *ipcp, struct in_addr ip, struct fsm_decode *dec) 9765f73635bSBrian Somers { 9775f73635bSBrian Somers struct bundle *bundle = ipcp->fsm.bundle; 9785f73635bSBrian Somers struct iface *iface = bundle->iface; 97930949fd4SBrian Somers struct in_addr myaddr, peer; 980057f1760SBrian Somers unsigned n; 9815f73635bSBrian Somers 9825f73635bSBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 98330949fd4SBrian Somers ncprange_getip4addr(&ipcp->cfg.my_range, &myaddr); 9845f73635bSBrian Somers if (ip.s_addr == INADDR_ANY || 9855f73635bSBrian Somers iplist_ip2pos(&ipcp->cfg.peer_list, ip) < 0 || 98630949fd4SBrian Somers !ipcp_SetIPaddress(ipcp, myaddr, ip)) { 9875f73635bSBrian Somers log_Printf(LogIPCP, "%s: Address invalid or already in use\n", 9885f73635bSBrian Somers inet_ntoa(ip)); 9895f73635bSBrian Somers /* 9905f73635bSBrian Somers * If we've already had a valid address configured for the peer, 9915f73635bSBrian Somers * try NAKing with that so that we don't have to upset things 9925f73635bSBrian Somers * too much. 9935f73635bSBrian Somers */ 99430949fd4SBrian Somers for (n = 0; n < iface->addrs; n++) { 99530949fd4SBrian Somers if (!ncpaddr_getip4(&iface->addr[n].peer, &peer)) 99630949fd4SBrian Somers continue; 99730949fd4SBrian Somers if (iplist_ip2pos(&ipcp->cfg.peer_list, peer) >= 0) { 99830949fd4SBrian Somers ipcp->peer_ip = peer; 9995f73635bSBrian Somers break; 10005f73635bSBrian Somers } 100130949fd4SBrian Somers } 10025f73635bSBrian Somers 100330949fd4SBrian Somers if (n == iface->addrs) { 10045f73635bSBrian Somers /* Just pick an IP number from our list */ 100530949fd4SBrian Somers ipcp->peer_ip = ChooseHisAddr(bundle, myaddr); 100630949fd4SBrian Somers } 10075f73635bSBrian Somers 10085f73635bSBrian Somers if (ipcp->peer_ip.s_addr == INADDR_ANY) { 10095f73635bSBrian Somers *dec->rejend++ = TY_IPADDR; 10105f73635bSBrian Somers *dec->rejend++ = 6; 10115f73635bSBrian Somers memcpy(dec->rejend, &ip.s_addr, 4); 10125f73635bSBrian Somers dec->rejend += 4; 10135f73635bSBrian Somers } else { 10145f73635bSBrian Somers *dec->nakend++ = TY_IPADDR; 10155f73635bSBrian Somers *dec->nakend++ = 6; 10165f73635bSBrian Somers memcpy(dec->nakend, &ipcp->peer_ip.s_addr, 4); 10175f73635bSBrian Somers dec->nakend += 4; 10185f73635bSBrian Somers } 10195f73635bSBrian Somers return; 10205f73635bSBrian Somers } 10213c34956aSBrian Somers } else if (ip.s_addr == INADDR_ANY || 10223c34956aSBrian Somers !ncprange_containsip4(&ipcp->cfg.peer_range, ip)) { 10235f73635bSBrian Somers /* 10245f73635bSBrian Somers * If the destination address is not acceptable, NAK with what we 10255f73635bSBrian Somers * want to use. 10265f73635bSBrian Somers */ 10275f73635bSBrian Somers *dec->nakend++ = TY_IPADDR; 10285f73635bSBrian Somers *dec->nakend++ = 6; 102930949fd4SBrian Somers for (n = 0; n < iface->addrs; n++) 103030949fd4SBrian Somers if (ncprange_contains(&ipcp->cfg.peer_range, &iface->addr[n].peer)) { 10315f73635bSBrian Somers /* We prefer the already-configured address */ 103230949fd4SBrian Somers ncpaddr_getip4addr(&iface->addr[n].peer, (u_int32_t *)dec->nakend); 10335f73635bSBrian Somers break; 10345f73635bSBrian Somers } 10355f73635bSBrian Somers 103630949fd4SBrian Somers if (n == iface->addrs) 10375f73635bSBrian Somers memcpy(dec->nakend, &ipcp->peer_ip.s_addr, 4); 10385f73635bSBrian Somers 10395f73635bSBrian Somers dec->nakend += 4; 10405f73635bSBrian Somers return; 10415f73635bSBrian Somers } 10425f73635bSBrian Somers 10435f73635bSBrian Somers ipcp->peer_ip = ip; 10445f73635bSBrian Somers *dec->ackend++ = TY_IPADDR; 10455f73635bSBrian Somers *dec->ackend++ = 6; 10465f73635bSBrian Somers memcpy(dec->ackend, &ip.s_addr, 4); 10475f73635bSBrian Somers dec->ackend += 4; 10485f73635bSBrian Somers } 10495f73635bSBrian Somers 10505f73635bSBrian Somers static void 1051ff360cc9SBrian Somers IpcpDecodeConfig(struct fsm *fp, u_char *cp, u_char *end, int mode_type, 105230c2f2ffSBrian Somers struct fsm_decode *dec) 1053af57ed9fSAtsushi Murai { 10547308ec68SBrian Somers /* Deal with incoming PROTO_IPCP */ 105530949fd4SBrian Somers struct ncpaddr ncpaddr; 1056aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 1057ff360cc9SBrian Somers int gotdnsnak; 1058fe3125a0SBrian Somers u_int32_t compproto; 1059eb1ecbb2SBrian Somers struct compreq pcomp; 1060d568d6c4SBrian Somers struct in_addr ipaddr, dstipaddr, have_ip; 106130c2f2ffSBrian Somers char tbuff[100], tbuff2[100]; 1062ff360cc9SBrian Somers struct fsm_opt *opt, nak; 1063af57ed9fSAtsushi Murai 10643edeb0c6SBrian Somers gotdnsnak = 0; 1065af57ed9fSAtsushi Murai 1066057f1760SBrian Somers while (end - cp >= (int)sizeof(opt->hdr)) { 1067ff360cc9SBrian Somers if ((opt = fsm_readopt(&cp)) == NULL) 1068d47dceb8SBrian Somers break; 1069d47dceb8SBrian Somers 1070ff360cc9SBrian Somers snprintf(tbuff, sizeof tbuff, " %s[%d]", protoname(opt->hdr.id), 1071ff360cc9SBrian Somers opt->hdr.len); 1072af57ed9fSAtsushi Murai 1073ff360cc9SBrian Somers switch (opt->hdr.id) { 1074af57ed9fSAtsushi Murai case TY_IPADDR: /* RFC1332 */ 1075ff360cc9SBrian Somers memcpy(&ipaddr.s_addr, opt->data, 4); 1076dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 1077af57ed9fSAtsushi Murai 10789780ef31SBrian Somers switch (mode_type) { 1079af57ed9fSAtsushi Murai case MODE_REQ: 10805e3b2d68SBrian Somers ipcp->peer_req = 1; 10815f73635bSBrian Somers ipcp_ValidateReq(ipcp, ipaddr, dec); 1082af57ed9fSAtsushi Murai break; 10838fa6ebe4SBrian Somers 1084af57ed9fSAtsushi Murai case MODE_NAK: 108530949fd4SBrian Somers if (ncprange_containsip4(&ipcp->cfg.my_range, ipaddr)) { 1086bcc332bdSBrian Somers /* Use address suggested by peer */ 108770ee81ffSBrian Somers snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s ", tbuff, 1088503a7782SBrian Somers inet_ntoa(ipcp->my_ip)); 1089dd7e2610SBrian Somers log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 1090503a7782SBrian Somers ipcp->my_ip = ipaddr; 109130949fd4SBrian Somers ncpaddr_setip4(&ncpaddr, ipcp->my_ip); 109230949fd4SBrian Somers bundle_AdjustFilters(fp->bundle, &ncpaddr, NULL); 1093bcc332bdSBrian Somers } else { 1094dd7e2610SBrian Somers log_Printf(log_IsKept(LogIPCP) ? LogIPCP : LogPHASE, 10958390b576SBrian Somers "%s: Unacceptable address!\n", inet_ntoa(ipaddr)); 1096dd7e2610SBrian Somers fsm_Close(&ipcp->fsm); 1097af57ed9fSAtsushi Murai } 1098af57ed9fSAtsushi Murai break; 10998fa6ebe4SBrian Somers 1100af57ed9fSAtsushi Murai case MODE_REJ: 1101ff360cc9SBrian Somers ipcp->peer_reject |= (1 << opt->hdr.id); 1102af57ed9fSAtsushi Murai break; 1103af57ed9fSAtsushi Murai } 1104af57ed9fSAtsushi Murai break; 11058fa6ebe4SBrian Somers 1106af57ed9fSAtsushi Murai case TY_COMPPROTO: 1107eb1ecbb2SBrian Somers memcpy(&pcomp, opt->data, sizeof pcomp); 1108eb1ecbb2SBrian Somers compproto = (ntohs(pcomp.proto) << 16) + ((int)pcomp.slots << 8) + 1109eb1ecbb2SBrian Somers pcomp.compcid; 1110dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto)); 1111af57ed9fSAtsushi Murai 11129780ef31SBrian Somers switch (mode_type) { 1113af57ed9fSAtsushi Murai case MODE_REQ: 1114ff360cc9SBrian Somers if (!IsAccepted(ipcp->cfg.vj.neg)) 1115ff360cc9SBrian Somers fsm_rej(dec, opt); 1116ff360cc9SBrian Somers else { 1117ff360cc9SBrian Somers switch (opt->hdr.len) { 1118af57ed9fSAtsushi Murai case 4: /* RFC1172 */ 1119eb1ecbb2SBrian Somers if (ntohs(pcomp.proto) == PROTO_VJCOMP) { 11207686a200SBrian Somers log_Printf(LogWARN, "Peer is speaking RFC1172 compression " 11217686a200SBrian Somers "protocol !\n"); 112283d1af55SBrian Somers ipcp->heis1172 = 1; 1123503a7782SBrian Somers ipcp->peer_compproto = compproto; 1124ff360cc9SBrian Somers fsm_ack(dec, opt); 1125af57ed9fSAtsushi Murai } else { 1126eb1ecbb2SBrian Somers pcomp.proto = htons(PROTO_VJCOMP); 1127ff360cc9SBrian Somers nak.hdr.id = TY_COMPPROTO; 1128ff360cc9SBrian Somers nak.hdr.len = 4; 1129ff360cc9SBrian Somers memcpy(nak.data, &pcomp, 2); 1130ff360cc9SBrian Somers fsm_nak(dec, &nak); 1131af57ed9fSAtsushi Murai } 1132af57ed9fSAtsushi Murai break; 1133af57ed9fSAtsushi Murai case 6: /* RFC1332 */ 1134eb1ecbb2SBrian Somers if (ntohs(pcomp.proto) == PROTO_VJCOMP) { 1135eb1ecbb2SBrian Somers /* We know pcomp.slots' max value == MAX_VJ_STATES */ 1136eb1ecbb2SBrian Somers if (pcomp.slots >= MIN_VJ_STATES) { 11377686a200SBrian Somers /* Ok, we can do that */ 1138503a7782SBrian Somers ipcp->peer_compproto = compproto; 113983d1af55SBrian Somers ipcp->heis1172 = 0; 1140ff360cc9SBrian Somers fsm_ack(dec, opt); 1141af57ed9fSAtsushi Murai } else { 11427686a200SBrian Somers /* Get as close as we can to what he wants */ 11437686a200SBrian Somers ipcp->heis1172 = 0; 1144eb1ecbb2SBrian Somers pcomp.slots = MIN_VJ_STATES; 1145ff360cc9SBrian Somers nak.hdr.id = TY_COMPPROTO; 1146ff360cc9SBrian Somers nak.hdr.len = 4; 1147ff360cc9SBrian Somers memcpy(nak.data, &pcomp, 2); 1148ff360cc9SBrian Somers fsm_nak(dec, &nak); 11497686a200SBrian Somers } 11507686a200SBrian Somers } else { 11517686a200SBrian Somers /* What we really want */ 1152eb1ecbb2SBrian Somers pcomp.proto = htons(PROTO_VJCOMP); 1153eb1ecbb2SBrian Somers pcomp.slots = DEF_VJ_STATES; 1154eb1ecbb2SBrian Somers pcomp.compcid = 1; 1155ff360cc9SBrian Somers nak.hdr.id = TY_COMPPROTO; 1156ff360cc9SBrian Somers nak.hdr.len = 6; 1157ff360cc9SBrian Somers memcpy(nak.data, &pcomp, sizeof pcomp); 1158ff360cc9SBrian Somers fsm_nak(dec, &nak); 1159af57ed9fSAtsushi Murai } 1160af57ed9fSAtsushi Murai break; 1161af57ed9fSAtsushi Murai default: 1162ff360cc9SBrian Somers fsm_rej(dec, opt); 1163af57ed9fSAtsushi Murai break; 1164af57ed9fSAtsushi Murai } 1165af57ed9fSAtsushi Murai } 1166af57ed9fSAtsushi Murai break; 11678fa6ebe4SBrian Somers 1168af57ed9fSAtsushi Murai case MODE_NAK: 1169eb1ecbb2SBrian Somers if (ntohs(pcomp.proto) == PROTO_VJCOMP) { 1170eb1ecbb2SBrian Somers /* We know pcomp.slots' max value == MAX_VJ_STATES */ 1171eb1ecbb2SBrian Somers if (pcomp.slots < MIN_VJ_STATES) 1172eb1ecbb2SBrian Somers pcomp.slots = MIN_VJ_STATES; 1173eb1ecbb2SBrian Somers compproto = (ntohs(pcomp.proto) << 16) + (pcomp.slots << 8) + 1174eb1ecbb2SBrian Somers pcomp.compcid; 11757686a200SBrian Somers } else 11767686a200SBrian Somers compproto = 0; 1177dd7e2610SBrian Somers log_Printf(LogIPCP, "%s changing compproto: %08x --> %08x\n", 1178503a7782SBrian Somers tbuff, ipcp->my_compproto, compproto); 1179503a7782SBrian Somers ipcp->my_compproto = compproto; 1180af57ed9fSAtsushi Murai break; 11818fa6ebe4SBrian Somers 1182af57ed9fSAtsushi Murai case MODE_REJ: 1183ff360cc9SBrian Somers ipcp->peer_reject |= (1 << opt->hdr.id); 1184af57ed9fSAtsushi Murai break; 1185af57ed9fSAtsushi Murai } 1186af57ed9fSAtsushi Murai break; 11878fa6ebe4SBrian Somers 1188af57ed9fSAtsushi Murai case TY_IPADDRS: /* RFC1172 */ 1189ff360cc9SBrian Somers memcpy(&ipaddr.s_addr, opt->data, 4); 1190ff360cc9SBrian Somers memcpy(&dstipaddr.s_addr, opt->data + 4, 4); 119170ee81ffSBrian Somers snprintf(tbuff2, sizeof tbuff2, "%s %s,", tbuff, inet_ntoa(ipaddr)); 1192dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr)); 1193af57ed9fSAtsushi Murai 11949780ef31SBrian Somers switch (mode_type) { 1195af57ed9fSAtsushi Murai case MODE_REQ: 1196ff360cc9SBrian Somers fsm_rej(dec, opt); 1197af57ed9fSAtsushi Murai break; 11988fa6ebe4SBrian Somers 1199af57ed9fSAtsushi Murai case MODE_NAK: 1200af57ed9fSAtsushi Murai case MODE_REJ: 1201af57ed9fSAtsushi Murai break; 1202af57ed9fSAtsushi Murai } 1203af57ed9fSAtsushi Murai break; 1204d8e55738SJordan K. Hubbard 12053edeb0c6SBrian Somers case TY_PRIMARY_DNS: /* DNS negotiation (rfc1877) */ 1206d8e55738SJordan K. Hubbard case TY_SECONDARY_DNS: 1207ff360cc9SBrian Somers memcpy(&ipaddr.s_addr, opt->data, 4); 1208dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 12093edeb0c6SBrian Somers 12109780ef31SBrian Somers switch (mode_type) { 1211d8e55738SJordan K. Hubbard case MODE_REQ: 12123edeb0c6SBrian Somers if (!IsAccepted(ipcp->cfg.ns.dns_neg)) { 1213ff360cc9SBrian Somers ipcp->my_reject |= (1 << (opt->hdr.id - TY_ADJUST_NS)); 1214ff360cc9SBrian Somers fsm_rej(dec, opt); 1215d8e55738SJordan K. Hubbard break; 1216d8e55738SJordan K. Hubbard } 1217ff360cc9SBrian Somers have_ip = ipcp->ns.dns[opt->hdr.id == TY_PRIMARY_DNS ? 0 : 1]; 1218d568d6c4SBrian Somers 1219ff360cc9SBrian Somers if (opt->hdr.id == TY_PRIMARY_DNS && ipaddr.s_addr != have_ip.s_addr && 122030949fd4SBrian Somers ipaddr.s_addr == ipcp->ns.dns[1].s_addr) { 1221d568d6c4SBrian Somers /* Swap 'em 'round */ 122230949fd4SBrian Somers ipcp->ns.dns[0] = ipcp->ns.dns[1]; 122330949fd4SBrian Somers ipcp->ns.dns[1] = have_ip; 122430949fd4SBrian Somers have_ip = ipcp->ns.dns[0]; 12253edeb0c6SBrian Somers } 1226944f7098SBrian Somers 12273edeb0c6SBrian Somers if (ipaddr.s_addr != have_ip.s_addr) { 12281ae349f5Scvs2svn /* 12293edeb0c6SBrian Somers * The client has got the DNS stuff wrong (first request) so 12301ae349f5Scvs2svn * we'll tell 'em how it is 12311ae349f5Scvs2svn */ 1232ff360cc9SBrian Somers nak.hdr.id = opt->hdr.id; 1233ff360cc9SBrian Somers nak.hdr.len = 6; 1234ff360cc9SBrian Somers memcpy(nak.data, &have_ip.s_addr, 4); 1235ff360cc9SBrian Somers fsm_nak(dec, &nak); 12363edeb0c6SBrian Somers } else { 1237d8e55738SJordan K. Hubbard /* 12389d5abbddSJens Schweikhardt * Otherwise they have it right (this time) so we send an ack packet 1239944f7098SBrian Somers * back confirming it... end of story 1240d8e55738SJordan K. Hubbard */ 1241ff360cc9SBrian Somers fsm_ack(dec, opt); 12423edeb0c6SBrian Somers } 1243d8e55738SJordan K. Hubbard break; 12448fa6ebe4SBrian Somers 1245d568d6c4SBrian Somers case MODE_NAK: 12463edeb0c6SBrian Somers if (IsEnabled(ipcp->cfg.ns.dns_neg)) { 12473edeb0c6SBrian Somers gotdnsnak = 1; 1248ff360cc9SBrian Somers memcpy(&ipcp->ns.dns[opt->hdr.id == TY_PRIMARY_DNS ? 0 : 1].s_addr, 1249ff360cc9SBrian Somers opt->data, 4); 12503edeb0c6SBrian Somers } 1251d8e55738SJordan K. Hubbard break; 12528fa6ebe4SBrian Somers 12533edeb0c6SBrian Somers case MODE_REJ: /* Can't do much, stop asking */ 1254ff360cc9SBrian Somers ipcp->peer_reject |= (1 << (opt->hdr.id - TY_ADJUST_NS)); 1255d8e55738SJordan K. Hubbard break; 1256d8e55738SJordan K. Hubbard } 1257d8e55738SJordan K. Hubbard break; 1258d8e55738SJordan K. Hubbard 12593edeb0c6SBrian Somers case TY_PRIMARY_NBNS: /* M$ NetBIOS nameserver hack (rfc1877) */ 1260d8e55738SJordan K. Hubbard case TY_SECONDARY_NBNS: 1261ff360cc9SBrian Somers memcpy(&ipaddr.s_addr, opt->data, 4); 1262dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 12633edeb0c6SBrian Somers 12649780ef31SBrian Somers switch (mode_type) { 1265d8e55738SJordan K. Hubbard case MODE_REQ: 12663edeb0c6SBrian Somers have_ip.s_addr = 1267ff360cc9SBrian Somers ipcp->cfg.ns.nbns[opt->hdr.id == TY_PRIMARY_NBNS ? 0 : 1].s_addr; 12683edeb0c6SBrian Somers 12693edeb0c6SBrian Somers if (have_ip.s_addr == INADDR_ANY) { 1270dd7e2610SBrian Somers log_Printf(LogIPCP, "NBNS REQ - rejected - nbns not set\n"); 1271ff360cc9SBrian Somers ipcp->my_reject |= (1 << (opt->hdr.id - TY_ADJUST_NS)); 1272ff360cc9SBrian Somers fsm_rej(dec, opt); 1273d8e55738SJordan K. Hubbard break; 1274d8e55738SJordan K. Hubbard } 12753edeb0c6SBrian Somers 12763edeb0c6SBrian Somers if (ipaddr.s_addr != have_ip.s_addr) { 1277ff360cc9SBrian Somers nak.hdr.id = opt->hdr.id; 1278ff360cc9SBrian Somers nak.hdr.len = 6; 1279ff360cc9SBrian Somers memcpy(nak.data, &have_ip.s_addr, 4); 1280ff360cc9SBrian Somers fsm_nak(dec, &nak); 1281ff360cc9SBrian Somers } else 1282ff360cc9SBrian Somers fsm_ack(dec, opt); 1283d8e55738SJordan K. Hubbard break; 12848fa6ebe4SBrian Somers 1285d8e55738SJordan K. Hubbard case MODE_NAK: 1286ff360cc9SBrian Somers log_Printf(LogIPCP, "MS NBNS req %d - NAK??\n", opt->hdr.id); 1287d8e55738SJordan K. Hubbard break; 12888fa6ebe4SBrian Somers 1289d8e55738SJordan K. Hubbard case MODE_REJ: 1290ff360cc9SBrian Somers log_Printf(LogIPCP, "MS NBNS req %d - REJ??\n", opt->hdr.id); 1291d8e55738SJordan K. Hubbard break; 1292d8e55738SJordan K. Hubbard } 1293d8e55738SJordan K. Hubbard break; 1294d8e55738SJordan K. Hubbard 1295af57ed9fSAtsushi Murai default: 129630c2f2ffSBrian Somers if (mode_type != MODE_NOP) { 1297ff360cc9SBrian Somers ipcp->my_reject |= (1 << opt->hdr.id); 1298ff360cc9SBrian Somers fsm_rej(dec, opt); 129930c2f2ffSBrian Somers } 1300af57ed9fSAtsushi Murai break; 1301af57ed9fSAtsushi Murai } 1302af57ed9fSAtsushi Murai } 13031342caedSBrian Somers 1304d568d6c4SBrian Somers if (gotdnsnak) { 1305d568d6c4SBrian Somers if (ipcp->ns.writable) { 1306d568d6c4SBrian Somers log_Printf(LogDEBUG, "Updating resolver\n"); 1307d568d6c4SBrian Somers if (!ipcp_WriteDNS(ipcp)) { 13083edeb0c6SBrian Somers ipcp->peer_reject |= (1 << (TY_PRIMARY_DNS - TY_ADJUST_NS)); 13093edeb0c6SBrian Somers ipcp->peer_reject |= (1 << (TY_SECONDARY_DNS - TY_ADJUST_NS)); 1310d568d6c4SBrian Somers } else 131130949fd4SBrian Somers bundle_AdjustDNS(fp->bundle); 1312d568d6c4SBrian Somers } else { 1313d568d6c4SBrian Somers log_Printf(LogDEBUG, "Not updating resolver (readonly)\n"); 131430949fd4SBrian Somers bundle_AdjustDNS(fp->bundle); 1315d568d6c4SBrian Somers } 13163edeb0c6SBrian Somers } 13173edeb0c6SBrian Somers 1318e43ebac1SBrian Somers if (mode_type != MODE_NOP) { 13195e3b2d68SBrian Somers if (mode_type == MODE_REQ && !ipcp->peer_req) { 13205e3b2d68SBrian Somers if (dec->rejend == dec->rej && dec->nakend == dec->nak) { 13215e3b2d68SBrian Somers /* 13225e3b2d68SBrian Somers * Pretend the peer has requested an IP. 13235e3b2d68SBrian Somers * We do this to ensure that we only send one NAK if the only 13245e3b2d68SBrian Somers * reason for the NAK is because the peer isn't sending a 13255e3b2d68SBrian Somers * TY_IPADDR REQ. This stops us from repeatedly trying to tell 13265e3b2d68SBrian Somers * the peer that we have to have an IP address on their end. 13275e3b2d68SBrian Somers */ 13285e3b2d68SBrian Somers ipcp->peer_req = 1; 13295e3b2d68SBrian Somers } 13305f73635bSBrian Somers ipaddr.s_addr = INADDR_ANY; 13315f73635bSBrian Somers ipcp_ValidateReq(ipcp, ipaddr, dec); 13325f73635bSBrian Somers } 1333ff360cc9SBrian Somers fsm_opt_normalise(dec); 13341ae349f5Scvs2svn } 1335af57ed9fSAtsushi Murai } 1336af57ed9fSAtsushi Murai 13375d9e6103SBrian Somers extern struct mbuf * 13385d9e6103SBrian Somers ipcp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 1339af57ed9fSAtsushi Murai { 13407308ec68SBrian Somers /* Got PROTO_IPCP from link */ 134126af0ae9SBrian Somers m_settype(bp, MB_IPCPIN); 1342641684cdSBrian Somers if (bundle_Phase(bundle) == PHASE_NETWORK) 13435d9e6103SBrian Somers fsm_Input(&bundle->ncp.ipcp.fsm, bp); 1344641684cdSBrian Somers else { 1345641684cdSBrian Somers if (bundle_Phase(bundle) < PHASE_NETWORK) 1346641684cdSBrian Somers log_Printf(LogIPCP, "%s: Error: Unexpected IPCP in phase %s (ignored)\n", 13475d9e6103SBrian Somers l->name, bundle_PhaseName(bundle)); 134826af0ae9SBrian Somers m_freem(bp); 1349641684cdSBrian Somers } 13505d9e6103SBrian Somers return NULL; 1351af57ed9fSAtsushi Murai } 13529c97abd8SBrian Somers 13539c97abd8SBrian Somers int 1354972a1bcfSBrian Somers ipcp_UseHisIPaddr(struct bundle *bundle, struct in_addr hisaddr) 1355972a1bcfSBrian Somers { 1356972a1bcfSBrian Somers struct ipcp *ipcp = &bundle->ncp.ipcp; 135730949fd4SBrian Somers struct in_addr myaddr; 1358972a1bcfSBrian Somers 1359972a1bcfSBrian Somers memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 1360972a1bcfSBrian Somers iplist_reset(&ipcp->cfg.peer_list); 136130949fd4SBrian Somers ipcp->peer_ip = hisaddr; 136230949fd4SBrian Somers ncprange_setip4host(&ipcp->cfg.peer_range, hisaddr); 136330949fd4SBrian Somers ncprange_getip4addr(&ipcp->cfg.my_range, &myaddr); 1364972a1bcfSBrian Somers 136530949fd4SBrian Somers return ipcp_SetIPaddress(ipcp, myaddr, hisaddr); 1366972a1bcfSBrian Somers } 1367972a1bcfSBrian Somers 1368972a1bcfSBrian Somers int 1369dd7e2610SBrian Somers ipcp_UseHisaddr(struct bundle *bundle, const char *hisaddr, int setaddr) 13709c97abd8SBrian Somers { 137130949fd4SBrian Somers struct in_addr myaddr; 137230949fd4SBrian Somers struct ncp *ncp = &bundle->ncp; 137330949fd4SBrian Somers struct ipcp *ipcp = &ncp->ipcp; 137430949fd4SBrian Somers struct ncpaddr ncpaddr; 13755828db6dSBrian Somers 13767308ec68SBrian Somers /* Use `hisaddr' for the peers address (set iface if `setaddr') */ 13775828db6dSBrian Somers memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 13785828db6dSBrian Somers iplist_reset(&ipcp->cfg.peer_list); 13799c97abd8SBrian Somers if (strpbrk(hisaddr, ",-")) { 13805828db6dSBrian Somers iplist_setsrc(&ipcp->cfg.peer_list, hisaddr); 13815828db6dSBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 13825828db6dSBrian Somers iplist_setrandpos(&ipcp->cfg.peer_list); 138330c2f2ffSBrian Somers ipcp->peer_ip = ChooseHisAddr(bundle, ipcp->my_ip); 13845828db6dSBrian Somers if (ipcp->peer_ip.s_addr == INADDR_ANY) { 1385dd7e2610SBrian Somers log_Printf(LogWARN, "%s: None available !\n", ipcp->cfg.peer_list.src); 13861d1fc017SBrian Somers return 0; 13879c97abd8SBrian Somers } 138830949fd4SBrian Somers ncprange_setip4host(&ipcp->cfg.peer_range, ipcp->peer_ip); 13899c97abd8SBrian Somers } else { 1390dd7e2610SBrian Somers log_Printf(LogWARN, "%s: Invalid range !\n", hisaddr); 13919c97abd8SBrian Somers return 0; 13929c97abd8SBrian Somers } 139330949fd4SBrian Somers } else if (ncprange_aton(&ipcp->cfg.peer_range, ncp, hisaddr) != 0) { 139430949fd4SBrian Somers if (ncprange_family(&ipcp->cfg.my_range) != AF_INET) { 139530949fd4SBrian Somers log_Printf(LogWARN, "%s: Not an AF_INET address !\n", hisaddr); 139630949fd4SBrian Somers return 0; 139730949fd4SBrian Somers } 139830949fd4SBrian Somers ncprange_getip4addr(&ipcp->cfg.my_range, &myaddr); 139930949fd4SBrian Somers ncprange_getip4addr(&ipcp->cfg.peer_range, &ipcp->peer_ip); 14009c97abd8SBrian Somers 140130949fd4SBrian Somers if (setaddr && !ipcp_SetIPaddress(ipcp, myaddr, ipcp->peer_ip)) 14029c97abd8SBrian Somers return 0; 14039c97abd8SBrian Somers } else 14049c97abd8SBrian Somers return 0; 14059c97abd8SBrian Somers 140630949fd4SBrian Somers ncpaddr_setip4(&ncpaddr, ipcp->peer_ip); 140730949fd4SBrian Somers bundle_AdjustFilters(bundle, NULL, &ncpaddr); 14081d1fc017SBrian Somers 14091d1fc017SBrian Somers return 1; /* Ok */ 14109c97abd8SBrian Somers } 1411bc76350eSBrian Somers 1412bc76350eSBrian Somers struct in_addr 1413bc76350eSBrian Somers addr2mask(struct in_addr addr) 1414bc76350eSBrian Somers { 1415bc76350eSBrian Somers u_int32_t haddr = ntohl(addr.s_addr); 1416bc76350eSBrian Somers 1417bc76350eSBrian Somers haddr = IN_CLASSA(haddr) ? IN_CLASSA_NET : 1418bc76350eSBrian Somers IN_CLASSB(haddr) ? IN_CLASSB_NET : 1419bc76350eSBrian Somers IN_CLASSC_NET; 1420bc76350eSBrian Somers addr.s_addr = htonl(haddr); 1421bc76350eSBrian Somers 1422bc76350eSBrian Somers return addr; 1423bc76350eSBrian Somers } 142430949fd4SBrian Somers 142530949fd4SBrian Somers size_t 142630949fd4SBrian Somers ipcp_QueueLen(struct ipcp *ipcp) 142730949fd4SBrian Somers { 142830949fd4SBrian Somers struct mqueue *q; 142930949fd4SBrian Somers size_t result; 143030949fd4SBrian Somers 143130949fd4SBrian Somers result = 0; 143230949fd4SBrian Somers for (q = ipcp->Queue; q < ipcp->Queue + IPCP_QUEUES(ipcp); q++) 143330949fd4SBrian Somers result += q->len; 143430949fd4SBrian Somers 143530949fd4SBrian Somers return result; 143630949fd4SBrian Somers } 143730949fd4SBrian Somers 143830949fd4SBrian Somers int 143930949fd4SBrian Somers ipcp_PushPacket(struct ipcp *ipcp, struct link *l) 144030949fd4SBrian Somers { 144130949fd4SBrian Somers struct bundle *bundle = ipcp->fsm.bundle; 144230949fd4SBrian Somers struct mqueue *queue; 144330949fd4SBrian Somers struct mbuf *bp; 144430949fd4SBrian Somers int m_len; 144530949fd4SBrian Somers u_int32_t secs = 0; 144630949fd4SBrian Somers unsigned alivesecs = 0; 144730949fd4SBrian Somers 144830949fd4SBrian Somers if (ipcp->fsm.state != ST_OPENED) 144930949fd4SBrian Somers return 0; 145030949fd4SBrian Somers 145130949fd4SBrian Somers /* 145230949fd4SBrian Somers * If ccp is not open but is required, do nothing. 145330949fd4SBrian Somers */ 145430949fd4SBrian Somers if (l->ccp.fsm.state != ST_OPENED && ccp_Required(&l->ccp)) { 145530949fd4SBrian Somers log_Printf(LogPHASE, "%s: Not transmitting... waiting for CCP\n", l->name); 145630949fd4SBrian Somers return 0; 145730949fd4SBrian Somers } 145830949fd4SBrian Somers 145930949fd4SBrian Somers queue = ipcp->Queue + IPCP_QUEUES(ipcp) - 1; 146030949fd4SBrian Somers do { 146130949fd4SBrian Somers if (queue->top) { 146230949fd4SBrian Somers bp = m_dequeue(queue); 146330949fd4SBrian Somers bp = mbuf_Read(bp, &secs, sizeof secs); 146430949fd4SBrian Somers bp = m_pullup(bp); 146530949fd4SBrian Somers m_len = m_length(bp); 146630949fd4SBrian Somers if (!FilterCheck(MBUF_CTOP(bp), AF_INET, &bundle->filter.alive, 146730949fd4SBrian Somers &alivesecs)) { 146830949fd4SBrian Somers if (secs == 0) 146930949fd4SBrian Somers secs = alivesecs; 147030949fd4SBrian Somers bundle_StartIdleTimer(bundle, secs); 147130949fd4SBrian Somers } 147230949fd4SBrian Somers link_PushPacket(l, bp, bundle, 0, PROTO_IP); 147330949fd4SBrian Somers ipcp_AddOutOctets(ipcp, m_len); 147430949fd4SBrian Somers return 1; 147530949fd4SBrian Somers } 147630949fd4SBrian Somers } while (queue-- != ipcp->Queue); 147730949fd4SBrian Somers 147830949fd4SBrian Somers return 0; 147930949fd4SBrian Somers } 1480