178189Sbrian/*- 2330449Seadler * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3330449Seadler * 478189Sbrian * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org> 578189Sbrian * based on work by Toshiharu OHNO <tony-o@iij.ad.jp> 678189Sbrian * Internet Initiative Japan, Inc (IIJ) 778189Sbrian * All rights reserved. 86059Samurai * 978189Sbrian * Redistribution and use in source and binary forms, with or without 1078189Sbrian * modification, are permitted provided that the following conditions 1178189Sbrian * are met: 1278189Sbrian * 1. Redistributions of source code must retain the above copyright 1378189Sbrian * notice, this list of conditions and the following disclaimer. 1478189Sbrian * 2. Redistributions in binary form must reproduce the above copyright 1578189Sbrian * notice, this list of conditions and the following disclaimer in the 1678189Sbrian * documentation and/or other materials provided with the distribution. 176059Samurai * 1878189Sbrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1978189Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2078189Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2178189Sbrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2278189Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2378189Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2478189Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2578189Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2678189Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2778189Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2878189Sbrian * SUCH DAMAGE. 296059Samurai * 3050479Speter * $FreeBSD: stable/11/usr.sbin/ppp/ipcp.c 330449 2018-03-05 07:26:05Z eadler $ 316059Samurai */ 3278189Sbrian 3330715Sbrian#include <sys/param.h> 346059Samurai#include <netinet/in_systm.h> 3529048Sbrian#include <netinet/in.h> 366059Samurai#include <netinet/ip.h> 376059Samurai#include <arpa/inet.h> 386059Samurai#include <sys/socket.h> 3976492Sbrian#include <net/if.h> 4040665Sbrian#include <net/route.h> 4130715Sbrian#include <netdb.h> 4236285Sbrian#include <sys/un.h> 4330715Sbrian 4446085Sbrian#include <errno.h> 4536285Sbrian#include <fcntl.h> 4636285Sbrian#include <resolv.h> 47102500Sbrian#include <stdarg.h> 4832614Sbrian#include <stdlib.h> 4930715Sbrian#include <string.h> 5058044Sbrian#include <sys/stat.h> 5136285Sbrian#include <termios.h> 5230715Sbrian#include <unistd.h> 5330715Sbrian 5450059Sbrian#ifndef NONAT 5558037Sbrian#ifdef LOCALNAT 5658037Sbrian#include "alias.h" 5758037Sbrian#else 5846086Sbrian#include <alias.h> 5939395Sbrian#endif 6039395Sbrian#endif 6158037Sbrian 6246686Sbrian#include "layer.h" 6338814Sbrian#include "ua.h" 6437009Sbrian#include "defs.h" 6531343Sbrian#include "command.h" 6630715Sbrian#include "mbuf.h" 6730715Sbrian#include "log.h" 6830715Sbrian#include "timer.h" 6929048Sbrian#include "fsm.h" 7046686Sbrian#include "proto.h" 7131690Sbrian#include "iplist.h" 7236285Sbrian#include "throughput.h" 7336285Sbrian#include "slcompress.h" 7438557Sbrian#include "lqr.h" 7538557Sbrian#include "hdlc.h" 7663484Sbrian#include "lcp.h" 7781634Sbrian#include "ncpaddr.h" 7881634Sbrian#include "ip.h" 7929048Sbrian#include "ipcp.h" 8036285Sbrian#include "filter.h" 8136285Sbrian#include "descriptor.h" 8230715Sbrian#include "vjcomp.h" 8336285Sbrian#include "async.h" 8436285Sbrian#include "ccp.h" 8536285Sbrian#include "link.h" 8636285Sbrian#include "physical.h" 8736285Sbrian#include "mp.h" 8843313Sbrian#ifndef NORADIUS 8943313Sbrian#include "radius.h" 9043313Sbrian#endif 9181634Sbrian#include "ipv6cp.h" 9281634Sbrian#include "ncp.h" 9336285Sbrian#include "bundle.h" 9436285Sbrian#include "id.h" 9536285Sbrian#include "arp.h" 9636285Sbrian#include "systems.h" 9736285Sbrian#include "prompt.h" 9831690Sbrian#include "route.h" 9940561Sbrian#include "iface.h" 1006059Samurai 10136285Sbrian#undef REJECTED 10236285Sbrian#define REJECTED(p, x) ((p)->peer_reject & (1<<(x))) 10336285Sbrian#define issep(ch) ((ch) == ' ' || (ch) == '\t') 10436285Sbrian#define isip(ch) (((ch) >= '0' && (ch) <= '9') || (ch) == '.') 1056059Samurai 10636285Sbrianstruct compreq { 10736285Sbrian u_short proto; 10836285Sbrian u_char slots; 10936285Sbrian u_char compcid; 11036285Sbrian}; 1116059Samurai 11236285Sbrianstatic int IpcpLayerUp(struct fsm *); 11336285Sbrianstatic void IpcpLayerDown(struct fsm *); 11426516Sbrianstatic void IpcpLayerStart(struct fsm *); 11526516Sbrianstatic void IpcpLayerFinish(struct fsm *); 11644305Sbrianstatic void IpcpInitRestartCounter(struct fsm *, int); 11736285Sbrianstatic void IpcpSendConfigReq(struct fsm *); 11836285Sbrianstatic void IpcpSentTerminateReq(struct fsm *); 11936285Sbrianstatic void IpcpSendTerminateAck(struct fsm *, u_char); 12094894Sbrianstatic void IpcpDecodeConfig(struct fsm *, u_char *, u_char *, int, 12136285Sbrian struct fsm_decode *); 1226059Samurai 123177100Spisoextern struct libalias *la; 124177100Spiso 12536285Sbrianstatic struct fsm_callbacks ipcp_Callbacks = { 1266059Samurai IpcpLayerUp, 1276059Samurai IpcpLayerDown, 1286059Samurai IpcpLayerStart, 1296059Samurai IpcpLayerFinish, 1306059Samurai IpcpInitRestartCounter, 1316059Samurai IpcpSendConfigReq, 13236285Sbrian IpcpSentTerminateReq, 1336059Samurai IpcpSendTerminateAck, 1346059Samurai IpcpDecodeConfig, 13536285Sbrian fsm_NullRecvResetReq, 13636285Sbrian fsm_NullRecvResetAck 1376059Samurai}; 1386059Samurai 13958034Sbrianstatic const char * 14058034Sbrianprotoname(int proto) 14158034Sbrian{ 14258034Sbrian static struct { 14358034Sbrian int id; 14458034Sbrian const char *txt; 14558034Sbrian } cftypes[] = { 14658034Sbrian /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */ 14758034Sbrian { 1, "IPADDRS" }, /* IP-Addresses */ /* deprecated */ 14858034Sbrian { 2, "COMPPROTO" }, /* IP-Compression-Protocol */ 14958034Sbrian { 3, "IPADDR" }, /* IP-Address */ 15058034Sbrian { 129, "PRIDNS" }, /* 129: Primary DNS Server Address */ 15158034Sbrian { 130, "PRINBNS" }, /* 130: Primary NBNS Server Address */ 15258034Sbrian { 131, "SECDNS" }, /* 131: Secondary DNS Server Address */ 15358034Sbrian { 132, "SECNBNS" } /* 132: Secondary NBNS Server Address */ 15458034Sbrian }; 155134789Sbrian unsigned f; 1566059Samurai 15758034Sbrian for (f = 0; f < sizeof cftypes / sizeof *cftypes; f++) 15858034Sbrian if (cftypes[f].id == proto) 15958034Sbrian return cftypes[f].txt; 16031171Sbrian 16158034Sbrian return NumStr(proto, NULL, 0); 16258034Sbrian} 16331171Sbrian 16431272Sbrianvoid 16536285Sbrianipcp_AddInOctets(struct ipcp *ipcp, int n) 1666059Samurai{ 16736285Sbrian throughput_addin(&ipcp->throughput, n); 1686059Samurai} 1696059Samurai 17031272Sbrianvoid 17136285Sbrianipcp_AddOutOctets(struct ipcp *ipcp, int n) 1726059Samurai{ 17336285Sbrian throughput_addout(&ipcp->throughput, n); 1746059Samurai} 1756059Samurai 17658044Sbrianvoid 17758044Sbrianipcp_LoadDNS(struct ipcp *ipcp) 1786059Samurai{ 17958044Sbrian int fd; 1806059Samurai 18158044Sbrian ipcp->ns.dns[0].s_addr = ipcp->ns.dns[1].s_addr = INADDR_NONE; 18236285Sbrian 18358044Sbrian if (ipcp->ns.resolv != NULL) { 18458044Sbrian free(ipcp->ns.resolv); 18558044Sbrian ipcp->ns.resolv = NULL; 18632614Sbrian } 18758044Sbrian if (ipcp->ns.resolv_nons != NULL) { 18858044Sbrian free(ipcp->ns.resolv_nons); 18958044Sbrian ipcp->ns.resolv_nons = NULL; 19058044Sbrian } 19158044Sbrian ipcp->ns.resolver = 0; 19229048Sbrian 19358044Sbrian if ((fd = open(_PATH_RESCONF, O_RDONLY)) != -1) { 19458044Sbrian struct stat st; 19526516Sbrian 19658044Sbrian if (fstat(fd, &st) == 0) { 19758044Sbrian ssize_t got; 19831272Sbrian 199139973Sbrian /* 200139973Sbrian * Note, ns.resolv and ns.resolv_nons are assumed to always point to 201139973Sbrian * buffers of the same size! See the strcpy() below. 202139973Sbrian */ 20358044Sbrian if ((ipcp->ns.resolv_nons = (char *)malloc(st.st_size + 1)) == NULL) 20458044Sbrian log_Printf(LogERROR, "Failed to malloc %lu for %s: %s\n", 20558044Sbrian (unsigned long)st.st_size, _PATH_RESCONF, strerror(errno)); 20658044Sbrian else if ((ipcp->ns.resolv = (char *)malloc(st.st_size + 1)) == NULL) { 20758044Sbrian log_Printf(LogERROR, "Failed(2) to malloc %lu for %s: %s\n", 20858044Sbrian (unsigned long)st.st_size, _PATH_RESCONF, strerror(errno)); 20958044Sbrian free(ipcp->ns.resolv_nons); 21058044Sbrian ipcp->ns.resolv_nons = NULL; 21158044Sbrian } else if ((got = read(fd, ipcp->ns.resolv, st.st_size)) != st.st_size) { 21258044Sbrian if (got == -1) 21358044Sbrian log_Printf(LogERROR, "Failed to read %s: %s\n", 21458044Sbrian _PATH_RESCONF, strerror(errno)); 21558044Sbrian else 21658044Sbrian log_Printf(LogERROR, "Failed to read %s, got %lu not %lu\n", 21758044Sbrian _PATH_RESCONF, (unsigned long)got, 21858044Sbrian (unsigned long)st.st_size); 21958044Sbrian free(ipcp->ns.resolv_nons); 22058044Sbrian ipcp->ns.resolv_nons = NULL; 22158044Sbrian free(ipcp->ns.resolv); 22258044Sbrian ipcp->ns.resolv = NULL; 22358044Sbrian } else { 22458044Sbrian char *cp, *cp_nons, *ncp, ch; 22558044Sbrian int n; 22636285Sbrian 22758044Sbrian ipcp->ns.resolv[st.st_size] = '\0'; 22858044Sbrian ipcp->ns.resolver = 1; 22936285Sbrian 23058044Sbrian cp_nons = ipcp->ns.resolv_nons; 23158044Sbrian cp = ipcp->ns.resolv; 23258044Sbrian n = 0; 23336285Sbrian 23458044Sbrian while ((ncp = strstr(cp, "nameserver")) != NULL) { 23558044Sbrian if (ncp != cp) { 23658044Sbrian memcpy(cp_nons, cp, ncp - cp); 23758044Sbrian cp_nons += ncp - cp; 23858044Sbrian } 23958044Sbrian if ((ncp != cp && ncp[-1] != '\n') || !issep(ncp[10])) { 24058044Sbrian memcpy(cp_nons, ncp, 9); 24158044Sbrian cp_nons += 9; 24258044Sbrian cp = ncp + 9; /* Can't match "nameserver" at cp... */ 24358044Sbrian continue; 24458044Sbrian } 24558044Sbrian 24658044Sbrian for (cp = ncp + 11; issep(*cp); cp++) /* Skip whitespace */ 24758044Sbrian ; 24858044Sbrian 24958044Sbrian for (ncp = cp; isip(*ncp); ncp++) /* Jump over IP */ 25058044Sbrian ; 25158044Sbrian 25258044Sbrian ch = *ncp; 25358044Sbrian *ncp = '\0'; 25481634Sbrian if (n < 2 && inet_aton(cp, ipcp->ns.dns)) 25558044Sbrian n++; 25658044Sbrian *ncp = ch; 25758044Sbrian 25858044Sbrian if ((cp = strchr(ncp, '\n')) == NULL) /* Point at next line */ 25958044Sbrian cp = ncp + strlen(ncp); 26058044Sbrian else 26158044Sbrian cp++; 26236285Sbrian } 263139973Sbrian /* 264139973Sbrian * Note, cp_nons and cp always point to buffers of the same size, so 265139973Sbrian * strcpy is ok! 266139973Sbrian */ 26758044Sbrian strcpy(cp_nons, cp); /* Copy the end - including the NUL */ 26858044Sbrian cp_nons += strlen(cp_nons) - 1; 26958044Sbrian while (cp_nons >= ipcp->ns.resolv_nons && *cp_nons == '\n') 27058044Sbrian *cp_nons-- = '\0'; 27158044Sbrian if (n == 2 && ipcp->ns.dns[0].s_addr == INADDR_ANY) { 27258044Sbrian ipcp->ns.dns[0].s_addr = ipcp->ns.dns[1].s_addr; 27358044Sbrian ipcp->ns.dns[1].s_addr = INADDR_ANY; 27458044Sbrian } 27581634Sbrian bundle_AdjustDNS(ipcp->fsm.bundle); 27636285Sbrian } 27758044Sbrian } else 27858044Sbrian log_Printf(LogERROR, "Failed to stat opened %s: %s\n", 27958044Sbrian _PATH_RESCONF, strerror(errno)); 28058044Sbrian 28158044Sbrian close(fd); 28236285Sbrian } 28358044Sbrian} 28436285Sbrian 28558044Sbrianint 28658044Sbrianipcp_WriteDNS(struct ipcp *ipcp) 28758044Sbrian{ 28858044Sbrian const char *paddr; 28958044Sbrian mode_t mask; 29058044Sbrian FILE *fp; 29158044Sbrian 29258044Sbrian if (ipcp->ns.dns[0].s_addr == INADDR_ANY && 29358044Sbrian ipcp->ns.dns[1].s_addr == INADDR_ANY) { 29458044Sbrian log_Printf(LogIPCP, "%s not modified: All nameservers NAKd\n", 29558044Sbrian _PATH_RESCONF); 29658044Sbrian return 0; 29736285Sbrian } 29836285Sbrian 29958044Sbrian if (ipcp->ns.dns[0].s_addr == INADDR_ANY) { 30058044Sbrian ipcp->ns.dns[0].s_addr = ipcp->ns.dns[1].s_addr; 30158044Sbrian ipcp->ns.dns[1].s_addr = INADDR_ANY; 30236285Sbrian } 30336285Sbrian 30460839Sbrian mask = umask(022); 30558044Sbrian if ((fp = ID0fopen(_PATH_RESCONF, "w")) != NULL) { 30658044Sbrian umask(mask); 30760922Sbrian if (ipcp->ns.resolv_nons) 30860839Sbrian fputs(ipcp->ns.resolv_nons, fp); 30958044Sbrian paddr = inet_ntoa(ipcp->ns.dns[0]); 31058044Sbrian log_Printf(LogIPCP, "Primary nameserver set to %s\n", paddr); 31158044Sbrian fprintf(fp, "\nnameserver %s\n", paddr); 31258044Sbrian if (ipcp->ns.dns[1].s_addr != INADDR_ANY && 31358044Sbrian ipcp->ns.dns[1].s_addr != INADDR_NONE && 31458044Sbrian ipcp->ns.dns[1].s_addr != ipcp->ns.dns[0].s_addr) { 31558044Sbrian paddr = inet_ntoa(ipcp->ns.dns[1]); 31658044Sbrian log_Printf(LogIPCP, "Secondary nameserver set to %s\n", paddr); 31758044Sbrian fprintf(fp, "nameserver %s\n", paddr); 31858044Sbrian } 31958044Sbrian if (fclose(fp) == EOF) { 32058044Sbrian log_Printf(LogERROR, "write(): Failed updating %s: %s\n", _PATH_RESCONF, 32158044Sbrian strerror(errno)); 32236285Sbrian return 0; 32336285Sbrian } 324214011Sglebius } else { 32558044Sbrian umask(mask); 326214011Sglebius log_Printf(LogERROR,"fopen(\"%s\", \"w\") failed: %s\n", _PATH_RESCONF, 327214011Sglebius strerror(errno)); 328214011Sglebius } 32936285Sbrian 33036285Sbrian return 1; 3316059Samurai} 3326059Samurai 33358044Sbrianvoid 33458044Sbrianipcp_RestoreDNS(struct ipcp *ipcp) 33558044Sbrian{ 33658044Sbrian if (ipcp->ns.resolver) { 337134789Sbrian ssize_t got, len; 33858044Sbrian int fd; 33958044Sbrian 34058044Sbrian if ((fd = ID0open(_PATH_RESCONF, O_WRONLY|O_TRUNC, 0644)) != -1) { 34158044Sbrian len = strlen(ipcp->ns.resolv); 34258044Sbrian if ((got = write(fd, ipcp->ns.resolv, len)) != len) { 34358044Sbrian if (got == -1) 34458044Sbrian log_Printf(LogERROR, "Failed rewriting %s: write: %s\n", 34558044Sbrian _PATH_RESCONF, strerror(errno)); 34658044Sbrian else 347134789Sbrian log_Printf(LogERROR, "Failed rewriting %s: wrote %ld of %ld\n", 348134789Sbrian _PATH_RESCONF, (long)got, (long)len); 34958044Sbrian } 35058044Sbrian close(fd); 35158044Sbrian } else 35258044Sbrian log_Printf(LogERROR, "Failed rewriting %s: open: %s\n", _PATH_RESCONF, 35358044Sbrian strerror(errno)); 35458044Sbrian } else if (remove(_PATH_RESCONF) == -1) 35558044Sbrian log_Printf(LogERROR, "Failed removing %s: %s\n", _PATH_RESCONF, 35658044Sbrian strerror(errno)); 35798243Sbrian 35858044Sbrian} 35958044Sbrian 36036285Sbrianint 36136285Sbrianipcp_Show(struct cmdargs const *arg) 3626059Samurai{ 36336285Sbrian struct ipcp *ipcp = &arg->bundle->ncp.ipcp; 3646059Samurai 36536285Sbrian prompt_Printf(arg->prompt, "%s [%s]\n", ipcp->fsm.name, 36636285Sbrian State2Nam(ipcp->fsm.state)); 36736285Sbrian if (ipcp->fsm.state == ST_OPENED) { 36836285Sbrian prompt_Printf(arg->prompt, " His side: %s, %s\n", 36994894Sbrian inet_ntoa(ipcp->peer_ip), vj2asc(ipcp->peer_compproto)); 37036285Sbrian prompt_Printf(arg->prompt, " My side: %s, %s\n", 37194894Sbrian inet_ntoa(ipcp->my_ip), vj2asc(ipcp->my_compproto)); 37258042Sbrian prompt_Printf(arg->prompt, " Queued packets: %lu\n", 37381634Sbrian (unsigned long)ipcp_QueueLen(ipcp)); 3746059Samurai } 37536285Sbrian 37636285Sbrian prompt_Printf(arg->prompt, "\nDefaults:\n"); 37744305Sbrian prompt_Printf(arg->prompt, " FSM retry = %us, max %u Config" 37844305Sbrian " REQ%s, %u Term REQ%s\n", ipcp->cfg.fsm.timeout, 37944305Sbrian ipcp->cfg.fsm.maxreq, ipcp->cfg.fsm.maxreq == 1 ? "" : "s", 38044305Sbrian ipcp->cfg.fsm.maxtrm, ipcp->cfg.fsm.maxtrm == 1 ? "" : "s"); 38181634Sbrian prompt_Printf(arg->prompt, " My Address: %s\n", 38294894Sbrian ncprange_ntoa(&ipcp->cfg.my_range)); 38336285Sbrian if (ipcp->cfg.HaveTriggerAddress) 38444455Sbrian prompt_Printf(arg->prompt, " Trigger address: %s\n", 38536285Sbrian inet_ntoa(ipcp->cfg.TriggerAddress)); 38644455Sbrian 38744455Sbrian prompt_Printf(arg->prompt, " VJ compression: %s (%d slots %s slot " 38836285Sbrian "compression)\n", command_ShowNegval(ipcp->cfg.vj.neg), 38936285Sbrian ipcp->cfg.vj.slots, ipcp->cfg.vj.slotcomp ? "with" : "without"); 39036285Sbrian 39136285Sbrian if (iplist_isvalid(&ipcp->cfg.peer_list)) 39236285Sbrian prompt_Printf(arg->prompt, " His Address: %s\n", 39336285Sbrian ipcp->cfg.peer_list.src); 39436285Sbrian else 39581634Sbrian prompt_Printf(arg->prompt, " His Address: %s\n", 39694894Sbrian ncprange_ntoa(&ipcp->cfg.peer_range)); 39736285Sbrian 39858044Sbrian prompt_Printf(arg->prompt, " DNS: %s", 39958044Sbrian ipcp->cfg.ns.dns[0].s_addr == INADDR_NONE ? 40058044Sbrian "none" : inet_ntoa(ipcp->cfg.ns.dns[0])); 40158044Sbrian if (ipcp->cfg.ns.dns[1].s_addr != INADDR_NONE) 40281634Sbrian prompt_Printf(arg->prompt, ", %s", 40381634Sbrian inet_ntoa(ipcp->cfg.ns.dns[1])); 40458044Sbrian prompt_Printf(arg->prompt, ", %s\n", 40536285Sbrian command_ShowNegval(ipcp->cfg.ns.dns_neg)); 40658044Sbrian prompt_Printf(arg->prompt, " Resolver DNS: %s", 40758044Sbrian ipcp->ns.dns[0].s_addr == INADDR_NONE ? 40858044Sbrian "none" : inet_ntoa(ipcp->ns.dns[0])); 40958044Sbrian if (ipcp->ns.dns[1].s_addr != INADDR_NONE && 41058044Sbrian ipcp->ns.dns[1].s_addr != ipcp->ns.dns[0].s_addr) 41181634Sbrian prompt_Printf(arg->prompt, ", %s", 41281634Sbrian inet_ntoa(ipcp->ns.dns[1])); 41358044Sbrian prompt_Printf(arg->prompt, "\n NetBIOS NS: %s, ", 41494894Sbrian inet_ntoa(ipcp->cfg.ns.nbns[0])); 41581693Sbrian prompt_Printf(arg->prompt, "%s\n\n", 41681634Sbrian inet_ntoa(ipcp->cfg.ns.nbns[1])); 41736285Sbrian 41836285Sbrian throughput_disp(&ipcp->throughput, arg->prompt); 41936285Sbrian 42036285Sbrian return 0; 4216059Samurai} 4226059Samurai 42332614Sbrianint 42436285Sbrianipcp_vjset(struct cmdargs const *arg) 42532614Sbrian{ 42636285Sbrian if (arg->argc != arg->argn+2) 42732614Sbrian return -1; 42836285Sbrian if (!strcasecmp(arg->argv[arg->argn], "slots")) { 42932614Sbrian int slots; 43032614Sbrian 43136285Sbrian slots = atoi(arg->argv[arg->argn+1]); 43232614Sbrian if (slots < 4 || slots > 16) 43332614Sbrian return 1; 43436285Sbrian arg->bundle->ncp.ipcp.cfg.vj.slots = slots; 43532614Sbrian return 0; 43636285Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "slotcomp")) { 43736285Sbrian if (!strcasecmp(arg->argv[arg->argn+1], "on")) 43836285Sbrian arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 1; 43936285Sbrian else if (!strcasecmp(arg->argv[arg->argn+1], "off")) 44036285Sbrian arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 0; 44132614Sbrian else 44232614Sbrian return 2; 44332614Sbrian return 0; 44432614Sbrian } 44532614Sbrian return -1; 44632614Sbrian} 44732614Sbrian 44836285Sbrianvoid 44936285Sbrianipcp_Init(struct ipcp *ipcp, struct bundle *bundle, struct link *l, 45036285Sbrian const struct fsm_parent *parent) 45132614Sbrian{ 45236285Sbrian struct hostent *hp; 45381634Sbrian struct in_addr host; 45474049Sbrian char name[MAXHOSTNAMELEN]; 45555146Sbrian static const char * const timer_names[] = 45636285Sbrian {"IPCP restart", "IPCP openmode", "IPCP stopped"}; 45736285Sbrian 45844305Sbrian fsm_Init(&ipcp->fsm, "IPCP", PROTO_IPCP, 1, IPCP_MAXCODE, LogIPCP, 45936285Sbrian bundle, l, parent, &ipcp_Callbacks, timer_names); 46036285Sbrian 46136285Sbrian ipcp->cfg.vj.slots = DEF_VJ_STATES; 46236285Sbrian ipcp->cfg.vj.slotcomp = 1; 46336285Sbrian memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range); 46481634Sbrian 46581634Sbrian host.s_addr = htonl(INADDR_LOOPBACK); 46681634Sbrian ipcp->cfg.netmask.s_addr = INADDR_ANY; 46736285Sbrian if (gethostname(name, sizeof name) == 0) { 46836285Sbrian hp = gethostbyname(name); 46981634Sbrian if (hp && hp->h_addrtype == AF_INET && hp->h_length == sizeof host.s_addr) 47081634Sbrian memcpy(&host.s_addr, hp->h_addr, sizeof host.s_addr); 47132614Sbrian } 47281634Sbrian ncprange_setip4(&ipcp->cfg.my_range, host, ipcp->cfg.netmask); 47381634Sbrian ncprange_setip4(&ipcp->cfg.peer_range, ipcp->cfg.netmask, ipcp->cfg.netmask); 47481634Sbrian 47536285Sbrian iplist_setsrc(&ipcp->cfg.peer_list, ""); 47636285Sbrian ipcp->cfg.HaveTriggerAddress = 0; 47736285Sbrian 47858044Sbrian ipcp->cfg.ns.dns[0].s_addr = INADDR_NONE; 47958044Sbrian ipcp->cfg.ns.dns[1].s_addr = INADDR_NONE; 48036285Sbrian ipcp->cfg.ns.dns_neg = 0; 48136285Sbrian ipcp->cfg.ns.nbns[0].s_addr = INADDR_ANY; 48236285Sbrian ipcp->cfg.ns.nbns[1].s_addr = INADDR_ANY; 48336285Sbrian 48444305Sbrian ipcp->cfg.fsm.timeout = DEF_FSMRETRY; 48544305Sbrian ipcp->cfg.fsm.maxreq = DEF_FSMTRIES; 48644305Sbrian ipcp->cfg.fsm.maxtrm = DEF_FSMTRIES; 48736285Sbrian ipcp->cfg.vj.neg = NEG_ENABLED|NEG_ACCEPTED; 48836285Sbrian 48936285Sbrian memset(&ipcp->vj, '\0', sizeof ipcp->vj); 49036285Sbrian 49158044Sbrian ipcp->ns.resolv = NULL; 49258044Sbrian ipcp->ns.resolv_nons = NULL; 49358044Sbrian ipcp->ns.writable = 1; 49458044Sbrian ipcp_LoadDNS(ipcp); 49558044Sbrian 49649434Sbrian throughput_init(&ipcp->throughput, SAMPLE_PERIOD); 49738557Sbrian memset(ipcp->Queue, '\0', sizeof ipcp->Queue); 49843313Sbrian ipcp_Setup(ipcp, INADDR_NONE); 49932614Sbrian} 50032614Sbrian 5016059Samuraivoid 50250867Sbrianipcp_Destroy(struct ipcp *ipcp) 50350867Sbrian{ 50481634Sbrian throughput_destroy(&ipcp->throughput); 50581634Sbrian 50658044Sbrian if (ipcp->ns.resolv != NULL) { 50758044Sbrian free(ipcp->ns.resolv); 50858044Sbrian ipcp->ns.resolv = NULL; 50958044Sbrian } 51058044Sbrian if (ipcp->ns.resolv_nons != NULL) { 51158044Sbrian free(ipcp->ns.resolv_nons); 51258044Sbrian ipcp->ns.resolv_nons = NULL; 51358044Sbrian } 51450867Sbrian} 51550867Sbrian 51650867Sbrianvoid 51736285Sbrianipcp_SetLink(struct ipcp *ipcp, struct link *l) 5186059Samurai{ 51936285Sbrian ipcp->fsm.link = l; 52036285Sbrian} 52136285Sbrian 52236285Sbrianvoid 52343313Sbrianipcp_Setup(struct ipcp *ipcp, u_int32_t mask) 52436285Sbrian{ 52540561Sbrian struct iface *iface = ipcp->fsm.bundle->iface; 52681634Sbrian struct ncpaddr ipaddr; 52781634Sbrian struct in_addr peer; 528134789Sbrian int pos; 529134789Sbrian unsigned n; 53036285Sbrian 53136285Sbrian ipcp->fsm.open_mode = 0; 53243313Sbrian ipcp->ifmask.s_addr = mask == INADDR_NONE ? ipcp->cfg.netmask.s_addr : mask; 53336285Sbrian 53436285Sbrian if (iplist_isvalid(&ipcp->cfg.peer_list)) { 53540561Sbrian /* Try to give the peer a previously configured IP address */ 53681634Sbrian for (n = 0; n < iface->addrs; n++) { 53781634Sbrian if (!ncpaddr_getip4(&iface->addr[n].peer, &peer)) 53881634Sbrian continue; 53981634Sbrian if ((pos = iplist_ip2pos(&ipcp->cfg.peer_list, peer)) != -1) { 54081634Sbrian ncpaddr_setip4(&ipaddr, iplist_setcurpos(&ipcp->cfg.peer_list, pos)); 54140561Sbrian break; 54240561Sbrian } 54340561Sbrian } 54481634Sbrian if (n == iface->addrs) 54540561Sbrian /* Ok, so none of 'em fit.... pick a random one */ 54681634Sbrian ncpaddr_setip4(&ipaddr, iplist_setrandpos(&ipcp->cfg.peer_list)); 54740561Sbrian 54881634Sbrian ncprange_sethost(&ipcp->cfg.peer_range, &ipaddr); 5496059Samurai } 5509440Samurai 55136285Sbrian ipcp->heis1172 = 0; 55280476Sbrian ipcp->peer_req = 0; 55381634Sbrian ncprange_getip4addr(&ipcp->cfg.peer_range, &ipcp->peer_ip); 55436285Sbrian ipcp->peer_compproto = 0; 55536285Sbrian 55636285Sbrian if (ipcp->cfg.HaveTriggerAddress) { 55736285Sbrian /* 55836285Sbrian * Some implementations of PPP require that we send a 55936285Sbrian * *special* value as our address, even though the rfc specifies 56036285Sbrian * full negotiation (e.g. "0.0.0.0" or Not "0.0.0.0"). 56136285Sbrian */ 56236285Sbrian ipcp->my_ip = ipcp->cfg.TriggerAddress; 56336285Sbrian log_Printf(LogIPCP, "Using trigger address %s\n", 56436285Sbrian inet_ntoa(ipcp->cfg.TriggerAddress)); 56540561Sbrian } else { 56636285Sbrian /* 56740561Sbrian * Otherwise, if we've used an IP number before and it's still within 56840561Sbrian * the network specified on the ``set ifaddr'' line, we really 56940561Sbrian * want to keep that IP number so that we can keep any existing 57081634Sbrian * connections that are bound to that IP. 57136285Sbrian */ 57281634Sbrian for (n = 0; n < iface->addrs; n++) { 57381634Sbrian ncprange_getaddr(&iface->addr[n].ifa, &ipaddr); 57481634Sbrian if (ncprange_contains(&ipcp->cfg.my_range, &ipaddr)) { 57581634Sbrian ncpaddr_getip4(&ipaddr, &ipcp->my_ip); 57640561Sbrian break; 57740561Sbrian } 57881634Sbrian } 57981634Sbrian if (n == iface->addrs) 58081634Sbrian ncprange_getip4addr(&ipcp->cfg.my_range, &ipcp->my_ip); 58140561Sbrian } 58236285Sbrian 58343313Sbrian if (IsEnabled(ipcp->cfg.vj.neg) 58443313Sbrian#ifndef NORADIUS 58543313Sbrian || (ipcp->fsm.bundle->radius.valid && ipcp->fsm.bundle->radius.vj) 58643313Sbrian#endif 58743313Sbrian ) 58836285Sbrian ipcp->my_compproto = (PROTO_VJCOMP << 16) + 58936285Sbrian ((ipcp->cfg.vj.slots - 1) << 8) + 59036285Sbrian ipcp->cfg.vj.slotcomp; 59136285Sbrian else 59236285Sbrian ipcp->my_compproto = 0; 59336285Sbrian sl_compress_init(&ipcp->vj.cslc, ipcp->cfg.vj.slots - 1); 59436285Sbrian 59536285Sbrian ipcp->peer_reject = 0; 59636285Sbrian ipcp->my_reject = 0; 59758044Sbrian 59881634Sbrian /* Copy startup values into ipcp->ns.dns */ 59958044Sbrian if (ipcp->cfg.ns.dns[0].s_addr != INADDR_NONE) 60081634Sbrian memcpy(ipcp->ns.dns, ipcp->cfg.ns.dns, sizeof ipcp->ns.dns); 60181634Sbrian} 60258044Sbrian 60381634Sbrianstatic int 60481634Sbriannumaddresses(struct in_addr mask) 60581634Sbrian{ 60681634Sbrian u_int32_t bit, haddr; 60781634Sbrian int n; 60881634Sbrian 60981634Sbrian haddr = ntohl(mask.s_addr); 61081634Sbrian bit = 1; 61181634Sbrian n = 1; 61281634Sbrian 61381634Sbrian do { 61481634Sbrian if (!(haddr & bit)) 61581634Sbrian n <<= 1; 61681634Sbrian } while (bit <<= 1); 61781634Sbrian 61881634Sbrian return n; 61936285Sbrian} 62036285Sbrian 62136285Sbrianstatic int 62281634Sbrianipcp_proxyarp(struct ipcp *ipcp, 623134789Sbrian int (*proxyfun)(struct bundle *, struct in_addr), 62481634Sbrian const struct iface_addr *addr) 62540665Sbrian{ 62681634Sbrian struct bundle *bundle = ipcp->fsm.bundle; 62781634Sbrian struct in_addr peer, mask, ip; 628134789Sbrian int n, ret; 62940665Sbrian 63081634Sbrian if (!ncpaddr_getip4(&addr->peer, &peer)) { 63181634Sbrian log_Printf(LogERROR, "Oops, ipcp_proxyarp() called with unexpected addr\n"); 63281634Sbrian return 0; 63381634Sbrian } 63481634Sbrian 63581634Sbrian ret = 0; 63681634Sbrian 63781634Sbrian if (Enabled(bundle, OPT_PROXYALL)) { 63881634Sbrian ncprange_getip4mask(&addr->ifa, &mask); 63981634Sbrian if ((n = numaddresses(mask)) > 256) { 64081634Sbrian log_Printf(LogWARN, "%s: Too many addresses for proxyall\n", 64181634Sbrian ncprange_ntoa(&addr->ifa)); 64281634Sbrian return 0; 64381634Sbrian } 64481634Sbrian ip.s_addr = peer.s_addr & mask.s_addr; 64581634Sbrian if (n >= 4) { 64681634Sbrian ip.s_addr = htonl(ntohl(ip.s_addr) + 1); 64781634Sbrian n -= 2; 64881634Sbrian } 64981634Sbrian while (n) { 65081634Sbrian if (!((ip.s_addr ^ peer.s_addr) & mask.s_addr)) { 651134789Sbrian if (!(ret = (*proxyfun)(bundle, ip))) 65281634Sbrian break; 65381634Sbrian n--; 65440665Sbrian } 65581634Sbrian ip.s_addr = htonl(ntohl(ip.s_addr) + 1); 65640665Sbrian } 65781634Sbrian ret = !n; 65881634Sbrian } else if (Enabled(bundle, OPT_PROXY)) 659134789Sbrian ret = (*proxyfun)(bundle, peer); 66040665Sbrian 66181634Sbrian return ret; 66240665Sbrian} 66340665Sbrian 66440665Sbrianstatic int 66581634Sbrianipcp_SetIPaddress(struct ipcp *ipcp, struct in_addr myaddr, 66681634Sbrian struct in_addr hisaddr) 66736285Sbrian{ 66881634Sbrian struct bundle *bundle = ipcp->fsm.bundle; 66981634Sbrian struct ncpaddr myncpaddr, hisncpaddr; 67081739Sbrian struct ncprange myrange; 67181634Sbrian struct in_addr mask; 67281739Sbrian struct sockaddr_storage ssdst, ssgw, ssmask; 67381739Sbrian struct sockaddr *sadst, *sagw, *samask; 67436285Sbrian 67581739Sbrian sadst = (struct sockaddr *)&ssdst; 67681739Sbrian sagw = (struct sockaddr *)&ssgw; 67781739Sbrian samask = (struct sockaddr *)&ssmask; 67881739Sbrian 67981634Sbrian ncpaddr_setip4(&hisncpaddr, hisaddr); 68081634Sbrian ncpaddr_setip4(&myncpaddr, myaddr); 68181634Sbrian ncprange_sethost(&myrange, &myncpaddr); 68281634Sbrian 68344455Sbrian mask = addr2mask(myaddr); 68436285Sbrian 68581634Sbrian if (ipcp->ifmask.s_addr != INADDR_ANY && 68681634Sbrian (ipcp->ifmask.s_addr & mask.s_addr) == mask.s_addr) 68781634Sbrian ncprange_setip4mask(&myrange, ipcp->ifmask); 68836285Sbrian 68981634Sbrian if (!iface_Add(bundle->iface, &bundle->ncp, &myrange, &hisncpaddr, 69081634Sbrian IFACE_ADD_FIRST|IFACE_FORCE_ADD|IFACE_SYSTEM)) 69181634Sbrian return 0; 69236285Sbrian 69381634Sbrian if (!Enabled(bundle, OPT_IFACEALIAS)) 69481634Sbrian iface_Clear(bundle->iface, &bundle->ncp, AF_INET, 69581634Sbrian IFACE_CLEAR_ALIASES|IFACE_SYSTEM); 69636285Sbrian 69781634Sbrian if (bundle->ncp.cfg.sendpipe > 0 || bundle->ncp.cfg.recvpipe > 0) { 69881739Sbrian ncprange_getsa(&myrange, &ssgw, &ssmask); 69981739Sbrian ncpaddr_getsa(&hisncpaddr, &ssdst); 700191316Sbz rt_Update(bundle, sadst, sagw, samask, NULL, NULL); 70181634Sbrian } 70240665Sbrian 70336285Sbrian if (Enabled(bundle, OPT_SROUTES)) 70481634Sbrian route_Change(bundle, bundle->ncp.route, &myncpaddr, &hisncpaddr); 70536285Sbrian 70643313Sbrian#ifndef NORADIUS 70743313Sbrian if (bundle->radius.valid) 70881634Sbrian route_Change(bundle, bundle->radius.routes, &myncpaddr, &hisncpaddr); 70943313Sbrian#endif 71043313Sbrian 71181634Sbrian return 1; /* Ok */ 7126059Samurai} 7136059Samurai 71436285Sbrianstatic struct in_addr 71540561SbrianChooseHisAddr(struct bundle *bundle, struct in_addr gw) 71636285Sbrian{ 71736285Sbrian struct in_addr try; 71837210Sbrian u_long f; 71936285Sbrian 72036285Sbrian for (f = 0; f < bundle->ncp.ipcp.cfg.peer_list.nItems; f++) { 72136285Sbrian try = iplist_next(&bundle->ncp.ipcp.cfg.peer_list); 72237210Sbrian log_Printf(LogDEBUG, "ChooseHisAddr: Check item %ld (%s)\n", 72336285Sbrian f, inet_ntoa(try)); 72481634Sbrian if (ipcp_SetIPaddress(&bundle->ncp.ipcp, gw, try)) { 72536285Sbrian log_Printf(LogIPCP, "Selected IP address %s\n", inet_ntoa(try)); 72636285Sbrian break; 72736285Sbrian } 72836285Sbrian } 72936285Sbrian 73036285Sbrian if (f == bundle->ncp.ipcp.cfg.peer_list.nItems) { 73136285Sbrian log_Printf(LogDEBUG, "ChooseHisAddr: All addresses in use !\n"); 73236285Sbrian try.s_addr = INADDR_ANY; 73336285Sbrian } 73436285Sbrian 73536285Sbrian return try; 73636285Sbrian} 73736285Sbrian 7386059Samuraistatic void 73944305SbrianIpcpInitRestartCounter(struct fsm *fp, int what) 7406059Samurai{ 74136285Sbrian /* Set fsm timer load */ 74236285Sbrian struct ipcp *ipcp = fsm2ipcp(fp); 74336285Sbrian 74444305Sbrian fp->FsmTimer.load = ipcp->cfg.fsm.timeout * SECTICKS; 74544305Sbrian switch (what) { 74644305Sbrian case FSM_REQ_TIMER: 74744305Sbrian fp->restart = ipcp->cfg.fsm.maxreq; 74844305Sbrian break; 74944305Sbrian case FSM_TRM_TIMER: 75044305Sbrian fp->restart = ipcp->cfg.fsm.maxtrm; 75144305Sbrian break; 75244305Sbrian default: 75344305Sbrian fp->restart = 1; 75444305Sbrian break; 75544305Sbrian } 7566059Samurai} 7576059Samurai 7586059Samuraistatic void 75936285SbrianIpcpSendConfigReq(struct fsm *fp) 7606059Samurai{ 76136285Sbrian /* Send config REQ please */ 76236285Sbrian struct physical *p = link2physical(fp->link); 76336285Sbrian struct ipcp *ipcp = fsm2ipcp(fp); 764139973Sbrian u_char buff[MAX_FSM_OPT_LEN]; 76594894Sbrian struct fsm_opt *o; 7666059Samurai 76794894Sbrian o = (struct fsm_opt *)buff; 76836285Sbrian 76936285Sbrian if ((p && !physical_IsSync(p)) || !REJECTED(ipcp, TY_IPADDR)) { 77038814Sbrian memcpy(o->data, &ipcp->my_ip.s_addr, 4); 77194894Sbrian INC_FSM_OPT(TY_IPADDR, 6, o); 77231514Sbrian } 77331514Sbrian 77436285Sbrian if (ipcp->my_compproto && !REJECTED(ipcp, TY_COMPPROTO)) { 77536285Sbrian if (ipcp->heis1172) { 77638814Sbrian u_int16_t proto = PROTO_VJCOMP; 77738814Sbrian 77838814Sbrian ua_htons(&proto, o->data); 77994894Sbrian INC_FSM_OPT(TY_COMPPROTO, 4, o); 78031514Sbrian } else { 78143545Sbrian struct compreq req; 78243545Sbrian 78343545Sbrian req.proto = htons(ipcp->my_compproto >> 16); 78443545Sbrian req.slots = (ipcp->my_compproto >> 8) & 255; 78543545Sbrian req.compcid = ipcp->my_compproto & 1; 78643545Sbrian memcpy(o->data, &req, 4); 78794894Sbrian INC_FSM_OPT(TY_COMPPROTO, 6, o); 78831514Sbrian } 7896059Samurai } 79036285Sbrian 79181634Sbrian if (IsEnabled(ipcp->cfg.ns.dns_neg)) { 79281634Sbrian if (!REJECTED(ipcp, TY_PRIMARY_DNS - TY_ADJUST_NS)) { 79381634Sbrian memcpy(o->data, &ipcp->ns.dns[0].s_addr, 4); 79494894Sbrian INC_FSM_OPT(TY_PRIMARY_DNS, 6, o); 79581634Sbrian } 79671356Sbrian 79781634Sbrian if (!REJECTED(ipcp, TY_SECONDARY_DNS - TY_ADJUST_NS)) { 79881634Sbrian memcpy(o->data, &ipcp->ns.dns[1].s_addr, 4); 79994894Sbrian INC_FSM_OPT(TY_SECONDARY_DNS, 6, o); 80081634Sbrian } 80136285Sbrian } 80236285Sbrian 80347695Sbrian fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff, 80447695Sbrian MB_IPCPOUT); 8056059Samurai} 8066059Samurai 8076059Samuraistatic void 808134789SbrianIpcpSentTerminateReq(struct fsm *fp __unused) 8096059Samurai{ 81036285Sbrian /* Term REQ just sent by FSM */ 8116059Samurai} 8126059Samurai 8136059Samuraistatic void 81436285SbrianIpcpSendTerminateAck(struct fsm *fp, u_char id) 8156059Samurai{ 81636285Sbrian /* Send Term ACK please */ 81747695Sbrian fsm_Output(fp, CODE_TERMACK, id, NULL, 0, MB_IPCPOUT); 8186059Samurai} 8196059Samurai 8206059Samuraistatic void 82137160SbrianIpcpLayerStart(struct fsm *fp) 8226059Samurai{ 82336285Sbrian /* We're about to start up ! */ 82437160Sbrian struct ipcp *ipcp = fsm2ipcp(fp); 82537160Sbrian 82637210Sbrian log_Printf(LogIPCP, "%s: LayerStart.\n", fp->link->name); 82737160Sbrian throughput_start(&ipcp->throughput, "IPCP throughput", 82837160Sbrian Enabled(fp->bundle, OPT_THROUGHPUT)); 82944305Sbrian fp->more.reqs = fp->more.naks = fp->more.rejs = ipcp->cfg.fsm.maxreq * 3; 83080476Sbrian ipcp->peer_req = 0; 8316059Samurai} 8326059Samurai 8336059Samuraistatic void 83436285SbrianIpcpLayerFinish(struct fsm *fp) 8356059Samurai{ 83636285Sbrian /* We're now down */ 83737160Sbrian struct ipcp *ipcp = fsm2ipcp(fp); 83837160Sbrian 83937210Sbrian log_Printf(LogIPCP, "%s: LayerFinish.\n", fp->link->name); 84037160Sbrian throughput_stop(&ipcp->throughput); 84137160Sbrian throughput_log(&ipcp->throughput, LogIPCP, NULL); 8426059Samurai} 8436059Samurai 84481634Sbrian/* 84581634Sbrian * Called from iface_Add() via ncp_IfaceAddrAdded() 84681634Sbrian */ 84736285Sbrianvoid 84881634Sbrianipcp_IfaceAddrAdded(struct ipcp *ipcp, const struct iface_addr *addr) 8496059Samurai{ 85081634Sbrian struct bundle *bundle = ipcp->fsm.bundle; 85136285Sbrian 85281634Sbrian if (Enabled(bundle, OPT_PROXY) || Enabled(bundle, OPT_PROXYALL)) 85381634Sbrian ipcp_proxyarp(ipcp, arp_SetProxy, addr); 85481634Sbrian} 85536285Sbrian 85681634Sbrian/* 85781634Sbrian * Called from iface_Clear() and iface_Delete() via ncp_IfaceAddrDeleted() 85881634Sbrian */ 85981634Sbrianvoid 86081634Sbrianipcp_IfaceAddrDeleted(struct ipcp *ipcp, const struct iface_addr *addr) 86181634Sbrian{ 86281634Sbrian struct bundle *bundle = ipcp->fsm.bundle; 86381634Sbrian 86481634Sbrian if (Enabled(bundle, OPT_PROXY) || Enabled(bundle, OPT_PROXYALL)) 86581634Sbrian ipcp_proxyarp(ipcp, arp_ClearProxy, addr); 8666059Samurai} 8676059Samurai 8686059Samuraistatic void 86936285SbrianIpcpLayerDown(struct fsm *fp) 8706059Samurai{ 87136285Sbrian /* About to come down */ 87281634Sbrian struct ipcp *ipcp = fsm2ipcp(fp); 87347835Sbrian static int recursing; 87481634Sbrian char addr[16]; 8756059Samurai 87647835Sbrian if (!recursing++) { 87781634Sbrian snprintf(addr, sizeof addr, "%s", inet_ntoa(ipcp->my_ip)); 87881634Sbrian log_Printf(LogIPCP, "%s: LayerDown: %s\n", fp->link->name, addr); 87930187Sbrian 88065178Sbrian#ifndef NORADIUS 881140905Sbrian radius_Flush(&fp->bundle->radius); 88265178Sbrian radius_Account(&fp->bundle->radius, &fp->bundle->radacct, 883116588Sume fp->bundle->links, RAD_STOP, &ipcp->throughput); 88498151Sbrian 885277857Sdim if (*fp->bundle->radius.cfg.file && fp->bundle->radius.filterid) 886132273Sbrian system_Select(fp->bundle, fp->bundle->radius.filterid, LINKDOWNFILE, 887132273Sbrian NULL, NULL); 888132273Sbrian radius_StopTimer(&fp->bundle->radius); 88965178Sbrian#endif 89065178Sbrian 89147835Sbrian /* 89247835Sbrian * XXX this stuff should really live in the FSM. Our config should 89347835Sbrian * associate executable sections in files with events. 89447835Sbrian */ 89581634Sbrian if (system_Select(fp->bundle, addr, LINKDOWNFILE, NULL, NULL) < 0) { 89647835Sbrian if (bundle_GetLabel(fp->bundle)) { 89747835Sbrian if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle), 89847835Sbrian LINKDOWNFILE, NULL, NULL) < 0) 89947835Sbrian system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL); 90047835Sbrian } else 90147835Sbrian system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL); 90247835Sbrian } 90347835Sbrian 90447835Sbrian ipcp_Setup(ipcp, INADDR_NONE); 90536285Sbrian } 90647835Sbrian recursing--; 90736285Sbrian} 90836285Sbrian 90936285Sbrianint 91036285Sbrianipcp_InterfaceUp(struct ipcp *ipcp) 91136285Sbrian{ 91281634Sbrian if (!ipcp_SetIPaddress(ipcp, ipcp->my_ip, ipcp->peer_ip)) { 91337019Sbrian log_Printf(LogERROR, "ipcp_InterfaceUp: unable to set ip address\n"); 91436285Sbrian return 0; 91525630Sbrian } 91636285Sbrian 91776492Sbrian if (!iface_SetFlags(ipcp->fsm.bundle->iface->name, IFF_UP)) { 91876492Sbrian log_Printf(LogERROR, "ipcp_InterfaceUp: Can't set the IFF_UP flag on %s\n", 91976492Sbrian ipcp->fsm.bundle->iface->name); 92076492Sbrian return 0; 92176492Sbrian } 92276492Sbrian 92350059Sbrian#ifndef NONAT 92450059Sbrian if (ipcp->fsm.bundle->NatEnabled) 925177100Spiso LibAliasSetAddress(la, ipcp->my_ip); 92631343Sbrian#endif 92736285Sbrian 92836285Sbrian return 1; 9296059Samurai} 9306059Samurai 93136285Sbrianstatic int 93236285SbrianIpcpLayerUp(struct fsm *fp) 9336059Samurai{ 93436285Sbrian /* We're now up */ 93536285Sbrian struct ipcp *ipcp = fsm2ipcp(fp); 93640561Sbrian char tbuff[16]; 9376059Samurai 93837210Sbrian log_Printf(LogIPCP, "%s: LayerUp.\n", fp->link->name); 93940561Sbrian snprintf(tbuff, sizeof tbuff, "%s", inet_ntoa(ipcp->my_ip)); 94040561Sbrian log_Printf(LogIPCP, "myaddr %s hisaddr = %s\n", 94140561Sbrian tbuff, inet_ntoa(ipcp->peer_ip)); 94236285Sbrian 94336285Sbrian if (ipcp->peer_compproto >> 16 == PROTO_VJCOMP) 94436285Sbrian sl_compress_init(&ipcp->vj.cslc, (ipcp->peer_compproto >> 8) & 255); 94536285Sbrian 94636285Sbrian if (!ipcp_InterfaceUp(ipcp)) 94736285Sbrian return 0; 94836285Sbrian 94965178Sbrian#ifndef NORADIUS 950116588Sume radius_Account_Set_Ip(&fp->bundle->radacct, &ipcp->peer_ip, &ipcp->ifmask); 95198243Sbrian radius_Account(&fp->bundle->radius, &fp->bundle->radacct, fp->bundle->links, 952116588Sume RAD_START, &ipcp->throughput); 95398151Sbrian 954277857Sdim if (*fp->bundle->radius.cfg.file && fp->bundle->radius.filterid) 95598151Sbrian system_Select(fp->bundle, fp->bundle->radius.filterid, LINKUPFILE, 95698151Sbrian NULL, NULL); 957132273Sbrian radius_StartTimer(fp->bundle); 95865178Sbrian#endif 95965178Sbrian 96036285Sbrian /* 96136285Sbrian * XXX this stuff should really live in the FSM. Our config should 96236285Sbrian * associate executable sections in files with events. 96336285Sbrian */ 96440561Sbrian if (system_Select(fp->bundle, tbuff, LINKUPFILE, NULL, NULL) < 0) { 96536285Sbrian if (bundle_GetLabel(fp->bundle)) { 96636285Sbrian if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle), 96737008Sbrian LINKUPFILE, NULL, NULL) < 0) 96837008Sbrian system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL); 96936285Sbrian } else 97037008Sbrian system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL); 97136285Sbrian } 97236285Sbrian 97344305Sbrian fp->more.reqs = fp->more.naks = fp->more.rejs = ipcp->cfg.fsm.maxreq * 3; 97436314Sbrian log_DisplayPrompts(); 97544305Sbrian 97636285Sbrian return 1; 9776059Samurai} 9786059Samurai 9796059Samuraistatic void 98076986Sbrianipcp_ValidateReq(struct ipcp *ipcp, struct in_addr ip, struct fsm_decode *dec) 98176986Sbrian{ 98276986Sbrian struct bundle *bundle = ipcp->fsm.bundle; 98376986Sbrian struct iface *iface = bundle->iface; 98481634Sbrian struct in_addr myaddr, peer; 985134789Sbrian unsigned n; 98676986Sbrian 98776986Sbrian if (iplist_isvalid(&ipcp->cfg.peer_list)) { 98881634Sbrian ncprange_getip4addr(&ipcp->cfg.my_range, &myaddr); 98976986Sbrian if (ip.s_addr == INADDR_ANY || 99076986Sbrian iplist_ip2pos(&ipcp->cfg.peer_list, ip) < 0 || 99181634Sbrian !ipcp_SetIPaddress(ipcp, myaddr, ip)) { 99276986Sbrian log_Printf(LogIPCP, "%s: Address invalid or already in use\n", 99376986Sbrian inet_ntoa(ip)); 99476986Sbrian /* 99576986Sbrian * If we've already had a valid address configured for the peer, 99676986Sbrian * try NAKing with that so that we don't have to upset things 99776986Sbrian * too much. 99876986Sbrian */ 99981634Sbrian for (n = 0; n < iface->addrs; n++) { 100081634Sbrian if (!ncpaddr_getip4(&iface->addr[n].peer, &peer)) 100181634Sbrian continue; 100281634Sbrian if (iplist_ip2pos(&ipcp->cfg.peer_list, peer) >= 0) { 100381634Sbrian ipcp->peer_ip = peer; 100476986Sbrian break; 100576986Sbrian } 100681634Sbrian } 100776986Sbrian 100881634Sbrian if (n == iface->addrs) { 100976986Sbrian /* Just pick an IP number from our list */ 101081634Sbrian ipcp->peer_ip = ChooseHisAddr(bundle, myaddr); 101181634Sbrian } 101276986Sbrian 101376986Sbrian if (ipcp->peer_ip.s_addr == INADDR_ANY) { 101476986Sbrian *dec->rejend++ = TY_IPADDR; 101576986Sbrian *dec->rejend++ = 6; 101676986Sbrian memcpy(dec->rejend, &ip.s_addr, 4); 101776986Sbrian dec->rejend += 4; 101876986Sbrian } else { 101976986Sbrian *dec->nakend++ = TY_IPADDR; 102076986Sbrian *dec->nakend++ = 6; 102176986Sbrian memcpy(dec->nakend, &ipcp->peer_ip.s_addr, 4); 102276986Sbrian dec->nakend += 4; 102376986Sbrian } 102476986Sbrian return; 102576986Sbrian } 1026103875Sbrian } else if (ip.s_addr == INADDR_ANY || 1027103875Sbrian !ncprange_containsip4(&ipcp->cfg.peer_range, ip)) { 102876986Sbrian /* 102976986Sbrian * If the destination address is not acceptable, NAK with what we 103076986Sbrian * want to use. 103176986Sbrian */ 103276986Sbrian *dec->nakend++ = TY_IPADDR; 103376986Sbrian *dec->nakend++ = 6; 103481634Sbrian for (n = 0; n < iface->addrs; n++) 103581634Sbrian if (ncprange_contains(&ipcp->cfg.peer_range, &iface->addr[n].peer)) { 103676986Sbrian /* We prefer the already-configured address */ 103781634Sbrian ncpaddr_getip4addr(&iface->addr[n].peer, (u_int32_t *)dec->nakend); 103876986Sbrian break; 103976986Sbrian } 104076986Sbrian 104181634Sbrian if (n == iface->addrs) 104276986Sbrian memcpy(dec->nakend, &ipcp->peer_ip.s_addr, 4); 104376986Sbrian 104476986Sbrian dec->nakend += 4; 104576986Sbrian return; 104676986Sbrian } 104776986Sbrian 104876986Sbrian ipcp->peer_ip = ip; 104976986Sbrian *dec->ackend++ = TY_IPADDR; 105076986Sbrian *dec->ackend++ = 6; 105176986Sbrian memcpy(dec->ackend, &ip.s_addr, 4); 105276986Sbrian dec->ackend += 4; 105376986Sbrian} 105476986Sbrian 105576986Sbrianstatic void 105694894SbrianIpcpDecodeConfig(struct fsm *fp, u_char *cp, u_char *end, int mode_type, 105736285Sbrian struct fsm_decode *dec) 10586059Samurai{ 105936285Sbrian /* Deal with incoming PROTO_IPCP */ 106081634Sbrian struct ncpaddr ncpaddr; 106136285Sbrian struct ipcp *ipcp = fsm2ipcp(fp); 106294894Sbrian int gotdnsnak; 106336285Sbrian u_int32_t compproto; 1064139973Sbrian struct compreq pcomp; 106558044Sbrian struct in_addr ipaddr, dstipaddr, have_ip; 106636285Sbrian char tbuff[100], tbuff2[100]; 106794894Sbrian struct fsm_opt *opt, nak; 10686059Samurai 106936285Sbrian gotdnsnak = 0; 10706059Samurai 1071134789Sbrian while (end - cp >= (int)sizeof(opt->hdr)) { 107294894Sbrian if ((opt = fsm_readopt(&cp)) == NULL) 107336285Sbrian break; 107436285Sbrian 107594894Sbrian snprintf(tbuff, sizeof tbuff, " %s[%d]", protoname(opt->hdr.id), 107694894Sbrian opt->hdr.len); 10776059Samurai 107894894Sbrian switch (opt->hdr.id) { 10796059Samurai case TY_IPADDR: /* RFC1332 */ 108094894Sbrian memcpy(&ipaddr.s_addr, opt->data, 4); 108136285Sbrian log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 10826059Samurai 108331034Sbrian switch (mode_type) { 10846059Samurai case MODE_REQ: 108580476Sbrian ipcp->peer_req = 1; 108676986Sbrian ipcp_ValidateReq(ipcp, ipaddr, dec); 108794894Sbrian break; 108840561Sbrian 10896059Samurai case MODE_NAK: 109081634Sbrian if (ncprange_containsip4(&ipcp->cfg.my_range, ipaddr)) { 109194894Sbrian /* Use address suggested by peer */ 109294894Sbrian snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s ", tbuff, 109394894Sbrian inet_ntoa(ipcp->my_ip)); 109494894Sbrian log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 109594894Sbrian ipcp->my_ip = ipaddr; 109681634Sbrian ncpaddr_setip4(&ncpaddr, ipcp->my_ip); 109781634Sbrian bundle_AdjustFilters(fp->bundle, &ncpaddr, NULL); 109894894Sbrian } else { 109994894Sbrian log_Printf(log_IsKept(LogIPCP) ? LogIPCP : LogPHASE, 110036285Sbrian "%s: Unacceptable address!\n", inet_ntoa(ipaddr)); 110136285Sbrian fsm_Close(&ipcp->fsm); 110294894Sbrian } 110394894Sbrian break; 110440561Sbrian 11056059Samurai case MODE_REJ: 110694894Sbrian ipcp->peer_reject |= (1 << opt->hdr.id); 110794894Sbrian break; 11086059Samurai } 11096059Samurai break; 111040561Sbrian 11116059Samurai case TY_COMPPROTO: 1112139973Sbrian memcpy(&pcomp, opt->data, sizeof pcomp); 1113139973Sbrian compproto = (ntohs(pcomp.proto) << 16) + ((int)pcomp.slots << 8) + 1114139973Sbrian pcomp.compcid; 111536285Sbrian log_Printf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto)); 11166059Samurai 111731034Sbrian switch (mode_type) { 11186059Samurai case MODE_REQ: 111994894Sbrian if (!IsAccepted(ipcp->cfg.vj.neg)) 112094894Sbrian fsm_rej(dec, opt); 112194894Sbrian else { 112294894Sbrian switch (opt->hdr.len) { 112394894Sbrian case 4: /* RFC1172 */ 1124139973Sbrian if (ntohs(pcomp.proto) == PROTO_VJCOMP) { 112594894Sbrian log_Printf(LogWARN, "Peer is speaking RFC1172 compression " 112643545Sbrian "protocol !\n"); 112794894Sbrian ipcp->heis1172 = 1; 112894894Sbrian ipcp->peer_compproto = compproto; 112994894Sbrian fsm_ack(dec, opt); 113094894Sbrian } else { 1131139973Sbrian pcomp.proto = htons(PROTO_VJCOMP); 113294894Sbrian nak.hdr.id = TY_COMPPROTO; 113394894Sbrian nak.hdr.len = 4; 113494894Sbrian memcpy(nak.data, &pcomp, 2); 113594894Sbrian fsm_nak(dec, &nak); 113694894Sbrian } 113794894Sbrian break; 113894894Sbrian case 6: /* RFC1332 */ 1139139973Sbrian if (ntohs(pcomp.proto) == PROTO_VJCOMP) { 1140139973Sbrian /* We know pcomp.slots' max value == MAX_VJ_STATES */ 1141139973Sbrian if (pcomp.slots >= MIN_VJ_STATES) { 114243545Sbrian /* Ok, we can do that */ 114394894Sbrian ipcp->peer_compproto = compproto; 114494894Sbrian ipcp->heis1172 = 0; 114594894Sbrian fsm_ack(dec, opt); 114694894Sbrian } else { 114743545Sbrian /* Get as close as we can to what he wants */ 114894894Sbrian ipcp->heis1172 = 0; 1149139973Sbrian pcomp.slots = MIN_VJ_STATES; 115094894Sbrian nak.hdr.id = TY_COMPPROTO; 115194894Sbrian nak.hdr.len = 4; 115294894Sbrian memcpy(nak.data, &pcomp, 2); 115394894Sbrian fsm_nak(dec, &nak); 115443545Sbrian } 115594894Sbrian } else { 115643545Sbrian /* What we really want */ 1157139973Sbrian pcomp.proto = htons(PROTO_VJCOMP); 1158139973Sbrian pcomp.slots = DEF_VJ_STATES; 1159139973Sbrian pcomp.compcid = 1; 116094894Sbrian nak.hdr.id = TY_COMPPROTO; 116194894Sbrian nak.hdr.len = 6; 116294894Sbrian memcpy(nak.data, &pcomp, sizeof pcomp); 116394894Sbrian fsm_nak(dec, &nak); 116494894Sbrian } 116594894Sbrian break; 116694894Sbrian default: 116794894Sbrian fsm_rej(dec, opt); 116894894Sbrian break; 116994894Sbrian } 117094894Sbrian } 117194894Sbrian break; 117240561Sbrian 11736059Samurai case MODE_NAK: 1174139973Sbrian if (ntohs(pcomp.proto) == PROTO_VJCOMP) { 1175139973Sbrian /* We know pcomp.slots' max value == MAX_VJ_STATES */ 1176139973Sbrian if (pcomp.slots < MIN_VJ_STATES) 1177139973Sbrian pcomp.slots = MIN_VJ_STATES; 1178139973Sbrian compproto = (ntohs(pcomp.proto) << 16) + (pcomp.slots << 8) + 1179139973Sbrian pcomp.compcid; 118043545Sbrian } else 118143545Sbrian compproto = 0; 118294894Sbrian log_Printf(LogIPCP, "%s changing compproto: %08x --> %08x\n", 118394894Sbrian tbuff, ipcp->my_compproto, compproto); 118443545Sbrian ipcp->my_compproto = compproto; 118594894Sbrian break; 118640561Sbrian 11876059Samurai case MODE_REJ: 118894894Sbrian ipcp->peer_reject |= (1 << opt->hdr.id); 118994894Sbrian break; 11906059Samurai } 11916059Samurai break; 119240561Sbrian 119328679Sbrian case TY_IPADDRS: /* RFC1172 */ 119494894Sbrian memcpy(&ipaddr.s_addr, opt->data, 4); 119594894Sbrian memcpy(&dstipaddr.s_addr, opt->data + 4, 4); 119631962Sbrian snprintf(tbuff2, sizeof tbuff2, "%s %s,", tbuff, inet_ntoa(ipaddr)); 119736285Sbrian log_Printf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr)); 11986059Samurai 119931034Sbrian switch (mode_type) { 12006059Samurai case MODE_REQ: 120194894Sbrian fsm_rej(dec, opt); 120294894Sbrian break; 120340561Sbrian 12046059Samurai case MODE_NAK: 12056059Samurai case MODE_REJ: 120694894Sbrian break; 12076059Samurai } 12086059Samurai break; 120918752Sjkh 121036285Sbrian case TY_PRIMARY_DNS: /* DNS negotiation (rfc1877) */ 121136285Sbrian case TY_SECONDARY_DNS: 121294894Sbrian memcpy(&ipaddr.s_addr, opt->data, 4); 121336285Sbrian log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 121418752Sjkh 121531034Sbrian switch (mode_type) { 121618752Sjkh case MODE_REQ: 121736285Sbrian if (!IsAccepted(ipcp->cfg.ns.dns_neg)) { 121894894Sbrian ipcp->my_reject |= (1 << (opt->hdr.id - TY_ADJUST_NS)); 121994894Sbrian fsm_rej(dec, opt); 122094894Sbrian break; 122136285Sbrian } 122294894Sbrian have_ip = ipcp->ns.dns[opt->hdr.id == TY_PRIMARY_DNS ? 0 : 1]; 122358044Sbrian 122494894Sbrian if (opt->hdr.id == TY_PRIMARY_DNS && ipaddr.s_addr != have_ip.s_addr && 122581634Sbrian ipaddr.s_addr == ipcp->ns.dns[1].s_addr) { 122658044Sbrian /* Swap 'em 'round */ 122781634Sbrian ipcp->ns.dns[0] = ipcp->ns.dns[1]; 122881634Sbrian ipcp->ns.dns[1] = have_ip; 122981634Sbrian have_ip = ipcp->ns.dns[0]; 123036285Sbrian } 123128679Sbrian 123294894Sbrian if (ipaddr.s_addr != have_ip.s_addr) { 123394894Sbrian /* 123494894Sbrian * The client has got the DNS stuff wrong (first request) so 123594894Sbrian * we'll tell 'em how it is 123694894Sbrian */ 123794894Sbrian nak.hdr.id = opt->hdr.id; 123894894Sbrian nak.hdr.len = 6; 123994894Sbrian memcpy(nak.data, &have_ip.s_addr, 4); 124094894Sbrian fsm_nak(dec, &nak); 124194894Sbrian } else { 124294894Sbrian /* 1243108533Sschweikh * Otherwise they have it right (this time) so we send an ack packet 124494894Sbrian * back confirming it... end of story 124594894Sbrian */ 124694894Sbrian fsm_ack(dec, opt); 124736285Sbrian } 124894894Sbrian break; 124940561Sbrian 125058044Sbrian case MODE_NAK: 125136285Sbrian if (IsEnabled(ipcp->cfg.ns.dns_neg)) { 125236285Sbrian gotdnsnak = 1; 125394894Sbrian memcpy(&ipcp->ns.dns[opt->hdr.id == TY_PRIMARY_DNS ? 0 : 1].s_addr, 125494894Sbrian opt->data, 4); 125594894Sbrian } 125694894Sbrian break; 125740561Sbrian 125836285Sbrian case MODE_REJ: /* Can't do much, stop asking */ 125994894Sbrian ipcp->peer_reject |= (1 << (opt->hdr.id - TY_ADJUST_NS)); 126094894Sbrian break; 126118752Sjkh } 126218752Sjkh break; 126318752Sjkh 126436285Sbrian case TY_PRIMARY_NBNS: /* M$ NetBIOS nameserver hack (rfc1877) */ 126518752Sjkh case TY_SECONDARY_NBNS: 126694894Sbrian memcpy(&ipaddr.s_addr, opt->data, 4); 126736285Sbrian log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 126836285Sbrian 126931034Sbrian switch (mode_type) { 127018752Sjkh case MODE_REQ: 127194894Sbrian have_ip.s_addr = 127294894Sbrian ipcp->cfg.ns.nbns[opt->hdr.id == TY_PRIMARY_NBNS ? 0 : 1].s_addr; 127336285Sbrian 127436285Sbrian if (have_ip.s_addr == INADDR_ANY) { 127594894Sbrian log_Printf(LogIPCP, "NBNS REQ - rejected - nbns not set\n"); 127694894Sbrian ipcp->my_reject |= (1 << (opt->hdr.id - TY_ADJUST_NS)); 127794894Sbrian fsm_rej(dec, opt); 127894894Sbrian break; 127936285Sbrian } 128036285Sbrian 128194894Sbrian if (ipaddr.s_addr != have_ip.s_addr) { 128294894Sbrian nak.hdr.id = opt->hdr.id; 128394894Sbrian nak.hdr.len = 6; 128494894Sbrian memcpy(nak.data, &have_ip.s_addr, 4); 128594894Sbrian fsm_nak(dec, &nak); 128694894Sbrian } else 128794894Sbrian fsm_ack(dec, opt); 128894894Sbrian break; 128940561Sbrian 129018752Sjkh case MODE_NAK: 129194894Sbrian log_Printf(LogIPCP, "MS NBNS req %d - NAK??\n", opt->hdr.id); 129294894Sbrian break; 129340561Sbrian 129418752Sjkh case MODE_REJ: 129594894Sbrian log_Printf(LogIPCP, "MS NBNS req %d - REJ??\n", opt->hdr.id); 129694894Sbrian break; 129718752Sjkh } 129818752Sjkh break; 129918752Sjkh 13006059Samurai default: 130136285Sbrian if (mode_type != MODE_NOP) { 130294894Sbrian ipcp->my_reject |= (1 << opt->hdr.id); 130394894Sbrian fsm_rej(dec, opt); 130436285Sbrian } 13056059Samurai break; 13066059Samurai } 13076059Samurai } 130836285Sbrian 130958044Sbrian if (gotdnsnak) { 131058044Sbrian if (ipcp->ns.writable) { 131158044Sbrian log_Printf(LogDEBUG, "Updating resolver\n"); 131258044Sbrian if (!ipcp_WriteDNS(ipcp)) { 131358044Sbrian ipcp->peer_reject |= (1 << (TY_PRIMARY_DNS - TY_ADJUST_NS)); 131458044Sbrian ipcp->peer_reject |= (1 << (TY_SECONDARY_DNS - TY_ADJUST_NS)); 131558044Sbrian } else 131681634Sbrian bundle_AdjustDNS(fp->bundle); 131758044Sbrian } else { 131858044Sbrian log_Printf(LogDEBUG, "Not updating resolver (readonly)\n"); 131981634Sbrian bundle_AdjustDNS(fp->bundle); 132036285Sbrian } 132158044Sbrian } 132236285Sbrian 132336285Sbrian if (mode_type != MODE_NOP) { 132480476Sbrian if (mode_type == MODE_REQ && !ipcp->peer_req) { 132580476Sbrian if (dec->rejend == dec->rej && dec->nakend == dec->nak) { 132680476Sbrian /* 132780476Sbrian * Pretend the peer has requested an IP. 132880476Sbrian * We do this to ensure that we only send one NAK if the only 132980476Sbrian * reason for the NAK is because the peer isn't sending a 133080476Sbrian * TY_IPADDR REQ. This stops us from repeatedly trying to tell 133180476Sbrian * the peer that we have to have an IP address on their end. 133280476Sbrian */ 133380476Sbrian ipcp->peer_req = 1; 133480476Sbrian } 133576986Sbrian ipaddr.s_addr = INADDR_ANY; 133676986Sbrian ipcp_ValidateReq(ipcp, ipaddr, dec); 133776986Sbrian } 133894894Sbrian fsm_opt_normalise(dec); 133936285Sbrian } 13406059Samurai} 13416059Samurai 134246686Sbrianextern struct mbuf * 134346686Sbrianipcp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 13446059Samurai{ 134536285Sbrian /* Got PROTO_IPCP from link */ 134654912Sbrian m_settype(bp, MB_IPCPIN); 134736285Sbrian if (bundle_Phase(bundle) == PHASE_NETWORK) 134846686Sbrian fsm_Input(&bundle->ncp.ipcp.fsm, bp); 134936285Sbrian else { 135036285Sbrian if (bundle_Phase(bundle) < PHASE_NETWORK) 135136285Sbrian log_Printf(LogIPCP, "%s: Error: Unexpected IPCP in phase %s (ignored)\n", 135246686Sbrian l->name, bundle_PhaseName(bundle)); 135354912Sbrian m_freem(bp); 135436285Sbrian } 135546686Sbrian return NULL; 13566059Samurai} 135732267Sbrian 135832267Sbrianint 135943313Sbrianipcp_UseHisIPaddr(struct bundle *bundle, struct in_addr hisaddr) 136043313Sbrian{ 136143313Sbrian struct ipcp *ipcp = &bundle->ncp.ipcp; 136281634Sbrian struct in_addr myaddr; 136343313Sbrian 136443313Sbrian memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 136543313Sbrian iplist_reset(&ipcp->cfg.peer_list); 136681634Sbrian ipcp->peer_ip = hisaddr; 136781634Sbrian ncprange_setip4host(&ipcp->cfg.peer_range, hisaddr); 136881634Sbrian ncprange_getip4addr(&ipcp->cfg.my_range, &myaddr); 136943313Sbrian 137081634Sbrian return ipcp_SetIPaddress(ipcp, myaddr, hisaddr); 137143313Sbrian} 137243313Sbrian 137343313Sbrianint 137436285Sbrianipcp_UseHisaddr(struct bundle *bundle, const char *hisaddr, int setaddr) 137532267Sbrian{ 137681634Sbrian struct in_addr myaddr; 137781634Sbrian struct ncp *ncp = &bundle->ncp; 137881634Sbrian struct ipcp *ipcp = &ncp->ipcp; 137981634Sbrian struct ncpaddr ncpaddr; 138036285Sbrian 138136285Sbrian /* Use `hisaddr' for the peers address (set iface if `setaddr') */ 138236285Sbrian memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 138336285Sbrian iplist_reset(&ipcp->cfg.peer_list); 138432267Sbrian if (strpbrk(hisaddr, ",-")) { 138536285Sbrian iplist_setsrc(&ipcp->cfg.peer_list, hisaddr); 138636285Sbrian if (iplist_isvalid(&ipcp->cfg.peer_list)) { 138736285Sbrian iplist_setrandpos(&ipcp->cfg.peer_list); 138836285Sbrian ipcp->peer_ip = ChooseHisAddr(bundle, ipcp->my_ip); 138936285Sbrian if (ipcp->peer_ip.s_addr == INADDR_ANY) { 139036285Sbrian log_Printf(LogWARN, "%s: None available !\n", ipcp->cfg.peer_list.src); 139147648Sbrian return 0; 139232267Sbrian } 139381634Sbrian ncprange_setip4host(&ipcp->cfg.peer_range, ipcp->peer_ip); 139432267Sbrian } else { 139536285Sbrian log_Printf(LogWARN, "%s: Invalid range !\n", hisaddr); 139632267Sbrian return 0; 139732267Sbrian } 139881634Sbrian } else if (ncprange_aton(&ipcp->cfg.peer_range, ncp, hisaddr) != 0) { 139981634Sbrian if (ncprange_family(&ipcp->cfg.my_range) != AF_INET) { 140081634Sbrian log_Printf(LogWARN, "%s: Not an AF_INET address !\n", hisaddr); 140181634Sbrian return 0; 140281634Sbrian } 140381634Sbrian ncprange_getip4addr(&ipcp->cfg.my_range, &myaddr); 140481634Sbrian ncprange_getip4addr(&ipcp->cfg.peer_range, &ipcp->peer_ip); 140532267Sbrian 140681634Sbrian if (setaddr && !ipcp_SetIPaddress(ipcp, myaddr, ipcp->peer_ip)) 140732267Sbrian return 0; 140832267Sbrian } else 140932267Sbrian return 0; 141032267Sbrian 141181634Sbrian ncpaddr_setip4(&ncpaddr, ipcp->peer_ip); 141281634Sbrian bundle_AdjustFilters(bundle, NULL, &ncpaddr); 141347648Sbrian 141447648Sbrian return 1; /* Ok */ 141532267Sbrian} 141644455Sbrian 141744455Sbrianstruct in_addr 141844455Sbrianaddr2mask(struct in_addr addr) 141944455Sbrian{ 142044455Sbrian u_int32_t haddr = ntohl(addr.s_addr); 142144455Sbrian 142244455Sbrian haddr = IN_CLASSA(haddr) ? IN_CLASSA_NET : 142344455Sbrian IN_CLASSB(haddr) ? IN_CLASSB_NET : 142444455Sbrian IN_CLASSC_NET; 142544455Sbrian addr.s_addr = htonl(haddr); 142644455Sbrian 142744455Sbrian return addr; 142844455Sbrian} 142981634Sbrian 143081634Sbriansize_t 143181634Sbrianipcp_QueueLen(struct ipcp *ipcp) 143281634Sbrian{ 143381634Sbrian struct mqueue *q; 143481634Sbrian size_t result; 143581634Sbrian 143681634Sbrian result = 0; 143781634Sbrian for (q = ipcp->Queue; q < ipcp->Queue + IPCP_QUEUES(ipcp); q++) 143881634Sbrian result += q->len; 143981634Sbrian 144081634Sbrian return result; 144181634Sbrian} 144281634Sbrian 144381634Sbrianint 144481634Sbrianipcp_PushPacket(struct ipcp *ipcp, struct link *l) 144581634Sbrian{ 144681634Sbrian struct bundle *bundle = ipcp->fsm.bundle; 144781634Sbrian struct mqueue *queue; 144881634Sbrian struct mbuf *bp; 144981634Sbrian int m_len; 145081634Sbrian u_int32_t secs = 0; 145181634Sbrian unsigned alivesecs = 0; 145281634Sbrian 145381634Sbrian if (ipcp->fsm.state != ST_OPENED) 145481634Sbrian return 0; 145581634Sbrian 145681634Sbrian /* 145781634Sbrian * If ccp is not open but is required, do nothing. 145881634Sbrian */ 145981634Sbrian if (l->ccp.fsm.state != ST_OPENED && ccp_Required(&l->ccp)) { 146081634Sbrian log_Printf(LogPHASE, "%s: Not transmitting... waiting for CCP\n", l->name); 146181634Sbrian return 0; 146281634Sbrian } 146381634Sbrian 146481634Sbrian queue = ipcp->Queue + IPCP_QUEUES(ipcp) - 1; 146581634Sbrian do { 146681634Sbrian if (queue->top) { 146781634Sbrian bp = m_dequeue(queue); 146881634Sbrian bp = mbuf_Read(bp, &secs, sizeof secs); 146981634Sbrian bp = m_pullup(bp); 147081634Sbrian m_len = m_length(bp); 147181634Sbrian if (!FilterCheck(MBUF_CTOP(bp), AF_INET, &bundle->filter.alive, 147281634Sbrian &alivesecs)) { 147381634Sbrian if (secs == 0) 147481634Sbrian secs = alivesecs; 147581634Sbrian bundle_StartIdleTimer(bundle, secs); 147681634Sbrian } 147781634Sbrian link_PushPacket(l, bp, bundle, 0, PROTO_IP); 147881634Sbrian ipcp_AddOutOctets(ipcp, m_len); 147981634Sbrian return 1; 148081634Sbrian } 148181634Sbrian } while (queue-- != ipcp->Queue); 148281634Sbrian 148381634Sbrian return 0; 148481634Sbrian} 1485