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 } 322*bc92b078SGleb Smirnoff } else { 323d568d6c4SBrian Somers umask(mask); 324*bc92b078SGleb Smirnoff log_Printf(LogERROR,"fopen(\"%s\", \"w\") failed: %s\n", _PATH_RESCONF, 325*bc92b078SGleb Smirnoff strerror(errno)); 326*bc92b078SGleb Smirnoff } 3273edeb0c6SBrian Somers 3283edeb0c6SBrian Somers return 1; 329af57ed9fSAtsushi Murai } 330af57ed9fSAtsushi Murai 331d568d6c4SBrian Somers void 332d568d6c4SBrian Somers ipcp_RestoreDNS(struct ipcp *ipcp) 333d568d6c4SBrian Somers { 334d568d6c4SBrian Somers if (ipcp->ns.resolver) { 335057f1760SBrian Somers ssize_t got, len; 336d568d6c4SBrian Somers int fd; 337d568d6c4SBrian Somers 338d568d6c4SBrian Somers if ((fd = ID0open(_PATH_RESCONF, O_WRONLY|O_TRUNC, 0644)) != -1) { 339d568d6c4SBrian Somers len = strlen(ipcp->ns.resolv); 340d568d6c4SBrian Somers if ((got = write(fd, ipcp->ns.resolv, len)) != len) { 341d568d6c4SBrian Somers if (got == -1) 342d568d6c4SBrian Somers log_Printf(LogERROR, "Failed rewriting %s: write: %s\n", 343d568d6c4SBrian Somers _PATH_RESCONF, strerror(errno)); 344d568d6c4SBrian Somers else 345057f1760SBrian Somers log_Printf(LogERROR, "Failed rewriting %s: wrote %ld of %ld\n", 346057f1760SBrian Somers _PATH_RESCONF, (long)got, (long)len); 347d568d6c4SBrian Somers } 348d568d6c4SBrian Somers close(fd); 349d568d6c4SBrian Somers } else 350d568d6c4SBrian Somers log_Printf(LogERROR, "Failed rewriting %s: open: %s\n", _PATH_RESCONF, 351d568d6c4SBrian Somers strerror(errno)); 352d568d6c4SBrian Somers } else if (remove(_PATH_RESCONF) == -1) 353d568d6c4SBrian Somers log_Printf(LogERROR, "Failed removing %s: %s\n", _PATH_RESCONF, 354d568d6c4SBrian Somers strerror(errno)); 355d568d6c4SBrian Somers 356d568d6c4SBrian Somers } 357d568d6c4SBrian Somers 358274e766cSBrian Somers int 359dd7e2610SBrian Somers ipcp_Show(struct cmdargs const *arg) 360af57ed9fSAtsushi Murai { 361610b185fSBrian Somers struct ipcp *ipcp = &arg->bundle->ncp.ipcp; 362af57ed9fSAtsushi Murai 363610b185fSBrian Somers prompt_Printf(arg->prompt, "%s [%s]\n", ipcp->fsm.name, 364610b185fSBrian Somers State2Nam(ipcp->fsm.state)); 365610b185fSBrian Somers if (ipcp->fsm.state == ST_OPENED) { 366b6217683SBrian Somers prompt_Printf(arg->prompt, " His side: %s, %s\n", 367610b185fSBrian Somers inet_ntoa(ipcp->peer_ip), vj2asc(ipcp->peer_compproto)); 368b6217683SBrian Somers prompt_Printf(arg->prompt, " My side: %s, %s\n", 369610b185fSBrian Somers inet_ntoa(ipcp->my_ip), vj2asc(ipcp->my_compproto)); 370209dc102SBrian Somers prompt_Printf(arg->prompt, " Queued packets: %lu\n", 37130949fd4SBrian Somers (unsigned long)ipcp_QueueLen(ipcp)); 3721ae349f5Scvs2svn } 373927145beSBrian Somers 374b6217683SBrian Somers prompt_Printf(arg->prompt, "\nDefaults:\n"); 375479508cfSBrian Somers prompt_Printf(arg->prompt, " FSM retry = %us, max %u Config" 376479508cfSBrian Somers " REQ%s, %u Term REQ%s\n", ipcp->cfg.fsm.timeout, 377479508cfSBrian Somers ipcp->cfg.fsm.maxreq, ipcp->cfg.fsm.maxreq == 1 ? "" : "s", 378479508cfSBrian Somers ipcp->cfg.fsm.maxtrm, ipcp->cfg.fsm.maxtrm == 1 ? "" : "s"); 37930949fd4SBrian Somers prompt_Printf(arg->prompt, " My Address: %s\n", 38030949fd4SBrian Somers ncprange_ntoa(&ipcp->cfg.my_range)); 381610b185fSBrian Somers if (ipcp->cfg.HaveTriggerAddress) 382bc76350eSBrian Somers prompt_Printf(arg->prompt, " Trigger address: %s\n", 383610b185fSBrian Somers inet_ntoa(ipcp->cfg.TriggerAddress)); 384bc76350eSBrian Somers 385bc76350eSBrian Somers prompt_Printf(arg->prompt, " VJ compression: %s (%d slots %s slot " 386610b185fSBrian Somers "compression)\n", command_ShowNegval(ipcp->cfg.vj.neg), 387610b185fSBrian Somers ipcp->cfg.vj.slots, ipcp->cfg.vj.slotcomp ? "with" : "without"); 38850abd4c8SBrian Somers 389610b185fSBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) 390b6217683SBrian Somers prompt_Printf(arg->prompt, " His Address: %s\n", 391610b185fSBrian Somers ipcp->cfg.peer_list.src); 3921ae349f5Scvs2svn else 39330949fd4SBrian Somers prompt_Printf(arg->prompt, " His Address: %s\n", 39430949fd4SBrian Somers ncprange_ntoa(&ipcp->cfg.peer_range)); 39550abd4c8SBrian Somers 396d568d6c4SBrian Somers prompt_Printf(arg->prompt, " DNS: %s", 397d568d6c4SBrian Somers ipcp->cfg.ns.dns[0].s_addr == INADDR_NONE ? 398d568d6c4SBrian Somers "none" : inet_ntoa(ipcp->cfg.ns.dns[0])); 399d568d6c4SBrian Somers if (ipcp->cfg.ns.dns[1].s_addr != INADDR_NONE) 40030949fd4SBrian Somers prompt_Printf(arg->prompt, ", %s", 40130949fd4SBrian Somers inet_ntoa(ipcp->cfg.ns.dns[1])); 402d568d6c4SBrian Somers prompt_Printf(arg->prompt, ", %s\n", 403610b185fSBrian Somers command_ShowNegval(ipcp->cfg.ns.dns_neg)); 404d568d6c4SBrian Somers prompt_Printf(arg->prompt, " Resolver DNS: %s", 405d568d6c4SBrian Somers ipcp->ns.dns[0].s_addr == INADDR_NONE ? 406d568d6c4SBrian Somers "none" : inet_ntoa(ipcp->ns.dns[0])); 407d568d6c4SBrian Somers if (ipcp->ns.dns[1].s_addr != INADDR_NONE && 408d568d6c4SBrian Somers ipcp->ns.dns[1].s_addr != ipcp->ns.dns[0].s_addr) 40930949fd4SBrian Somers prompt_Printf(arg->prompt, ", %s", 41030949fd4SBrian Somers inet_ntoa(ipcp->ns.dns[1])); 411d568d6c4SBrian Somers prompt_Printf(arg->prompt, "\n NetBIOS NS: %s, ", 412610b185fSBrian Somers inet_ntoa(ipcp->cfg.ns.nbns[0])); 413ad1f9eaeSBrian Somers prompt_Printf(arg->prompt, "%s\n\n", 41430949fd4SBrian Somers inet_ntoa(ipcp->cfg.ns.nbns[1])); 415442f8495SBrian Somers 416610b185fSBrian Somers throughput_disp(&ipcp->throughput, arg->prompt); 4179a0b991fSBrian Somers 418927145beSBrian Somers return 0; 419af57ed9fSAtsushi Murai } 420af57ed9fSAtsushi Murai 421d1a3ea47SBrian Somers int 422dd7e2610SBrian Somers ipcp_vjset(struct cmdargs const *arg) 423d1a3ea47SBrian Somers { 42425092092SBrian Somers if (arg->argc != arg->argn+2) 425d1a3ea47SBrian Somers return -1; 42625092092SBrian Somers if (!strcasecmp(arg->argv[arg->argn], "slots")) { 427d1a3ea47SBrian Somers int slots; 428d1a3ea47SBrian Somers 42925092092SBrian Somers slots = atoi(arg->argv[arg->argn+1]); 430d1a3ea47SBrian Somers if (slots < 4 || slots > 16) 431d1a3ea47SBrian Somers return 1; 4321342caedSBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slots = slots; 433d1a3ea47SBrian Somers return 0; 43425092092SBrian Somers } else if (!strcasecmp(arg->argv[arg->argn], "slotcomp")) { 43525092092SBrian Somers if (!strcasecmp(arg->argv[arg->argn+1], "on")) 4361342caedSBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 1; 43725092092SBrian Somers else if (!strcasecmp(arg->argv[arg->argn+1], "off")) 4381342caedSBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 0; 439d1a3ea47SBrian Somers else 440d1a3ea47SBrian Somers return 2; 441d1a3ea47SBrian Somers return 0; 442d1a3ea47SBrian Somers } 443d1a3ea47SBrian Somers return -1; 444d1a3ea47SBrian Somers } 445d1a3ea47SBrian Somers 4461ae349f5Scvs2svn void 4476d666775SBrian Somers ipcp_Init(struct ipcp *ipcp, struct bundle *bundle, struct link *l, 4486d666775SBrian Somers const struct fsm_parent *parent) 449d1a3ea47SBrian Somers { 450503a7782SBrian Somers struct hostent *hp; 45130949fd4SBrian Somers struct in_addr host; 45226e6a622SBrian Somers char name[MAXHOSTNAMELEN]; 453182c898aSBrian Somers static const char * const timer_names[] = 4543b0f8d2eSBrian Somers {"IPCP restart", "IPCP openmode", "IPCP stopped"}; 45529e275ceSBrian Somers 456479508cfSBrian Somers fsm_Init(&ipcp->fsm, "IPCP", PROTO_IPCP, 1, IPCP_MAXCODE, LogIPCP, 4573b0f8d2eSBrian Somers bundle, l, parent, &ipcp_Callbacks, timer_names); 458503a7782SBrian Somers 4591342caedSBrian Somers ipcp->cfg.vj.slots = DEF_VJ_STATES; 4601342caedSBrian Somers ipcp->cfg.vj.slotcomp = 1; 461503a7782SBrian Somers memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range); 46230949fd4SBrian Somers 46330949fd4SBrian Somers host.s_addr = htonl(INADDR_LOOPBACK); 46430949fd4SBrian Somers ipcp->cfg.netmask.s_addr = INADDR_ANY; 465503a7782SBrian Somers if (gethostname(name, sizeof name) == 0) { 466503a7782SBrian Somers hp = gethostbyname(name); 46730949fd4SBrian Somers if (hp && hp->h_addrtype == AF_INET && hp->h_length == sizeof host.s_addr) 46830949fd4SBrian Somers memcpy(&host.s_addr, hp->h_addr, sizeof host.s_addr); 469503a7782SBrian Somers } 47030949fd4SBrian Somers ncprange_setip4(&ipcp->cfg.my_range, host, ipcp->cfg.netmask); 47130949fd4SBrian Somers ncprange_setip4(&ipcp->cfg.peer_range, ipcp->cfg.netmask, ipcp->cfg.netmask); 47230949fd4SBrian Somers 473503a7782SBrian Somers iplist_setsrc(&ipcp->cfg.peer_list, ""); 474503a7782SBrian Somers ipcp->cfg.HaveTriggerAddress = 0; 475503a7782SBrian Somers 476d568d6c4SBrian Somers ipcp->cfg.ns.dns[0].s_addr = INADDR_NONE; 477d568d6c4SBrian Somers ipcp->cfg.ns.dns[1].s_addr = INADDR_NONE; 4783edeb0c6SBrian Somers ipcp->cfg.ns.dns_neg = 0; 4793edeb0c6SBrian Somers ipcp->cfg.ns.nbns[0].s_addr = INADDR_ANY; 4803edeb0c6SBrian Somers ipcp->cfg.ns.nbns[1].s_addr = INADDR_ANY; 481cd9647a1SBrian Somers 482479508cfSBrian Somers ipcp->cfg.fsm.timeout = DEF_FSMRETRY; 483479508cfSBrian Somers ipcp->cfg.fsm.maxreq = DEF_FSMTRIES; 484479508cfSBrian Somers ipcp->cfg.fsm.maxtrm = DEF_FSMTRIES; 4851342caedSBrian Somers ipcp->cfg.vj.neg = NEG_ENABLED|NEG_ACCEPTED; 486503a7782SBrian Somers 487eaa4df37SBrian Somers memset(&ipcp->vj, '\0', sizeof ipcp->vj); 488eaa4df37SBrian Somers 489d568d6c4SBrian Somers ipcp->ns.resolv = NULL; 490d568d6c4SBrian Somers ipcp->ns.resolv_nons = NULL; 491d568d6c4SBrian Somers ipcp->ns.writable = 1; 492d568d6c4SBrian Somers ipcp_LoadDNS(ipcp); 493d568d6c4SBrian Somers 494ab2de065SBrian Somers throughput_init(&ipcp->throughput, SAMPLE_PERIOD); 4955a72b6edSBrian Somers memset(ipcp->Queue, '\0', sizeof ipcp->Queue); 496972a1bcfSBrian Somers ipcp_Setup(ipcp, INADDR_NONE); 497d1a3ea47SBrian Somers } 498d1a3ea47SBrian Somers 499af57ed9fSAtsushi Murai void 500442f8495SBrian Somers ipcp_Destroy(struct ipcp *ipcp) 501442f8495SBrian Somers { 50230949fd4SBrian Somers throughput_destroy(&ipcp->throughput); 50330949fd4SBrian Somers 504d568d6c4SBrian Somers if (ipcp->ns.resolv != NULL) { 505d568d6c4SBrian Somers free(ipcp->ns.resolv); 506d568d6c4SBrian Somers ipcp->ns.resolv = NULL; 507d568d6c4SBrian Somers } 508d568d6c4SBrian Somers if (ipcp->ns.resolv_nons != NULL) { 509d568d6c4SBrian Somers free(ipcp->ns.resolv_nons); 510d568d6c4SBrian Somers ipcp->ns.resolv_nons = NULL; 511d568d6c4SBrian Somers } 512442f8495SBrian Somers } 513442f8495SBrian Somers 514442f8495SBrian Somers void 515ce828a6eSBrian Somers ipcp_SetLink(struct ipcp *ipcp, struct link *l) 516af57ed9fSAtsushi Murai { 517ce828a6eSBrian Somers ipcp->fsm.link = l; 518af57ed9fSAtsushi Murai } 519549d663dSAtsushi Murai 520ce828a6eSBrian Somers void 521972a1bcfSBrian Somers ipcp_Setup(struct ipcp *ipcp, u_int32_t mask) 522503a7782SBrian Somers { 5238fa6ebe4SBrian Somers struct iface *iface = ipcp->fsm.bundle->iface; 52430949fd4SBrian Somers struct ncpaddr ipaddr; 52530949fd4SBrian Somers struct in_addr peer; 526057f1760SBrian Somers int pos; 527057f1760SBrian Somers unsigned n; 528503a7782SBrian Somers 529503a7782SBrian Somers ipcp->fsm.open_mode = 0; 530972a1bcfSBrian Somers ipcp->ifmask.s_addr = mask == INADDR_NONE ? ipcp->cfg.netmask.s_addr : mask; 531503a7782SBrian Somers 532503a7782SBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 5338fa6ebe4SBrian Somers /* Try to give the peer a previously configured IP address */ 53430949fd4SBrian Somers for (n = 0; n < iface->addrs; n++) { 53530949fd4SBrian Somers if (!ncpaddr_getip4(&iface->addr[n].peer, &peer)) 53630949fd4SBrian Somers continue; 53730949fd4SBrian Somers if ((pos = iplist_ip2pos(&ipcp->cfg.peer_list, peer)) != -1) { 53830949fd4SBrian Somers ncpaddr_setip4(&ipaddr, iplist_setcurpos(&ipcp->cfg.peer_list, pos)); 5398fa6ebe4SBrian Somers break; 5408fa6ebe4SBrian Somers } 5418fa6ebe4SBrian Somers } 54230949fd4SBrian Somers if (n == iface->addrs) 5438fa6ebe4SBrian Somers /* Ok, so none of 'em fit.... pick a random one */ 54430949fd4SBrian Somers ncpaddr_setip4(&ipaddr, iplist_setrandpos(&ipcp->cfg.peer_list)); 5458fa6ebe4SBrian Somers 54630949fd4SBrian Somers ncprange_sethost(&ipcp->cfg.peer_range, &ipaddr); 547503a7782SBrian Somers } 548503a7782SBrian Somers 549503a7782SBrian Somers ipcp->heis1172 = 0; 5505e3b2d68SBrian Somers ipcp->peer_req = 0; 55130949fd4SBrian Somers ncprange_getip4addr(&ipcp->cfg.peer_range, &ipcp->peer_ip); 552503a7782SBrian Somers ipcp->peer_compproto = 0; 5531ae349f5Scvs2svn 5548390b576SBrian Somers if (ipcp->cfg.HaveTriggerAddress) { 555549d663dSAtsushi Murai /* 5565b4c5b00SBrian Somers * Some implementations of PPP require that we send a 5575b4c5b00SBrian Somers * *special* value as our address, even though the rfc specifies 5585b4c5b00SBrian Somers * full negotiation (e.g. "0.0.0.0" or Not "0.0.0.0"). 559549d663dSAtsushi Murai */ 560503a7782SBrian Somers ipcp->my_ip = ipcp->cfg.TriggerAddress; 561dd7e2610SBrian Somers log_Printf(LogIPCP, "Using trigger address %s\n", 562503a7782SBrian Somers inet_ntoa(ipcp->cfg.TriggerAddress)); 5638fa6ebe4SBrian Somers } else { 5648390b576SBrian Somers /* 5658fa6ebe4SBrian Somers * Otherwise, if we've used an IP number before and it's still within 5668fa6ebe4SBrian Somers * the network specified on the ``set ifaddr'' line, we really 5678fa6ebe4SBrian Somers * want to keep that IP number so that we can keep any existing 56830949fd4SBrian Somers * connections that are bound to that IP. 5698390b576SBrian Somers */ 57030949fd4SBrian Somers for (n = 0; n < iface->addrs; n++) { 57130949fd4SBrian Somers ncprange_getaddr(&iface->addr[n].ifa, &ipaddr); 57230949fd4SBrian Somers if (ncprange_contains(&ipcp->cfg.my_range, &ipaddr)) { 57330949fd4SBrian Somers ncpaddr_getip4(&ipaddr, &ipcp->my_ip); 5748fa6ebe4SBrian Somers break; 5758fa6ebe4SBrian Somers } 57630949fd4SBrian Somers } 57730949fd4SBrian Somers if (n == iface->addrs) 57830949fd4SBrian Somers ncprange_getip4addr(&ipcp->cfg.my_range, &ipcp->my_ip); 5798fa6ebe4SBrian Somers } 58029e275ceSBrian Somers 581972a1bcfSBrian Somers if (IsEnabled(ipcp->cfg.vj.neg) 582972a1bcfSBrian Somers #ifndef NORADIUS 583972a1bcfSBrian Somers || (ipcp->fsm.bundle->radius.valid && ipcp->fsm.bundle->radius.vj) 584972a1bcfSBrian Somers #endif 585972a1bcfSBrian Somers ) 586503a7782SBrian Somers ipcp->my_compproto = (PROTO_VJCOMP << 16) + 5871342caedSBrian Somers ((ipcp->cfg.vj.slots - 1) << 8) + 5881342caedSBrian Somers ipcp->cfg.vj.slotcomp; 5891ae349f5Scvs2svn else 590503a7782SBrian Somers ipcp->my_compproto = 0; 5911342caedSBrian Somers sl_compress_init(&ipcp->vj.cslc, ipcp->cfg.vj.slots - 1); 59229e275ceSBrian Somers 593503a7782SBrian Somers ipcp->peer_reject = 0; 594503a7782SBrian Somers ipcp->my_reject = 0; 595d568d6c4SBrian Somers 59630949fd4SBrian Somers /* Copy startup values into ipcp->ns.dns */ 597d568d6c4SBrian Somers if (ipcp->cfg.ns.dns[0].s_addr != INADDR_NONE) 59830949fd4SBrian Somers memcpy(ipcp->ns.dns, ipcp->cfg.ns.dns, sizeof ipcp->ns.dns); 5991ae349f5Scvs2svn } 6001ae349f5Scvs2svn 601455aabc3SBrian Somers static int 60230949fd4SBrian Somers numaddresses(struct in_addr mask) 6033afe5ccbSBrian Somers { 60430949fd4SBrian Somers u_int32_t bit, haddr; 60530949fd4SBrian Somers int n; 6063afe5ccbSBrian Somers 60730949fd4SBrian Somers haddr = ntohl(mask.s_addr); 60830949fd4SBrian Somers bit = 1; 60930949fd4SBrian Somers n = 1; 61030949fd4SBrian Somers 61130949fd4SBrian Somers do { 61230949fd4SBrian Somers if (!(haddr & bit)) 61330949fd4SBrian Somers n <<= 1; 61430949fd4SBrian Somers } while (bit <<= 1); 61530949fd4SBrian Somers 61630949fd4SBrian Somers return n; 6173afe5ccbSBrian Somers } 6183afe5ccbSBrian Somers 61930949fd4SBrian Somers static int 62030949fd4SBrian Somers ipcp_proxyarp(struct ipcp *ipcp, 621057f1760SBrian Somers int (*proxyfun)(struct bundle *, struct in_addr), 62230949fd4SBrian Somers const struct iface_addr *addr) 62330949fd4SBrian Somers { 62430949fd4SBrian Somers struct bundle *bundle = ipcp->fsm.bundle; 62530949fd4SBrian Somers struct in_addr peer, mask, ip; 626057f1760SBrian Somers int n, ret; 62730949fd4SBrian Somers 62830949fd4SBrian Somers if (!ncpaddr_getip4(&addr->peer, &peer)) { 62930949fd4SBrian Somers log_Printf(LogERROR, "Oops, ipcp_proxyarp() called with unexpected addr\n"); 6303afe5ccbSBrian Somers return 0; 6313afe5ccbSBrian Somers } 6323afe5ccbSBrian Somers 63330949fd4SBrian Somers ret = 0; 63430949fd4SBrian Somers 63530949fd4SBrian Somers if (Enabled(bundle, OPT_PROXYALL)) { 63630949fd4SBrian Somers ncprange_getip4mask(&addr->ifa, &mask); 63730949fd4SBrian Somers if ((n = numaddresses(mask)) > 256) { 63830949fd4SBrian Somers log_Printf(LogWARN, "%s: Too many addresses for proxyall\n", 63930949fd4SBrian Somers ncprange_ntoa(&addr->ifa)); 64030949fd4SBrian Somers return 0; 64130949fd4SBrian Somers } 64230949fd4SBrian Somers ip.s_addr = peer.s_addr & mask.s_addr; 64330949fd4SBrian Somers if (n >= 4) { 64430949fd4SBrian Somers ip.s_addr = htonl(ntohl(ip.s_addr) + 1); 64530949fd4SBrian Somers n -= 2; 64630949fd4SBrian Somers } 64730949fd4SBrian Somers while (n) { 64830949fd4SBrian Somers if (!((ip.s_addr ^ peer.s_addr) & mask.s_addr)) { 649057f1760SBrian Somers if (!(ret = (*proxyfun)(bundle, ip))) 65030949fd4SBrian Somers break; 65130949fd4SBrian Somers n--; 65230949fd4SBrian Somers } 65330949fd4SBrian Somers ip.s_addr = htonl(ntohl(ip.s_addr) + 1); 65430949fd4SBrian Somers } 65530949fd4SBrian Somers ret = !n; 65630949fd4SBrian Somers } else if (Enabled(bundle, OPT_PROXY)) 657057f1760SBrian Somers ret = (*proxyfun)(bundle, peer); 65830949fd4SBrian Somers 65930949fd4SBrian Somers return ret; 66030949fd4SBrian Somers } 66130949fd4SBrian Somers 6623afe5ccbSBrian Somers static int 66330949fd4SBrian Somers ipcp_SetIPaddress(struct ipcp *ipcp, struct in_addr myaddr, 66430949fd4SBrian Somers struct in_addr hisaddr) 665455aabc3SBrian Somers { 66630949fd4SBrian Somers struct bundle *bundle = ipcp->fsm.bundle; 66730949fd4SBrian Somers struct ncpaddr myncpaddr, hisncpaddr; 6685ae08329SBrian Somers struct ncprange myrange; 66930949fd4SBrian Somers struct in_addr mask; 6705ae08329SBrian Somers struct sockaddr_storage ssdst, ssgw, ssmask; 6715ae08329SBrian Somers struct sockaddr *sadst, *sagw, *samask; 6725ae08329SBrian Somers 6735ae08329SBrian Somers sadst = (struct sockaddr *)&ssdst; 6745ae08329SBrian Somers sagw = (struct sockaddr *)&ssgw; 6755ae08329SBrian Somers samask = (struct sockaddr *)&ssmask; 67630949fd4SBrian Somers 67730949fd4SBrian Somers ncpaddr_setip4(&hisncpaddr, hisaddr); 67830949fd4SBrian Somers ncpaddr_setip4(&myncpaddr, myaddr); 67930949fd4SBrian Somers ncprange_sethost(&myrange, &myncpaddr); 680455aabc3SBrian Somers 681bc76350eSBrian Somers mask = addr2mask(myaddr); 682455aabc3SBrian Somers 68330949fd4SBrian Somers if (ipcp->ifmask.s_addr != INADDR_ANY && 68430949fd4SBrian Somers (ipcp->ifmask.s_addr & mask.s_addr) == mask.s_addr) 68530949fd4SBrian Somers ncprange_setip4mask(&myrange, ipcp->ifmask); 686455aabc3SBrian Somers 68730949fd4SBrian Somers if (!iface_Add(bundle->iface, &bundle->ncp, &myrange, &hisncpaddr, 68830949fd4SBrian Somers IFACE_ADD_FIRST|IFACE_FORCE_ADD|IFACE_SYSTEM)) 68930949fd4SBrian Somers return 0; 690455aabc3SBrian Somers 69130949fd4SBrian Somers if (!Enabled(bundle, OPT_IFACEALIAS)) 69230949fd4SBrian Somers iface_Clear(bundle->iface, &bundle->ncp, AF_INET, 69330949fd4SBrian Somers IFACE_CLEAR_ALIASES|IFACE_SYSTEM); 694455aabc3SBrian Somers 69530949fd4SBrian Somers if (bundle->ncp.cfg.sendpipe > 0 || bundle->ncp.cfg.recvpipe > 0) { 6965ae08329SBrian Somers ncprange_getsa(&myrange, &ssgw, &ssmask); 6975ae08329SBrian Somers ncpaddr_getsa(&hisncpaddr, &ssdst); 6980e81959dSBjoern A. Zeeb rt_Update(bundle, sadst, sagw, samask, NULL, NULL); 69930949fd4SBrian Somers } 7003afe5ccbSBrian Somers 701610b185fSBrian Somers if (Enabled(bundle, OPT_SROUTES)) 70230949fd4SBrian Somers route_Change(bundle, bundle->ncp.route, &myncpaddr, &hisncpaddr); 703610b185fSBrian Somers 704972a1bcfSBrian Somers #ifndef NORADIUS 705972a1bcfSBrian Somers if (bundle->radius.valid) 70630949fd4SBrian Somers route_Change(bundle, bundle->radius.routes, &myncpaddr, &hisncpaddr); 707972a1bcfSBrian Somers #endif 708972a1bcfSBrian Somers 70930949fd4SBrian Somers return 1; /* Ok */ 710455aabc3SBrian Somers } 711455aabc3SBrian Somers 712455aabc3SBrian Somers static struct in_addr 7138fa6ebe4SBrian Somers ChooseHisAddr(struct bundle *bundle, struct in_addr gw) 714455aabc3SBrian Somers { 715455aabc3SBrian Somers struct in_addr try; 7163a2e4f62SBrian Somers u_long f; 717455aabc3SBrian Somers 7185828db6dSBrian Somers for (f = 0; f < bundle->ncp.ipcp.cfg.peer_list.nItems; f++) { 7195828db6dSBrian Somers try = iplist_next(&bundle->ncp.ipcp.cfg.peer_list); 7203a2e4f62SBrian Somers log_Printf(LogDEBUG, "ChooseHisAddr: Check item %ld (%s)\n", 721455aabc3SBrian Somers f, inet_ntoa(try)); 72230949fd4SBrian Somers if (ipcp_SetIPaddress(&bundle->ncp.ipcp, gw, try)) { 723dd7e2610SBrian Somers log_Printf(LogIPCP, "Selected IP address %s\n", inet_ntoa(try)); 724455aabc3SBrian Somers break; 725455aabc3SBrian Somers } 726455aabc3SBrian Somers } 727455aabc3SBrian Somers 7285828db6dSBrian Somers if (f == bundle->ncp.ipcp.cfg.peer_list.nItems) { 729dd7e2610SBrian Somers log_Printf(LogDEBUG, "ChooseHisAddr: All addresses in use !\n"); 730455aabc3SBrian Somers try.s_addr = INADDR_ANY; 731455aabc3SBrian Somers } 732455aabc3SBrian Somers 733455aabc3SBrian Somers return try; 734af57ed9fSAtsushi Murai } 735af57ed9fSAtsushi Murai 736af57ed9fSAtsushi Murai static void 737479508cfSBrian Somers IpcpInitRestartCounter(struct fsm *fp, int what) 738af57ed9fSAtsushi Murai { 7397308ec68SBrian Somers /* Set fsm timer load */ 740cd9647a1SBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 741cd9647a1SBrian Somers 742479508cfSBrian Somers fp->FsmTimer.load = ipcp->cfg.fsm.timeout * SECTICKS; 743479508cfSBrian Somers switch (what) { 744479508cfSBrian Somers case FSM_REQ_TIMER: 745479508cfSBrian Somers fp->restart = ipcp->cfg.fsm.maxreq; 746479508cfSBrian Somers break; 747479508cfSBrian Somers case FSM_TRM_TIMER: 748479508cfSBrian Somers fp->restart = ipcp->cfg.fsm.maxtrm; 749479508cfSBrian Somers break; 750479508cfSBrian Somers default: 751479508cfSBrian Somers fp->restart = 1; 752479508cfSBrian Somers break; 753479508cfSBrian Somers } 754af57ed9fSAtsushi Murai } 755af57ed9fSAtsushi Murai 756af57ed9fSAtsushi Murai static void 757944f7098SBrian Somers IpcpSendConfigReq(struct fsm *fp) 758af57ed9fSAtsushi Murai { 7597308ec68SBrian Somers /* Send config REQ please */ 7608c07a7b2SBrian Somers struct physical *p = link2physical(fp->link); 761aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 762eb1ecbb2SBrian Somers u_char buff[MAX_FSM_OPT_LEN]; 763ff360cc9SBrian Somers struct fsm_opt *o; 764af57ed9fSAtsushi Murai 765ff360cc9SBrian Somers o = (struct fsm_opt *)buff; 76630c2f2ffSBrian Somers 767dd7e2610SBrian Somers if ((p && !physical_IsSync(p)) || !REJECTED(ipcp, TY_IPADDR)) { 7689e8ec64bSBrian Somers memcpy(o->data, &ipcp->my_ip.s_addr, 4); 769ff360cc9SBrian Somers INC_FSM_OPT(TY_IPADDR, 6, o); 7700053cc58SBrian Somers } 7710053cc58SBrian Somers 772e43ebac1SBrian Somers if (ipcp->my_compproto && !REJECTED(ipcp, TY_COMPPROTO)) { 77383d1af55SBrian Somers if (ipcp->heis1172) { 7749e8ec64bSBrian Somers u_int16_t proto = PROTO_VJCOMP; 7759e8ec64bSBrian Somers 7769e8ec64bSBrian Somers ua_htons(&proto, o->data); 777ff360cc9SBrian Somers INC_FSM_OPT(TY_COMPPROTO, 4, o); 7780053cc58SBrian Somers } else { 7797686a200SBrian Somers struct compreq req; 7807686a200SBrian Somers 7817686a200SBrian Somers req.proto = htons(ipcp->my_compproto >> 16); 7827686a200SBrian Somers req.slots = (ipcp->my_compproto >> 8) & 255; 7837686a200SBrian Somers req.compcid = ipcp->my_compproto & 1; 7847686a200SBrian Somers memcpy(o->data, &req, 4); 785ff360cc9SBrian Somers INC_FSM_OPT(TY_COMPPROTO, 6, o); 7860053cc58SBrian Somers } 787af57ed9fSAtsushi Murai } 7882267893fSBrian Somers 78930949fd4SBrian Somers if (IsEnabled(ipcp->cfg.ns.dns_neg)) { 79030949fd4SBrian Somers if (!REJECTED(ipcp, TY_PRIMARY_DNS - TY_ADJUST_NS)) { 79130949fd4SBrian Somers memcpy(o->data, &ipcp->ns.dns[0].s_addr, 4); 792ff360cc9SBrian Somers INC_FSM_OPT(TY_PRIMARY_DNS, 6, o); 7937d39b1e3SBrian Somers } 7947d39b1e3SBrian Somers 79530949fd4SBrian Somers if (!REJECTED(ipcp, TY_SECONDARY_DNS - TY_ADJUST_NS)) { 79630949fd4SBrian Somers memcpy(o->data, &ipcp->ns.dns[1].s_addr, 4); 797ff360cc9SBrian Somers INC_FSM_OPT(TY_SECONDARY_DNS, 6, o); 7983edeb0c6SBrian Somers } 79930949fd4SBrian Somers } 8003edeb0c6SBrian Somers 801411675baSBrian Somers fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff, 802411675baSBrian Somers MB_IPCPOUT); 803af57ed9fSAtsushi Murai } 804af57ed9fSAtsushi Murai 805af57ed9fSAtsushi Murai static void 806057f1760SBrian Somers IpcpSentTerminateReq(struct fsm *fp __unused) 807af57ed9fSAtsushi Murai { 8087308ec68SBrian Somers /* Term REQ just sent by FSM */ 809af57ed9fSAtsushi Murai } 810af57ed9fSAtsushi Murai 811af57ed9fSAtsushi Murai static void 8122267893fSBrian Somers IpcpSendTerminateAck(struct fsm *fp, u_char id) 813af57ed9fSAtsushi Murai { 8147308ec68SBrian Somers /* Send Term ACK please */ 815411675baSBrian Somers fsm_Output(fp, CODE_TERMACK, id, NULL, 0, MB_IPCPOUT); 816af57ed9fSAtsushi Murai } 817af57ed9fSAtsushi Murai 818af57ed9fSAtsushi Murai static void 819944f7098SBrian Somers IpcpLayerStart(struct fsm *fp) 820af57ed9fSAtsushi Murai { 8217308ec68SBrian Somers /* We're about to start up ! */ 822897f9429SBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 823897f9429SBrian Somers 8243a2e4f62SBrian Somers log_Printf(LogIPCP, "%s: LayerStart.\n", fp->link->name); 825897f9429SBrian Somers throughput_start(&ipcp->throughput, "IPCP throughput", 826897f9429SBrian Somers Enabled(fp->bundle, OPT_THROUGHPUT)); 827479508cfSBrian Somers fp->more.reqs = fp->more.naks = fp->more.rejs = ipcp->cfg.fsm.maxreq * 3; 8285e3b2d68SBrian Somers ipcp->peer_req = 0; 829af57ed9fSAtsushi Murai } 830af57ed9fSAtsushi Murai 831af57ed9fSAtsushi Murai static void 832944f7098SBrian Somers IpcpLayerFinish(struct fsm *fp) 833af57ed9fSAtsushi Murai { 8347308ec68SBrian Somers /* We're now down */ 835897f9429SBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 836897f9429SBrian Somers 8373a2e4f62SBrian Somers log_Printf(LogIPCP, "%s: LayerFinish.\n", fp->link->name); 838897f9429SBrian Somers throughput_stop(&ipcp->throughput); 839897f9429SBrian Somers throughput_log(&ipcp->throughput, LogIPCP, NULL); 8401ae349f5Scvs2svn } 8411ae349f5Scvs2svn 84230949fd4SBrian Somers /* 84330949fd4SBrian Somers * Called from iface_Add() via ncp_IfaceAddrAdded() 84430949fd4SBrian Somers */ 84568a0f0ccSBrian Somers void 84630949fd4SBrian Somers ipcp_IfaceAddrAdded(struct ipcp *ipcp, const struct iface_addr *addr) 84768a0f0ccSBrian Somers { 84830949fd4SBrian Somers struct bundle *bundle = ipcp->fsm.bundle; 84968a0f0ccSBrian Somers 85030949fd4SBrian Somers if (Enabled(bundle, OPT_PROXY) || Enabled(bundle, OPT_PROXYALL)) 85130949fd4SBrian Somers ipcp_proxyarp(ipcp, arp_SetProxy, addr); 85268a0f0ccSBrian Somers } 85368a0f0ccSBrian Somers 85430949fd4SBrian Somers /* 85530949fd4SBrian Somers * Called from iface_Clear() and iface_Delete() via ncp_IfaceAddrDeleted() 85630949fd4SBrian Somers */ 85730949fd4SBrian Somers void 85830949fd4SBrian Somers ipcp_IfaceAddrDeleted(struct ipcp *ipcp, const struct iface_addr *addr) 85930949fd4SBrian Somers { 86030949fd4SBrian Somers struct bundle *bundle = ipcp->fsm.bundle; 86130949fd4SBrian Somers 86230949fd4SBrian Somers if (Enabled(bundle, OPT_PROXY) || Enabled(bundle, OPT_PROXYALL)) 86330949fd4SBrian Somers ipcp_proxyarp(ipcp, arp_ClearProxy, addr); 864af57ed9fSAtsushi Murai } 865af57ed9fSAtsushi Murai 866af57ed9fSAtsushi Murai static void 867944f7098SBrian Somers IpcpLayerDown(struct fsm *fp) 868af57ed9fSAtsushi Murai { 8697308ec68SBrian Somers /* About to come down */ 870aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 87130949fd4SBrian Somers static int recursing; 87230949fd4SBrian Somers char addr[16]; 873455aabc3SBrian Somers 874aa857470SBrian Somers if (!recursing++) { 87530949fd4SBrian Somers snprintf(addr, sizeof addr, "%s", inet_ntoa(ipcp->my_ip)); 87630949fd4SBrian Somers log_Printf(LogIPCP, "%s: LayerDown: %s\n", fp->link->name, addr); 877455aabc3SBrian Somers 878794c9bbcSBrian Somers #ifndef NORADIUS 87988044778SBrian Somers radius_Flush(&fp->bundle->radius); 880794c9bbcSBrian Somers radius_Account(&fp->bundle->radius, &fp->bundle->radacct, 881cf7c10d0SHajimu UMEMOTO fp->bundle->links, RAD_STOP, &ipcp->throughput); 882635ad5f0SBrian Somers 883635ad5f0SBrian Somers if (fp->bundle->radius.cfg.file && fp->bundle->radius.filterid) 884635ad5f0SBrian Somers system_Select(fp->bundle, fp->bundle->radius.filterid, LINKDOWNFILE, 885635ad5f0SBrian Somers NULL, NULL); 886e715b13bSBrian Somers radius_StopTimer(&fp->bundle->radius); 887794c9bbcSBrian Somers #endif 888794c9bbcSBrian Somers 889455aabc3SBrian Somers /* 890455aabc3SBrian Somers * XXX this stuff should really live in the FSM. Our config should 891455aabc3SBrian Somers * associate executable sections in files with events. 892455aabc3SBrian Somers */ 89330949fd4SBrian Somers if (system_Select(fp->bundle, addr, LINKDOWNFILE, NULL, NULL) < 0) { 89449052c95SBrian Somers if (bundle_GetLabel(fp->bundle)) { 895dd7e2610SBrian Somers if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle), 89630291ffbSBrian Somers LINKDOWNFILE, NULL, NULL) < 0) 89730291ffbSBrian Somers system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL); 898455aabc3SBrian Somers } else 89930291ffbSBrian Somers system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL); 900af57ed9fSAtsushi Murai } 901af57ed9fSAtsushi Murai 902972a1bcfSBrian Somers ipcp_Setup(ipcp, INADDR_NONE); 9031ae349f5Scvs2svn } 904aa857470SBrian Somers recursing--; 905aa857470SBrian Somers } 9061ae349f5Scvs2svn 907dd0645c5SBrian Somers int 908dd0645c5SBrian Somers ipcp_InterfaceUp(struct ipcp *ipcp) 909dd0645c5SBrian Somers { 91030949fd4SBrian Somers if (!ipcp_SetIPaddress(ipcp, ipcp->my_ip, ipcp->peer_ip)) { 911a33b2ef7SBrian Somers log_Printf(LogERROR, "ipcp_InterfaceUp: unable to set ip address\n"); 912dd0645c5SBrian Somers return 0; 913dd0645c5SBrian Somers } 914dd0645c5SBrian Somers 915448374baSBrian Somers if (!iface_SetFlags(ipcp->fsm.bundle->iface->name, IFF_UP)) { 916448374baSBrian Somers log_Printf(LogERROR, "ipcp_InterfaceUp: Can't set the IFF_UP flag on %s\n", 917448374baSBrian Somers ipcp->fsm.bundle->iface->name); 918448374baSBrian Somers return 0; 919448374baSBrian Somers } 920448374baSBrian Somers 92167b072f7SBrian Somers #ifndef NONAT 92267b072f7SBrian Somers if (ipcp->fsm.bundle->NatEnabled) 923a5625ae7SPaolo Pisati LibAliasSetAddress(la, ipcp->my_ip); 924dd0645c5SBrian Somers #endif 925dd0645c5SBrian Somers 926dd0645c5SBrian Somers return 1; 927dd0645c5SBrian Somers } 928dd0645c5SBrian Somers 9296f384573SBrian Somers static int 930944f7098SBrian Somers IpcpLayerUp(struct fsm *fp) 931af57ed9fSAtsushi Murai { 9327308ec68SBrian Somers /* We're now up */ 933aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 9348fa6ebe4SBrian Somers char tbuff[16]; 935af57ed9fSAtsushi Murai 9363a2e4f62SBrian Somers log_Printf(LogIPCP, "%s: LayerUp.\n", fp->link->name); 9378fa6ebe4SBrian Somers snprintf(tbuff, sizeof tbuff, "%s", inet_ntoa(ipcp->my_ip)); 9388fa6ebe4SBrian Somers log_Printf(LogIPCP, "myaddr %s hisaddr = %s\n", 9398fa6ebe4SBrian Somers tbuff, inet_ntoa(ipcp->peer_ip)); 94003604f35SBrian Somers 941503a7782SBrian Somers if (ipcp->peer_compproto >> 16 == PROTO_VJCOMP) 942eaa4df37SBrian Somers sl_compress_init(&ipcp->vj.cslc, (ipcp->peer_compproto >> 8) & 255); 94303604f35SBrian Somers 944dd0645c5SBrian Somers if (!ipcp_InterfaceUp(ipcp)) 9456f384573SBrian Somers return 0; 946455aabc3SBrian Somers 947794c9bbcSBrian Somers #ifndef NORADIUS 948cf7c10d0SHajimu UMEMOTO radius_Account_Set_Ip(&fp->bundle->radacct, &ipcp->peer_ip, &ipcp->ifmask); 949794c9bbcSBrian Somers radius_Account(&fp->bundle->radius, &fp->bundle->radacct, fp->bundle->links, 950cf7c10d0SHajimu UMEMOTO RAD_START, &ipcp->throughput); 951635ad5f0SBrian Somers 952635ad5f0SBrian Somers if (fp->bundle->radius.cfg.file && fp->bundle->radius.filterid) 953635ad5f0SBrian Somers system_Select(fp->bundle, fp->bundle->radius.filterid, LINKUPFILE, 954635ad5f0SBrian Somers NULL, NULL); 955e715b13bSBrian Somers radius_StartTimer(fp->bundle); 956794c9bbcSBrian Somers #endif 957794c9bbcSBrian Somers 958455aabc3SBrian Somers /* 959455aabc3SBrian Somers * XXX this stuff should really live in the FSM. Our config should 960455aabc3SBrian Somers * associate executable sections in files with events. 961455aabc3SBrian Somers */ 9628fa6ebe4SBrian Somers if (system_Select(fp->bundle, tbuff, LINKUPFILE, NULL, NULL) < 0) { 96349052c95SBrian Somers if (bundle_GetLabel(fp->bundle)) { 964dd7e2610SBrian Somers if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle), 96530291ffbSBrian Somers LINKUPFILE, NULL, NULL) < 0) 96630291ffbSBrian Somers system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL); 967455aabc3SBrian Somers } else 96830291ffbSBrian Somers system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL); 969af57ed9fSAtsushi Murai } 970af57ed9fSAtsushi Murai 971479508cfSBrian Somers fp->more.reqs = fp->more.naks = fp->more.rejs = ipcp->cfg.fsm.maxreq * 3; 9720f2f3eb3SBrian Somers log_DisplayPrompts(); 973479508cfSBrian Somers 9746f384573SBrian Somers return 1; 975af57ed9fSAtsushi Murai } 976af57ed9fSAtsushi Murai 977af57ed9fSAtsushi Murai static void 9785f73635bSBrian Somers ipcp_ValidateReq(struct ipcp *ipcp, struct in_addr ip, struct fsm_decode *dec) 9795f73635bSBrian Somers { 9805f73635bSBrian Somers struct bundle *bundle = ipcp->fsm.bundle; 9815f73635bSBrian Somers struct iface *iface = bundle->iface; 98230949fd4SBrian Somers struct in_addr myaddr, peer; 983057f1760SBrian Somers unsigned n; 9845f73635bSBrian Somers 9855f73635bSBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 98630949fd4SBrian Somers ncprange_getip4addr(&ipcp->cfg.my_range, &myaddr); 9875f73635bSBrian Somers if (ip.s_addr == INADDR_ANY || 9885f73635bSBrian Somers iplist_ip2pos(&ipcp->cfg.peer_list, ip) < 0 || 98930949fd4SBrian Somers !ipcp_SetIPaddress(ipcp, myaddr, ip)) { 9905f73635bSBrian Somers log_Printf(LogIPCP, "%s: Address invalid or already in use\n", 9915f73635bSBrian Somers inet_ntoa(ip)); 9925f73635bSBrian Somers /* 9935f73635bSBrian Somers * If we've already had a valid address configured for the peer, 9945f73635bSBrian Somers * try NAKing with that so that we don't have to upset things 9955f73635bSBrian Somers * too much. 9965f73635bSBrian Somers */ 99730949fd4SBrian Somers for (n = 0; n < iface->addrs; n++) { 99830949fd4SBrian Somers if (!ncpaddr_getip4(&iface->addr[n].peer, &peer)) 99930949fd4SBrian Somers continue; 100030949fd4SBrian Somers if (iplist_ip2pos(&ipcp->cfg.peer_list, peer) >= 0) { 100130949fd4SBrian Somers ipcp->peer_ip = peer; 10025f73635bSBrian Somers break; 10035f73635bSBrian Somers } 100430949fd4SBrian Somers } 10055f73635bSBrian Somers 100630949fd4SBrian Somers if (n == iface->addrs) { 10075f73635bSBrian Somers /* Just pick an IP number from our list */ 100830949fd4SBrian Somers ipcp->peer_ip = ChooseHisAddr(bundle, myaddr); 100930949fd4SBrian Somers } 10105f73635bSBrian Somers 10115f73635bSBrian Somers if (ipcp->peer_ip.s_addr == INADDR_ANY) { 10125f73635bSBrian Somers *dec->rejend++ = TY_IPADDR; 10135f73635bSBrian Somers *dec->rejend++ = 6; 10145f73635bSBrian Somers memcpy(dec->rejend, &ip.s_addr, 4); 10155f73635bSBrian Somers dec->rejend += 4; 10165f73635bSBrian Somers } else { 10175f73635bSBrian Somers *dec->nakend++ = TY_IPADDR; 10185f73635bSBrian Somers *dec->nakend++ = 6; 10195f73635bSBrian Somers memcpy(dec->nakend, &ipcp->peer_ip.s_addr, 4); 10205f73635bSBrian Somers dec->nakend += 4; 10215f73635bSBrian Somers } 10225f73635bSBrian Somers return; 10235f73635bSBrian Somers } 10243c34956aSBrian Somers } else if (ip.s_addr == INADDR_ANY || 10253c34956aSBrian Somers !ncprange_containsip4(&ipcp->cfg.peer_range, ip)) { 10265f73635bSBrian Somers /* 10275f73635bSBrian Somers * If the destination address is not acceptable, NAK with what we 10285f73635bSBrian Somers * want to use. 10295f73635bSBrian Somers */ 10305f73635bSBrian Somers *dec->nakend++ = TY_IPADDR; 10315f73635bSBrian Somers *dec->nakend++ = 6; 103230949fd4SBrian Somers for (n = 0; n < iface->addrs; n++) 103330949fd4SBrian Somers if (ncprange_contains(&ipcp->cfg.peer_range, &iface->addr[n].peer)) { 10345f73635bSBrian Somers /* We prefer the already-configured address */ 103530949fd4SBrian Somers ncpaddr_getip4addr(&iface->addr[n].peer, (u_int32_t *)dec->nakend); 10365f73635bSBrian Somers break; 10375f73635bSBrian Somers } 10385f73635bSBrian Somers 103930949fd4SBrian Somers if (n == iface->addrs) 10405f73635bSBrian Somers memcpy(dec->nakend, &ipcp->peer_ip.s_addr, 4); 10415f73635bSBrian Somers 10425f73635bSBrian Somers dec->nakend += 4; 10435f73635bSBrian Somers return; 10445f73635bSBrian Somers } 10455f73635bSBrian Somers 10465f73635bSBrian Somers ipcp->peer_ip = ip; 10475f73635bSBrian Somers *dec->ackend++ = TY_IPADDR; 10485f73635bSBrian Somers *dec->ackend++ = 6; 10495f73635bSBrian Somers memcpy(dec->ackend, &ip.s_addr, 4); 10505f73635bSBrian Somers dec->ackend += 4; 10515f73635bSBrian Somers } 10525f73635bSBrian Somers 10535f73635bSBrian Somers static void 1054ff360cc9SBrian Somers IpcpDecodeConfig(struct fsm *fp, u_char *cp, u_char *end, int mode_type, 105530c2f2ffSBrian Somers struct fsm_decode *dec) 1056af57ed9fSAtsushi Murai { 10577308ec68SBrian Somers /* Deal with incoming PROTO_IPCP */ 105830949fd4SBrian Somers struct ncpaddr ncpaddr; 1059aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 1060ff360cc9SBrian Somers int gotdnsnak; 1061fe3125a0SBrian Somers u_int32_t compproto; 1062eb1ecbb2SBrian Somers struct compreq pcomp; 1063d568d6c4SBrian Somers struct in_addr ipaddr, dstipaddr, have_ip; 106430c2f2ffSBrian Somers char tbuff[100], tbuff2[100]; 1065ff360cc9SBrian Somers struct fsm_opt *opt, nak; 1066af57ed9fSAtsushi Murai 10673edeb0c6SBrian Somers gotdnsnak = 0; 1068af57ed9fSAtsushi Murai 1069057f1760SBrian Somers while (end - cp >= (int)sizeof(opt->hdr)) { 1070ff360cc9SBrian Somers if ((opt = fsm_readopt(&cp)) == NULL) 1071d47dceb8SBrian Somers break; 1072d47dceb8SBrian Somers 1073ff360cc9SBrian Somers snprintf(tbuff, sizeof tbuff, " %s[%d]", protoname(opt->hdr.id), 1074ff360cc9SBrian Somers opt->hdr.len); 1075af57ed9fSAtsushi Murai 1076ff360cc9SBrian Somers switch (opt->hdr.id) { 1077af57ed9fSAtsushi Murai case TY_IPADDR: /* RFC1332 */ 1078ff360cc9SBrian Somers memcpy(&ipaddr.s_addr, opt->data, 4); 1079dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 1080af57ed9fSAtsushi Murai 10819780ef31SBrian Somers switch (mode_type) { 1082af57ed9fSAtsushi Murai case MODE_REQ: 10835e3b2d68SBrian Somers ipcp->peer_req = 1; 10845f73635bSBrian Somers ipcp_ValidateReq(ipcp, ipaddr, dec); 1085af57ed9fSAtsushi Murai break; 10868fa6ebe4SBrian Somers 1087af57ed9fSAtsushi Murai case MODE_NAK: 108830949fd4SBrian Somers if (ncprange_containsip4(&ipcp->cfg.my_range, ipaddr)) { 1089bcc332bdSBrian Somers /* Use address suggested by peer */ 109070ee81ffSBrian Somers snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s ", tbuff, 1091503a7782SBrian Somers inet_ntoa(ipcp->my_ip)); 1092dd7e2610SBrian Somers log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 1093503a7782SBrian Somers ipcp->my_ip = ipaddr; 109430949fd4SBrian Somers ncpaddr_setip4(&ncpaddr, ipcp->my_ip); 109530949fd4SBrian Somers bundle_AdjustFilters(fp->bundle, &ncpaddr, NULL); 1096bcc332bdSBrian Somers } else { 1097dd7e2610SBrian Somers log_Printf(log_IsKept(LogIPCP) ? LogIPCP : LogPHASE, 10988390b576SBrian Somers "%s: Unacceptable address!\n", inet_ntoa(ipaddr)); 1099dd7e2610SBrian Somers fsm_Close(&ipcp->fsm); 1100af57ed9fSAtsushi Murai } 1101af57ed9fSAtsushi Murai break; 11028fa6ebe4SBrian Somers 1103af57ed9fSAtsushi Murai case MODE_REJ: 1104ff360cc9SBrian Somers ipcp->peer_reject |= (1 << opt->hdr.id); 1105af57ed9fSAtsushi Murai break; 1106af57ed9fSAtsushi Murai } 1107af57ed9fSAtsushi Murai break; 11088fa6ebe4SBrian Somers 1109af57ed9fSAtsushi Murai case TY_COMPPROTO: 1110eb1ecbb2SBrian Somers memcpy(&pcomp, opt->data, sizeof pcomp); 1111eb1ecbb2SBrian Somers compproto = (ntohs(pcomp.proto) << 16) + ((int)pcomp.slots << 8) + 1112eb1ecbb2SBrian Somers pcomp.compcid; 1113dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto)); 1114af57ed9fSAtsushi Murai 11159780ef31SBrian Somers switch (mode_type) { 1116af57ed9fSAtsushi Murai case MODE_REQ: 1117ff360cc9SBrian Somers if (!IsAccepted(ipcp->cfg.vj.neg)) 1118ff360cc9SBrian Somers fsm_rej(dec, opt); 1119ff360cc9SBrian Somers else { 1120ff360cc9SBrian Somers switch (opt->hdr.len) { 1121af57ed9fSAtsushi Murai case 4: /* RFC1172 */ 1122eb1ecbb2SBrian Somers if (ntohs(pcomp.proto) == PROTO_VJCOMP) { 11237686a200SBrian Somers log_Printf(LogWARN, "Peer is speaking RFC1172 compression " 11247686a200SBrian Somers "protocol !\n"); 112583d1af55SBrian Somers ipcp->heis1172 = 1; 1126503a7782SBrian Somers ipcp->peer_compproto = compproto; 1127ff360cc9SBrian Somers fsm_ack(dec, opt); 1128af57ed9fSAtsushi Murai } else { 1129eb1ecbb2SBrian Somers pcomp.proto = htons(PROTO_VJCOMP); 1130ff360cc9SBrian Somers nak.hdr.id = TY_COMPPROTO; 1131ff360cc9SBrian Somers nak.hdr.len = 4; 1132ff360cc9SBrian Somers memcpy(nak.data, &pcomp, 2); 1133ff360cc9SBrian Somers fsm_nak(dec, &nak); 1134af57ed9fSAtsushi Murai } 1135af57ed9fSAtsushi Murai break; 1136af57ed9fSAtsushi Murai case 6: /* RFC1332 */ 1137eb1ecbb2SBrian Somers if (ntohs(pcomp.proto) == PROTO_VJCOMP) { 1138eb1ecbb2SBrian Somers /* We know pcomp.slots' max value == MAX_VJ_STATES */ 1139eb1ecbb2SBrian Somers if (pcomp.slots >= MIN_VJ_STATES) { 11407686a200SBrian Somers /* Ok, we can do that */ 1141503a7782SBrian Somers ipcp->peer_compproto = compproto; 114283d1af55SBrian Somers ipcp->heis1172 = 0; 1143ff360cc9SBrian Somers fsm_ack(dec, opt); 1144af57ed9fSAtsushi Murai } else { 11457686a200SBrian Somers /* Get as close as we can to what he wants */ 11467686a200SBrian Somers ipcp->heis1172 = 0; 1147eb1ecbb2SBrian Somers pcomp.slots = MIN_VJ_STATES; 1148ff360cc9SBrian Somers nak.hdr.id = TY_COMPPROTO; 1149ff360cc9SBrian Somers nak.hdr.len = 4; 1150ff360cc9SBrian Somers memcpy(nak.data, &pcomp, 2); 1151ff360cc9SBrian Somers fsm_nak(dec, &nak); 11527686a200SBrian Somers } 11537686a200SBrian Somers } else { 11547686a200SBrian Somers /* What we really want */ 1155eb1ecbb2SBrian Somers pcomp.proto = htons(PROTO_VJCOMP); 1156eb1ecbb2SBrian Somers pcomp.slots = DEF_VJ_STATES; 1157eb1ecbb2SBrian Somers pcomp.compcid = 1; 1158ff360cc9SBrian Somers nak.hdr.id = TY_COMPPROTO; 1159ff360cc9SBrian Somers nak.hdr.len = 6; 1160ff360cc9SBrian Somers memcpy(nak.data, &pcomp, sizeof pcomp); 1161ff360cc9SBrian Somers fsm_nak(dec, &nak); 1162af57ed9fSAtsushi Murai } 1163af57ed9fSAtsushi Murai break; 1164af57ed9fSAtsushi Murai default: 1165ff360cc9SBrian Somers fsm_rej(dec, opt); 1166af57ed9fSAtsushi Murai break; 1167af57ed9fSAtsushi Murai } 1168af57ed9fSAtsushi Murai } 1169af57ed9fSAtsushi Murai break; 11708fa6ebe4SBrian Somers 1171af57ed9fSAtsushi Murai case MODE_NAK: 1172eb1ecbb2SBrian Somers if (ntohs(pcomp.proto) == PROTO_VJCOMP) { 1173eb1ecbb2SBrian Somers /* We know pcomp.slots' max value == MAX_VJ_STATES */ 1174eb1ecbb2SBrian Somers if (pcomp.slots < MIN_VJ_STATES) 1175eb1ecbb2SBrian Somers pcomp.slots = MIN_VJ_STATES; 1176eb1ecbb2SBrian Somers compproto = (ntohs(pcomp.proto) << 16) + (pcomp.slots << 8) + 1177eb1ecbb2SBrian Somers pcomp.compcid; 11787686a200SBrian Somers } else 11797686a200SBrian Somers compproto = 0; 1180dd7e2610SBrian Somers log_Printf(LogIPCP, "%s changing compproto: %08x --> %08x\n", 1181503a7782SBrian Somers tbuff, ipcp->my_compproto, compproto); 1182503a7782SBrian Somers ipcp->my_compproto = compproto; 1183af57ed9fSAtsushi Murai break; 11848fa6ebe4SBrian Somers 1185af57ed9fSAtsushi Murai case MODE_REJ: 1186ff360cc9SBrian Somers ipcp->peer_reject |= (1 << opt->hdr.id); 1187af57ed9fSAtsushi Murai break; 1188af57ed9fSAtsushi Murai } 1189af57ed9fSAtsushi Murai break; 11908fa6ebe4SBrian Somers 1191af57ed9fSAtsushi Murai case TY_IPADDRS: /* RFC1172 */ 1192ff360cc9SBrian Somers memcpy(&ipaddr.s_addr, opt->data, 4); 1193ff360cc9SBrian Somers memcpy(&dstipaddr.s_addr, opt->data + 4, 4); 119470ee81ffSBrian Somers snprintf(tbuff2, sizeof tbuff2, "%s %s,", tbuff, inet_ntoa(ipaddr)); 1195dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr)); 1196af57ed9fSAtsushi Murai 11979780ef31SBrian Somers switch (mode_type) { 1198af57ed9fSAtsushi Murai case MODE_REQ: 1199ff360cc9SBrian Somers fsm_rej(dec, opt); 1200af57ed9fSAtsushi Murai break; 12018fa6ebe4SBrian Somers 1202af57ed9fSAtsushi Murai case MODE_NAK: 1203af57ed9fSAtsushi Murai case MODE_REJ: 1204af57ed9fSAtsushi Murai break; 1205af57ed9fSAtsushi Murai } 1206af57ed9fSAtsushi Murai break; 1207d8e55738SJordan K. Hubbard 12083edeb0c6SBrian Somers case TY_PRIMARY_DNS: /* DNS negotiation (rfc1877) */ 1209d8e55738SJordan K. Hubbard case TY_SECONDARY_DNS: 1210ff360cc9SBrian Somers memcpy(&ipaddr.s_addr, opt->data, 4); 1211dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 12123edeb0c6SBrian Somers 12139780ef31SBrian Somers switch (mode_type) { 1214d8e55738SJordan K. Hubbard case MODE_REQ: 12153edeb0c6SBrian Somers if (!IsAccepted(ipcp->cfg.ns.dns_neg)) { 1216ff360cc9SBrian Somers ipcp->my_reject |= (1 << (opt->hdr.id - TY_ADJUST_NS)); 1217ff360cc9SBrian Somers fsm_rej(dec, opt); 1218d8e55738SJordan K. Hubbard break; 1219d8e55738SJordan K. Hubbard } 1220ff360cc9SBrian Somers have_ip = ipcp->ns.dns[opt->hdr.id == TY_PRIMARY_DNS ? 0 : 1]; 1221d568d6c4SBrian Somers 1222ff360cc9SBrian Somers if (opt->hdr.id == TY_PRIMARY_DNS && ipaddr.s_addr != have_ip.s_addr && 122330949fd4SBrian Somers ipaddr.s_addr == ipcp->ns.dns[1].s_addr) { 1224d568d6c4SBrian Somers /* Swap 'em 'round */ 122530949fd4SBrian Somers ipcp->ns.dns[0] = ipcp->ns.dns[1]; 122630949fd4SBrian Somers ipcp->ns.dns[1] = have_ip; 122730949fd4SBrian Somers have_ip = ipcp->ns.dns[0]; 12283edeb0c6SBrian Somers } 1229944f7098SBrian Somers 12303edeb0c6SBrian Somers if (ipaddr.s_addr != have_ip.s_addr) { 12311ae349f5Scvs2svn /* 12323edeb0c6SBrian Somers * The client has got the DNS stuff wrong (first request) so 12331ae349f5Scvs2svn * we'll tell 'em how it is 12341ae349f5Scvs2svn */ 1235ff360cc9SBrian Somers nak.hdr.id = opt->hdr.id; 1236ff360cc9SBrian Somers nak.hdr.len = 6; 1237ff360cc9SBrian Somers memcpy(nak.data, &have_ip.s_addr, 4); 1238ff360cc9SBrian Somers fsm_nak(dec, &nak); 12393edeb0c6SBrian Somers } else { 1240d8e55738SJordan K. Hubbard /* 12419d5abbddSJens Schweikhardt * Otherwise they have it right (this time) so we send an ack packet 1242944f7098SBrian Somers * back confirming it... end of story 1243d8e55738SJordan K. Hubbard */ 1244ff360cc9SBrian Somers fsm_ack(dec, opt); 12453edeb0c6SBrian Somers } 1246d8e55738SJordan K. Hubbard break; 12478fa6ebe4SBrian Somers 1248d568d6c4SBrian Somers case MODE_NAK: 12493edeb0c6SBrian Somers if (IsEnabled(ipcp->cfg.ns.dns_neg)) { 12503edeb0c6SBrian Somers gotdnsnak = 1; 1251ff360cc9SBrian Somers memcpy(&ipcp->ns.dns[opt->hdr.id == TY_PRIMARY_DNS ? 0 : 1].s_addr, 1252ff360cc9SBrian Somers opt->data, 4); 12533edeb0c6SBrian Somers } 1254d8e55738SJordan K. Hubbard break; 12558fa6ebe4SBrian Somers 12563edeb0c6SBrian Somers case MODE_REJ: /* Can't do much, stop asking */ 1257ff360cc9SBrian Somers ipcp->peer_reject |= (1 << (opt->hdr.id - TY_ADJUST_NS)); 1258d8e55738SJordan K. Hubbard break; 1259d8e55738SJordan K. Hubbard } 1260d8e55738SJordan K. Hubbard break; 1261d8e55738SJordan K. Hubbard 12623edeb0c6SBrian Somers case TY_PRIMARY_NBNS: /* M$ NetBIOS nameserver hack (rfc1877) */ 1263d8e55738SJordan K. Hubbard case TY_SECONDARY_NBNS: 1264ff360cc9SBrian Somers memcpy(&ipaddr.s_addr, opt->data, 4); 1265dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 12663edeb0c6SBrian Somers 12679780ef31SBrian Somers switch (mode_type) { 1268d8e55738SJordan K. Hubbard case MODE_REQ: 12693edeb0c6SBrian Somers have_ip.s_addr = 1270ff360cc9SBrian Somers ipcp->cfg.ns.nbns[opt->hdr.id == TY_PRIMARY_NBNS ? 0 : 1].s_addr; 12713edeb0c6SBrian Somers 12723edeb0c6SBrian Somers if (have_ip.s_addr == INADDR_ANY) { 1273dd7e2610SBrian Somers log_Printf(LogIPCP, "NBNS REQ - rejected - nbns not set\n"); 1274ff360cc9SBrian Somers ipcp->my_reject |= (1 << (opt->hdr.id - TY_ADJUST_NS)); 1275ff360cc9SBrian Somers fsm_rej(dec, opt); 1276d8e55738SJordan K. Hubbard break; 1277d8e55738SJordan K. Hubbard } 12783edeb0c6SBrian Somers 12793edeb0c6SBrian Somers if (ipaddr.s_addr != have_ip.s_addr) { 1280ff360cc9SBrian Somers nak.hdr.id = opt->hdr.id; 1281ff360cc9SBrian Somers nak.hdr.len = 6; 1282ff360cc9SBrian Somers memcpy(nak.data, &have_ip.s_addr, 4); 1283ff360cc9SBrian Somers fsm_nak(dec, &nak); 1284ff360cc9SBrian Somers } else 1285ff360cc9SBrian Somers fsm_ack(dec, opt); 1286d8e55738SJordan K. Hubbard break; 12878fa6ebe4SBrian Somers 1288d8e55738SJordan K. Hubbard case MODE_NAK: 1289ff360cc9SBrian Somers log_Printf(LogIPCP, "MS NBNS req %d - NAK??\n", opt->hdr.id); 1290d8e55738SJordan K. Hubbard break; 12918fa6ebe4SBrian Somers 1292d8e55738SJordan K. Hubbard case MODE_REJ: 1293ff360cc9SBrian Somers log_Printf(LogIPCP, "MS NBNS req %d - REJ??\n", opt->hdr.id); 1294d8e55738SJordan K. Hubbard break; 1295d8e55738SJordan K. Hubbard } 1296d8e55738SJordan K. Hubbard break; 1297d8e55738SJordan K. Hubbard 1298af57ed9fSAtsushi Murai default: 129930c2f2ffSBrian Somers if (mode_type != MODE_NOP) { 1300ff360cc9SBrian Somers ipcp->my_reject |= (1 << opt->hdr.id); 1301ff360cc9SBrian Somers fsm_rej(dec, opt); 130230c2f2ffSBrian Somers } 1303af57ed9fSAtsushi Murai break; 1304af57ed9fSAtsushi Murai } 1305af57ed9fSAtsushi Murai } 13061342caedSBrian Somers 1307d568d6c4SBrian Somers if (gotdnsnak) { 1308d568d6c4SBrian Somers if (ipcp->ns.writable) { 1309d568d6c4SBrian Somers log_Printf(LogDEBUG, "Updating resolver\n"); 1310d568d6c4SBrian Somers if (!ipcp_WriteDNS(ipcp)) { 13113edeb0c6SBrian Somers ipcp->peer_reject |= (1 << (TY_PRIMARY_DNS - TY_ADJUST_NS)); 13123edeb0c6SBrian Somers ipcp->peer_reject |= (1 << (TY_SECONDARY_DNS - TY_ADJUST_NS)); 1313d568d6c4SBrian Somers } else 131430949fd4SBrian Somers bundle_AdjustDNS(fp->bundle); 1315d568d6c4SBrian Somers } else { 1316d568d6c4SBrian Somers log_Printf(LogDEBUG, "Not updating resolver (readonly)\n"); 131730949fd4SBrian Somers bundle_AdjustDNS(fp->bundle); 1318d568d6c4SBrian Somers } 13193edeb0c6SBrian Somers } 13203edeb0c6SBrian Somers 1321e43ebac1SBrian Somers if (mode_type != MODE_NOP) { 13225e3b2d68SBrian Somers if (mode_type == MODE_REQ && !ipcp->peer_req) { 13235e3b2d68SBrian Somers if (dec->rejend == dec->rej && dec->nakend == dec->nak) { 13245e3b2d68SBrian Somers /* 13255e3b2d68SBrian Somers * Pretend the peer has requested an IP. 13265e3b2d68SBrian Somers * We do this to ensure that we only send one NAK if the only 13275e3b2d68SBrian Somers * reason for the NAK is because the peer isn't sending a 13285e3b2d68SBrian Somers * TY_IPADDR REQ. This stops us from repeatedly trying to tell 13295e3b2d68SBrian Somers * the peer that we have to have an IP address on their end. 13305e3b2d68SBrian Somers */ 13315e3b2d68SBrian Somers ipcp->peer_req = 1; 13325e3b2d68SBrian Somers } 13335f73635bSBrian Somers ipaddr.s_addr = INADDR_ANY; 13345f73635bSBrian Somers ipcp_ValidateReq(ipcp, ipaddr, dec); 13355f73635bSBrian Somers } 1336ff360cc9SBrian Somers fsm_opt_normalise(dec); 13371ae349f5Scvs2svn } 1338af57ed9fSAtsushi Murai } 1339af57ed9fSAtsushi Murai 13405d9e6103SBrian Somers extern struct mbuf * 13415d9e6103SBrian Somers ipcp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 1342af57ed9fSAtsushi Murai { 13437308ec68SBrian Somers /* Got PROTO_IPCP from link */ 134426af0ae9SBrian Somers m_settype(bp, MB_IPCPIN); 1345641684cdSBrian Somers if (bundle_Phase(bundle) == PHASE_NETWORK) 13465d9e6103SBrian Somers fsm_Input(&bundle->ncp.ipcp.fsm, bp); 1347641684cdSBrian Somers else { 1348641684cdSBrian Somers if (bundle_Phase(bundle) < PHASE_NETWORK) 1349641684cdSBrian Somers log_Printf(LogIPCP, "%s: Error: Unexpected IPCP in phase %s (ignored)\n", 13505d9e6103SBrian Somers l->name, bundle_PhaseName(bundle)); 135126af0ae9SBrian Somers m_freem(bp); 1352641684cdSBrian Somers } 13535d9e6103SBrian Somers return NULL; 1354af57ed9fSAtsushi Murai } 13559c97abd8SBrian Somers 13569c97abd8SBrian Somers int 1357972a1bcfSBrian Somers ipcp_UseHisIPaddr(struct bundle *bundle, struct in_addr hisaddr) 1358972a1bcfSBrian Somers { 1359972a1bcfSBrian Somers struct ipcp *ipcp = &bundle->ncp.ipcp; 136030949fd4SBrian Somers struct in_addr myaddr; 1361972a1bcfSBrian Somers 1362972a1bcfSBrian Somers memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 1363972a1bcfSBrian Somers iplist_reset(&ipcp->cfg.peer_list); 136430949fd4SBrian Somers ipcp->peer_ip = hisaddr; 136530949fd4SBrian Somers ncprange_setip4host(&ipcp->cfg.peer_range, hisaddr); 136630949fd4SBrian Somers ncprange_getip4addr(&ipcp->cfg.my_range, &myaddr); 1367972a1bcfSBrian Somers 136830949fd4SBrian Somers return ipcp_SetIPaddress(ipcp, myaddr, hisaddr); 1369972a1bcfSBrian Somers } 1370972a1bcfSBrian Somers 1371972a1bcfSBrian Somers int 1372dd7e2610SBrian Somers ipcp_UseHisaddr(struct bundle *bundle, const char *hisaddr, int setaddr) 13739c97abd8SBrian Somers { 137430949fd4SBrian Somers struct in_addr myaddr; 137530949fd4SBrian Somers struct ncp *ncp = &bundle->ncp; 137630949fd4SBrian Somers struct ipcp *ipcp = &ncp->ipcp; 137730949fd4SBrian Somers struct ncpaddr ncpaddr; 13785828db6dSBrian Somers 13797308ec68SBrian Somers /* Use `hisaddr' for the peers address (set iface if `setaddr') */ 13805828db6dSBrian Somers memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 13815828db6dSBrian Somers iplist_reset(&ipcp->cfg.peer_list); 13829c97abd8SBrian Somers if (strpbrk(hisaddr, ",-")) { 13835828db6dSBrian Somers iplist_setsrc(&ipcp->cfg.peer_list, hisaddr); 13845828db6dSBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 13855828db6dSBrian Somers iplist_setrandpos(&ipcp->cfg.peer_list); 138630c2f2ffSBrian Somers ipcp->peer_ip = ChooseHisAddr(bundle, ipcp->my_ip); 13875828db6dSBrian Somers if (ipcp->peer_ip.s_addr == INADDR_ANY) { 1388dd7e2610SBrian Somers log_Printf(LogWARN, "%s: None available !\n", ipcp->cfg.peer_list.src); 13891d1fc017SBrian Somers return 0; 13909c97abd8SBrian Somers } 139130949fd4SBrian Somers ncprange_setip4host(&ipcp->cfg.peer_range, ipcp->peer_ip); 13929c97abd8SBrian Somers } else { 1393dd7e2610SBrian Somers log_Printf(LogWARN, "%s: Invalid range !\n", hisaddr); 13949c97abd8SBrian Somers return 0; 13959c97abd8SBrian Somers } 139630949fd4SBrian Somers } else if (ncprange_aton(&ipcp->cfg.peer_range, ncp, hisaddr) != 0) { 139730949fd4SBrian Somers if (ncprange_family(&ipcp->cfg.my_range) != AF_INET) { 139830949fd4SBrian Somers log_Printf(LogWARN, "%s: Not an AF_INET address !\n", hisaddr); 139930949fd4SBrian Somers return 0; 140030949fd4SBrian Somers } 140130949fd4SBrian Somers ncprange_getip4addr(&ipcp->cfg.my_range, &myaddr); 140230949fd4SBrian Somers ncprange_getip4addr(&ipcp->cfg.peer_range, &ipcp->peer_ip); 14039c97abd8SBrian Somers 140430949fd4SBrian Somers if (setaddr && !ipcp_SetIPaddress(ipcp, myaddr, ipcp->peer_ip)) 14059c97abd8SBrian Somers return 0; 14069c97abd8SBrian Somers } else 14079c97abd8SBrian Somers return 0; 14089c97abd8SBrian Somers 140930949fd4SBrian Somers ncpaddr_setip4(&ncpaddr, ipcp->peer_ip); 141030949fd4SBrian Somers bundle_AdjustFilters(bundle, NULL, &ncpaddr); 14111d1fc017SBrian Somers 14121d1fc017SBrian Somers return 1; /* Ok */ 14139c97abd8SBrian Somers } 1414bc76350eSBrian Somers 1415bc76350eSBrian Somers struct in_addr 1416bc76350eSBrian Somers addr2mask(struct in_addr addr) 1417bc76350eSBrian Somers { 1418bc76350eSBrian Somers u_int32_t haddr = ntohl(addr.s_addr); 1419bc76350eSBrian Somers 1420bc76350eSBrian Somers haddr = IN_CLASSA(haddr) ? IN_CLASSA_NET : 1421bc76350eSBrian Somers IN_CLASSB(haddr) ? IN_CLASSB_NET : 1422bc76350eSBrian Somers IN_CLASSC_NET; 1423bc76350eSBrian Somers addr.s_addr = htonl(haddr); 1424bc76350eSBrian Somers 1425bc76350eSBrian Somers return addr; 1426bc76350eSBrian Somers } 142730949fd4SBrian Somers 142830949fd4SBrian Somers size_t 142930949fd4SBrian Somers ipcp_QueueLen(struct ipcp *ipcp) 143030949fd4SBrian Somers { 143130949fd4SBrian Somers struct mqueue *q; 143230949fd4SBrian Somers size_t result; 143330949fd4SBrian Somers 143430949fd4SBrian Somers result = 0; 143530949fd4SBrian Somers for (q = ipcp->Queue; q < ipcp->Queue + IPCP_QUEUES(ipcp); q++) 143630949fd4SBrian Somers result += q->len; 143730949fd4SBrian Somers 143830949fd4SBrian Somers return result; 143930949fd4SBrian Somers } 144030949fd4SBrian Somers 144130949fd4SBrian Somers int 144230949fd4SBrian Somers ipcp_PushPacket(struct ipcp *ipcp, struct link *l) 144330949fd4SBrian Somers { 144430949fd4SBrian Somers struct bundle *bundle = ipcp->fsm.bundle; 144530949fd4SBrian Somers struct mqueue *queue; 144630949fd4SBrian Somers struct mbuf *bp; 144730949fd4SBrian Somers int m_len; 144830949fd4SBrian Somers u_int32_t secs = 0; 144930949fd4SBrian Somers unsigned alivesecs = 0; 145030949fd4SBrian Somers 145130949fd4SBrian Somers if (ipcp->fsm.state != ST_OPENED) 145230949fd4SBrian Somers return 0; 145330949fd4SBrian Somers 145430949fd4SBrian Somers /* 145530949fd4SBrian Somers * If ccp is not open but is required, do nothing. 145630949fd4SBrian Somers */ 145730949fd4SBrian Somers if (l->ccp.fsm.state != ST_OPENED && ccp_Required(&l->ccp)) { 145830949fd4SBrian Somers log_Printf(LogPHASE, "%s: Not transmitting... waiting for CCP\n", l->name); 145930949fd4SBrian Somers return 0; 146030949fd4SBrian Somers } 146130949fd4SBrian Somers 146230949fd4SBrian Somers queue = ipcp->Queue + IPCP_QUEUES(ipcp) - 1; 146330949fd4SBrian Somers do { 146430949fd4SBrian Somers if (queue->top) { 146530949fd4SBrian Somers bp = m_dequeue(queue); 146630949fd4SBrian Somers bp = mbuf_Read(bp, &secs, sizeof secs); 146730949fd4SBrian Somers bp = m_pullup(bp); 146830949fd4SBrian Somers m_len = m_length(bp); 146930949fd4SBrian Somers if (!FilterCheck(MBUF_CTOP(bp), AF_INET, &bundle->filter.alive, 147030949fd4SBrian Somers &alivesecs)) { 147130949fd4SBrian Somers if (secs == 0) 147230949fd4SBrian Somers secs = alivesecs; 147330949fd4SBrian Somers bundle_StartIdleTimer(bundle, secs); 147430949fd4SBrian Somers } 147530949fd4SBrian Somers link_PushPacket(l, bp, bundle, 0, PROTO_IP); 147630949fd4SBrian Somers ipcp_AddOutOctets(ipcp, m_len); 147730949fd4SBrian Somers return 1; 147830949fd4SBrian Somers } 147930949fd4SBrian Somers } while (queue-- != ipcp->Queue); 148030949fd4SBrian Somers 148130949fd4SBrian Somers return 0; 148230949fd4SBrian Somers } 1483