178189Sbrian/*- 278189Sbrian * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org> 378189Sbrian * based on work by Toshiharu OHNO <tony-o@iij.ad.jp> 478189Sbrian * Internet Initiative Japan, Inc (IIJ) 578189Sbrian * All rights reserved. 66059Samurai * 778189Sbrian * Redistribution and use in source and binary forms, with or without 878189Sbrian * modification, are permitted provided that the following conditions 978189Sbrian * are met: 1078189Sbrian * 1. Redistributions of source code must retain the above copyright 1178189Sbrian * notice, this list of conditions and the following disclaimer. 1278189Sbrian * 2. Redistributions in binary form must reproduce the above copyright 1378189Sbrian * notice, this list of conditions and the following disclaimer in the 1478189Sbrian * documentation and/or other materials provided with the distribution. 156059Samurai * 1678189Sbrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1778189Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1878189Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1978189Sbrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2078189Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2178189Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2278189Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2378189Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2478189Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2578189Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2678189Sbrian * SUCH DAMAGE. 276059Samurai * 2850479Speter * $FreeBSD: releng/11.0/usr.sbin/ppp/ipcp.c 277857 2015-01-28 21:33:49Z dim $ 296059Samurai */ 3078189Sbrian 3130715Sbrian#include <sys/param.h> 326059Samurai#include <netinet/in_systm.h> 3329048Sbrian#include <netinet/in.h> 346059Samurai#include <netinet/ip.h> 356059Samurai#include <arpa/inet.h> 366059Samurai#include <sys/socket.h> 3776492Sbrian#include <net/if.h> 3840665Sbrian#include <net/route.h> 3930715Sbrian#include <netdb.h> 4036285Sbrian#include <sys/un.h> 4130715Sbrian 4246085Sbrian#include <errno.h> 4336285Sbrian#include <fcntl.h> 4436285Sbrian#include <resolv.h> 45102500Sbrian#include <stdarg.h> 4632614Sbrian#include <stdlib.h> 4730715Sbrian#include <string.h> 4858044Sbrian#include <sys/stat.h> 4936285Sbrian#include <termios.h> 5030715Sbrian#include <unistd.h> 5130715Sbrian 5250059Sbrian#ifndef NONAT 5358037Sbrian#ifdef LOCALNAT 5458037Sbrian#include "alias.h" 5558037Sbrian#else 5646086Sbrian#include <alias.h> 5739395Sbrian#endif 5839395Sbrian#endif 5958037Sbrian 6046686Sbrian#include "layer.h" 6138814Sbrian#include "ua.h" 6237009Sbrian#include "defs.h" 6331343Sbrian#include "command.h" 6430715Sbrian#include "mbuf.h" 6530715Sbrian#include "log.h" 6630715Sbrian#include "timer.h" 6729048Sbrian#include "fsm.h" 6846686Sbrian#include "proto.h" 6931690Sbrian#include "iplist.h" 7036285Sbrian#include "throughput.h" 7136285Sbrian#include "slcompress.h" 7238557Sbrian#include "lqr.h" 7338557Sbrian#include "hdlc.h" 7463484Sbrian#include "lcp.h" 7581634Sbrian#include "ncpaddr.h" 7681634Sbrian#include "ip.h" 7729048Sbrian#include "ipcp.h" 7836285Sbrian#include "filter.h" 7936285Sbrian#include "descriptor.h" 8030715Sbrian#include "vjcomp.h" 8136285Sbrian#include "async.h" 8236285Sbrian#include "ccp.h" 8336285Sbrian#include "link.h" 8436285Sbrian#include "physical.h" 8536285Sbrian#include "mp.h" 8643313Sbrian#ifndef NORADIUS 8743313Sbrian#include "radius.h" 8843313Sbrian#endif 8981634Sbrian#include "ipv6cp.h" 9081634Sbrian#include "ncp.h" 9136285Sbrian#include "bundle.h" 9236285Sbrian#include "id.h" 9336285Sbrian#include "arp.h" 9436285Sbrian#include "systems.h" 9536285Sbrian#include "prompt.h" 9631690Sbrian#include "route.h" 9740561Sbrian#include "iface.h" 986059Samurai 9936285Sbrian#undef REJECTED 10036285Sbrian#define REJECTED(p, x) ((p)->peer_reject & (1<<(x))) 10136285Sbrian#define issep(ch) ((ch) == ' ' || (ch) == '\t') 10236285Sbrian#define isip(ch) (((ch) >= '0' && (ch) <= '9') || (ch) == '.') 1036059Samurai 10436285Sbrianstruct compreq { 10536285Sbrian u_short proto; 10636285Sbrian u_char slots; 10736285Sbrian u_char compcid; 10836285Sbrian}; 1096059Samurai 11036285Sbrianstatic int IpcpLayerUp(struct fsm *); 11136285Sbrianstatic void IpcpLayerDown(struct fsm *); 11226516Sbrianstatic void IpcpLayerStart(struct fsm *); 11326516Sbrianstatic void IpcpLayerFinish(struct fsm *); 11444305Sbrianstatic void IpcpInitRestartCounter(struct fsm *, int); 11536285Sbrianstatic void IpcpSendConfigReq(struct fsm *); 11636285Sbrianstatic void IpcpSentTerminateReq(struct fsm *); 11736285Sbrianstatic void IpcpSendTerminateAck(struct fsm *, u_char); 11894894Sbrianstatic void IpcpDecodeConfig(struct fsm *, u_char *, u_char *, int, 11936285Sbrian struct fsm_decode *); 1206059Samurai 121177100Spisoextern struct libalias *la; 122177100Spiso 12336285Sbrianstatic struct fsm_callbacks ipcp_Callbacks = { 1246059Samurai IpcpLayerUp, 1256059Samurai IpcpLayerDown, 1266059Samurai IpcpLayerStart, 1276059Samurai IpcpLayerFinish, 1286059Samurai IpcpInitRestartCounter, 1296059Samurai IpcpSendConfigReq, 13036285Sbrian IpcpSentTerminateReq, 1316059Samurai IpcpSendTerminateAck, 1326059Samurai IpcpDecodeConfig, 13336285Sbrian fsm_NullRecvResetReq, 13436285Sbrian fsm_NullRecvResetAck 1356059Samurai}; 1366059Samurai 13758034Sbrianstatic const char * 13858034Sbrianprotoname(int proto) 13958034Sbrian{ 14058034Sbrian static struct { 14158034Sbrian int id; 14258034Sbrian const char *txt; 14358034Sbrian } cftypes[] = { 14458034Sbrian /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */ 14558034Sbrian { 1, "IPADDRS" }, /* IP-Addresses */ /* deprecated */ 14658034Sbrian { 2, "COMPPROTO" }, /* IP-Compression-Protocol */ 14758034Sbrian { 3, "IPADDR" }, /* IP-Address */ 14858034Sbrian { 129, "PRIDNS" }, /* 129: Primary DNS Server Address */ 14958034Sbrian { 130, "PRINBNS" }, /* 130: Primary NBNS Server Address */ 15058034Sbrian { 131, "SECDNS" }, /* 131: Secondary DNS Server Address */ 15158034Sbrian { 132, "SECNBNS" } /* 132: Secondary NBNS Server Address */ 15258034Sbrian }; 153134789Sbrian unsigned f; 1546059Samurai 15558034Sbrian for (f = 0; f < sizeof cftypes / sizeof *cftypes; f++) 15658034Sbrian if (cftypes[f].id == proto) 15758034Sbrian return cftypes[f].txt; 15831171Sbrian 15958034Sbrian return NumStr(proto, NULL, 0); 16058034Sbrian} 16131171Sbrian 16231272Sbrianvoid 16336285Sbrianipcp_AddInOctets(struct ipcp *ipcp, int n) 1646059Samurai{ 16536285Sbrian throughput_addin(&ipcp->throughput, n); 1666059Samurai} 1676059Samurai 16831272Sbrianvoid 16936285Sbrianipcp_AddOutOctets(struct ipcp *ipcp, int n) 1706059Samurai{ 17136285Sbrian throughput_addout(&ipcp->throughput, n); 1726059Samurai} 1736059Samurai 17458044Sbrianvoid 17558044Sbrianipcp_LoadDNS(struct ipcp *ipcp) 1766059Samurai{ 17758044Sbrian int fd; 1786059Samurai 17958044Sbrian ipcp->ns.dns[0].s_addr = ipcp->ns.dns[1].s_addr = INADDR_NONE; 18036285Sbrian 18158044Sbrian if (ipcp->ns.resolv != NULL) { 18258044Sbrian free(ipcp->ns.resolv); 18358044Sbrian ipcp->ns.resolv = NULL; 18432614Sbrian } 18558044Sbrian if (ipcp->ns.resolv_nons != NULL) { 18658044Sbrian free(ipcp->ns.resolv_nons); 18758044Sbrian ipcp->ns.resolv_nons = NULL; 18858044Sbrian } 18958044Sbrian ipcp->ns.resolver = 0; 19029048Sbrian 19158044Sbrian if ((fd = open(_PATH_RESCONF, O_RDONLY)) != -1) { 19258044Sbrian struct stat st; 19326516Sbrian 19458044Sbrian if (fstat(fd, &st) == 0) { 19558044Sbrian ssize_t got; 19631272Sbrian 197139973Sbrian /* 198139973Sbrian * Note, ns.resolv and ns.resolv_nons are assumed to always point to 199139973Sbrian * buffers of the same size! See the strcpy() below. 200139973Sbrian */ 20158044Sbrian if ((ipcp->ns.resolv_nons = (char *)malloc(st.st_size + 1)) == NULL) 20258044Sbrian log_Printf(LogERROR, "Failed to malloc %lu for %s: %s\n", 20358044Sbrian (unsigned long)st.st_size, _PATH_RESCONF, strerror(errno)); 20458044Sbrian else if ((ipcp->ns.resolv = (char *)malloc(st.st_size + 1)) == NULL) { 20558044Sbrian log_Printf(LogERROR, "Failed(2) to malloc %lu for %s: %s\n", 20658044Sbrian (unsigned long)st.st_size, _PATH_RESCONF, strerror(errno)); 20758044Sbrian free(ipcp->ns.resolv_nons); 20858044Sbrian ipcp->ns.resolv_nons = NULL; 20958044Sbrian } else if ((got = read(fd, ipcp->ns.resolv, st.st_size)) != st.st_size) { 21058044Sbrian if (got == -1) 21158044Sbrian log_Printf(LogERROR, "Failed to read %s: %s\n", 21258044Sbrian _PATH_RESCONF, strerror(errno)); 21358044Sbrian else 21458044Sbrian log_Printf(LogERROR, "Failed to read %s, got %lu not %lu\n", 21558044Sbrian _PATH_RESCONF, (unsigned long)got, 21658044Sbrian (unsigned long)st.st_size); 21758044Sbrian free(ipcp->ns.resolv_nons); 21858044Sbrian ipcp->ns.resolv_nons = NULL; 21958044Sbrian free(ipcp->ns.resolv); 22058044Sbrian ipcp->ns.resolv = NULL; 22158044Sbrian } else { 22258044Sbrian char *cp, *cp_nons, *ncp, ch; 22358044Sbrian int n; 22436285Sbrian 22558044Sbrian ipcp->ns.resolv[st.st_size] = '\0'; 22658044Sbrian ipcp->ns.resolver = 1; 22736285Sbrian 22858044Sbrian cp_nons = ipcp->ns.resolv_nons; 22958044Sbrian cp = ipcp->ns.resolv; 23058044Sbrian n = 0; 23136285Sbrian 23258044Sbrian while ((ncp = strstr(cp, "nameserver")) != NULL) { 23358044Sbrian if (ncp != cp) { 23458044Sbrian memcpy(cp_nons, cp, ncp - cp); 23558044Sbrian cp_nons += ncp - cp; 23658044Sbrian } 23758044Sbrian if ((ncp != cp && ncp[-1] != '\n') || !issep(ncp[10])) { 23858044Sbrian memcpy(cp_nons, ncp, 9); 23958044Sbrian cp_nons += 9; 24058044Sbrian cp = ncp + 9; /* Can't match "nameserver" at cp... */ 24158044Sbrian continue; 24258044Sbrian } 24358044Sbrian 24458044Sbrian for (cp = ncp + 11; issep(*cp); cp++) /* Skip whitespace */ 24558044Sbrian ; 24658044Sbrian 24758044Sbrian for (ncp = cp; isip(*ncp); ncp++) /* Jump over IP */ 24858044Sbrian ; 24958044Sbrian 25058044Sbrian ch = *ncp; 25158044Sbrian *ncp = '\0'; 25281634Sbrian if (n < 2 && inet_aton(cp, ipcp->ns.dns)) 25358044Sbrian n++; 25458044Sbrian *ncp = ch; 25558044Sbrian 25658044Sbrian if ((cp = strchr(ncp, '\n')) == NULL) /* Point at next line */ 25758044Sbrian cp = ncp + strlen(ncp); 25858044Sbrian else 25958044Sbrian cp++; 26036285Sbrian } 261139973Sbrian /* 262139973Sbrian * Note, cp_nons and cp always point to buffers of the same size, so 263139973Sbrian * strcpy is ok! 264139973Sbrian */ 26558044Sbrian strcpy(cp_nons, cp); /* Copy the end - including the NUL */ 26658044Sbrian cp_nons += strlen(cp_nons) - 1; 26758044Sbrian while (cp_nons >= ipcp->ns.resolv_nons && *cp_nons == '\n') 26858044Sbrian *cp_nons-- = '\0'; 26958044Sbrian if (n == 2 && ipcp->ns.dns[0].s_addr == INADDR_ANY) { 27058044Sbrian ipcp->ns.dns[0].s_addr = ipcp->ns.dns[1].s_addr; 27158044Sbrian ipcp->ns.dns[1].s_addr = INADDR_ANY; 27258044Sbrian } 27381634Sbrian bundle_AdjustDNS(ipcp->fsm.bundle); 27436285Sbrian } 27558044Sbrian } else 27658044Sbrian log_Printf(LogERROR, "Failed to stat opened %s: %s\n", 27758044Sbrian _PATH_RESCONF, strerror(errno)); 27858044Sbrian 27958044Sbrian close(fd); 28036285Sbrian } 28158044Sbrian} 28236285Sbrian 28358044Sbrianint 28458044Sbrianipcp_WriteDNS(struct ipcp *ipcp) 28558044Sbrian{ 28658044Sbrian const char *paddr; 28758044Sbrian mode_t mask; 28858044Sbrian FILE *fp; 28958044Sbrian 29058044Sbrian if (ipcp->ns.dns[0].s_addr == INADDR_ANY && 29158044Sbrian ipcp->ns.dns[1].s_addr == INADDR_ANY) { 29258044Sbrian log_Printf(LogIPCP, "%s not modified: All nameservers NAKd\n", 29358044Sbrian _PATH_RESCONF); 29458044Sbrian return 0; 29536285Sbrian } 29636285Sbrian 29758044Sbrian if (ipcp->ns.dns[0].s_addr == INADDR_ANY) { 29858044Sbrian ipcp->ns.dns[0].s_addr = ipcp->ns.dns[1].s_addr; 29958044Sbrian ipcp->ns.dns[1].s_addr = INADDR_ANY; 30036285Sbrian } 30136285Sbrian 30260839Sbrian mask = umask(022); 30358044Sbrian if ((fp = ID0fopen(_PATH_RESCONF, "w")) != NULL) { 30458044Sbrian umask(mask); 30560922Sbrian if (ipcp->ns.resolv_nons) 30660839Sbrian fputs(ipcp->ns.resolv_nons, fp); 30758044Sbrian paddr = inet_ntoa(ipcp->ns.dns[0]); 30858044Sbrian log_Printf(LogIPCP, "Primary nameserver set to %s\n", paddr); 30958044Sbrian fprintf(fp, "\nnameserver %s\n", paddr); 31058044Sbrian if (ipcp->ns.dns[1].s_addr != INADDR_ANY && 31158044Sbrian ipcp->ns.dns[1].s_addr != INADDR_NONE && 31258044Sbrian ipcp->ns.dns[1].s_addr != ipcp->ns.dns[0].s_addr) { 31358044Sbrian paddr = inet_ntoa(ipcp->ns.dns[1]); 31458044Sbrian log_Printf(LogIPCP, "Secondary nameserver set to %s\n", paddr); 31558044Sbrian fprintf(fp, "nameserver %s\n", paddr); 31658044Sbrian } 31758044Sbrian if (fclose(fp) == EOF) { 31858044Sbrian log_Printf(LogERROR, "write(): Failed updating %s: %s\n", _PATH_RESCONF, 31958044Sbrian strerror(errno)); 32036285Sbrian return 0; 32136285Sbrian } 322214011Sglebius } else { 32358044Sbrian umask(mask); 324214011Sglebius log_Printf(LogERROR,"fopen(\"%s\", \"w\") failed: %s\n", _PATH_RESCONF, 325214011Sglebius strerror(errno)); 326214011Sglebius } 32736285Sbrian 32836285Sbrian return 1; 3296059Samurai} 3306059Samurai 33158044Sbrianvoid 33258044Sbrianipcp_RestoreDNS(struct ipcp *ipcp) 33358044Sbrian{ 33458044Sbrian if (ipcp->ns.resolver) { 335134789Sbrian ssize_t got, len; 33658044Sbrian int fd; 33758044Sbrian 33858044Sbrian if ((fd = ID0open(_PATH_RESCONF, O_WRONLY|O_TRUNC, 0644)) != -1) { 33958044Sbrian len = strlen(ipcp->ns.resolv); 34058044Sbrian if ((got = write(fd, ipcp->ns.resolv, len)) != len) { 34158044Sbrian if (got == -1) 34258044Sbrian log_Printf(LogERROR, "Failed rewriting %s: write: %s\n", 34358044Sbrian _PATH_RESCONF, strerror(errno)); 34458044Sbrian else 345134789Sbrian log_Printf(LogERROR, "Failed rewriting %s: wrote %ld of %ld\n", 346134789Sbrian _PATH_RESCONF, (long)got, (long)len); 34758044Sbrian } 34858044Sbrian close(fd); 34958044Sbrian } else 35058044Sbrian log_Printf(LogERROR, "Failed rewriting %s: open: %s\n", _PATH_RESCONF, 35158044Sbrian strerror(errno)); 35258044Sbrian } else if (remove(_PATH_RESCONF) == -1) 35358044Sbrian log_Printf(LogERROR, "Failed removing %s: %s\n", _PATH_RESCONF, 35458044Sbrian strerror(errno)); 35598243Sbrian 35658044Sbrian} 35758044Sbrian 35836285Sbrianint 35936285Sbrianipcp_Show(struct cmdargs const *arg) 3606059Samurai{ 36136285Sbrian struct ipcp *ipcp = &arg->bundle->ncp.ipcp; 3626059Samurai 36336285Sbrian prompt_Printf(arg->prompt, "%s [%s]\n", ipcp->fsm.name, 36436285Sbrian State2Nam(ipcp->fsm.state)); 36536285Sbrian if (ipcp->fsm.state == ST_OPENED) { 36636285Sbrian prompt_Printf(arg->prompt, " His side: %s, %s\n", 36794894Sbrian inet_ntoa(ipcp->peer_ip), vj2asc(ipcp->peer_compproto)); 36836285Sbrian prompt_Printf(arg->prompt, " My side: %s, %s\n", 36994894Sbrian inet_ntoa(ipcp->my_ip), vj2asc(ipcp->my_compproto)); 37058042Sbrian prompt_Printf(arg->prompt, " Queued packets: %lu\n", 37181634Sbrian (unsigned long)ipcp_QueueLen(ipcp)); 3726059Samurai } 37336285Sbrian 37436285Sbrian prompt_Printf(arg->prompt, "\nDefaults:\n"); 37544305Sbrian prompt_Printf(arg->prompt, " FSM retry = %us, max %u Config" 37644305Sbrian " REQ%s, %u Term REQ%s\n", ipcp->cfg.fsm.timeout, 37744305Sbrian ipcp->cfg.fsm.maxreq, ipcp->cfg.fsm.maxreq == 1 ? "" : "s", 37844305Sbrian ipcp->cfg.fsm.maxtrm, ipcp->cfg.fsm.maxtrm == 1 ? "" : "s"); 37981634Sbrian prompt_Printf(arg->prompt, " My Address: %s\n", 38094894Sbrian ncprange_ntoa(&ipcp->cfg.my_range)); 38136285Sbrian if (ipcp->cfg.HaveTriggerAddress) 38244455Sbrian prompt_Printf(arg->prompt, " Trigger address: %s\n", 38336285Sbrian inet_ntoa(ipcp->cfg.TriggerAddress)); 38444455Sbrian 38544455Sbrian prompt_Printf(arg->prompt, " VJ compression: %s (%d slots %s slot " 38636285Sbrian "compression)\n", command_ShowNegval(ipcp->cfg.vj.neg), 38736285Sbrian ipcp->cfg.vj.slots, ipcp->cfg.vj.slotcomp ? "with" : "without"); 38836285Sbrian 38936285Sbrian if (iplist_isvalid(&ipcp->cfg.peer_list)) 39036285Sbrian prompt_Printf(arg->prompt, " His Address: %s\n", 39136285Sbrian ipcp->cfg.peer_list.src); 39236285Sbrian else 39381634Sbrian prompt_Printf(arg->prompt, " His Address: %s\n", 39494894Sbrian ncprange_ntoa(&ipcp->cfg.peer_range)); 39536285Sbrian 39658044Sbrian prompt_Printf(arg->prompt, " DNS: %s", 39758044Sbrian ipcp->cfg.ns.dns[0].s_addr == INADDR_NONE ? 39858044Sbrian "none" : inet_ntoa(ipcp->cfg.ns.dns[0])); 39958044Sbrian if (ipcp->cfg.ns.dns[1].s_addr != INADDR_NONE) 40081634Sbrian prompt_Printf(arg->prompt, ", %s", 40181634Sbrian inet_ntoa(ipcp->cfg.ns.dns[1])); 40258044Sbrian prompt_Printf(arg->prompt, ", %s\n", 40336285Sbrian command_ShowNegval(ipcp->cfg.ns.dns_neg)); 40458044Sbrian prompt_Printf(arg->prompt, " Resolver DNS: %s", 40558044Sbrian ipcp->ns.dns[0].s_addr == INADDR_NONE ? 40658044Sbrian "none" : inet_ntoa(ipcp->ns.dns[0])); 40758044Sbrian if (ipcp->ns.dns[1].s_addr != INADDR_NONE && 40858044Sbrian ipcp->ns.dns[1].s_addr != ipcp->ns.dns[0].s_addr) 40981634Sbrian prompt_Printf(arg->prompt, ", %s", 41081634Sbrian inet_ntoa(ipcp->ns.dns[1])); 41158044Sbrian prompt_Printf(arg->prompt, "\n NetBIOS NS: %s, ", 41294894Sbrian inet_ntoa(ipcp->cfg.ns.nbns[0])); 41381693Sbrian prompt_Printf(arg->prompt, "%s\n\n", 41481634Sbrian inet_ntoa(ipcp->cfg.ns.nbns[1])); 41536285Sbrian 41636285Sbrian throughput_disp(&ipcp->throughput, arg->prompt); 41736285Sbrian 41836285Sbrian return 0; 4196059Samurai} 4206059Samurai 42132614Sbrianint 42236285Sbrianipcp_vjset(struct cmdargs const *arg) 42332614Sbrian{ 42436285Sbrian if (arg->argc != arg->argn+2) 42532614Sbrian return -1; 42636285Sbrian if (!strcasecmp(arg->argv[arg->argn], "slots")) { 42732614Sbrian int slots; 42832614Sbrian 42936285Sbrian slots = atoi(arg->argv[arg->argn+1]); 43032614Sbrian if (slots < 4 || slots > 16) 43132614Sbrian return 1; 43236285Sbrian arg->bundle->ncp.ipcp.cfg.vj.slots = slots; 43332614Sbrian return 0; 43436285Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "slotcomp")) { 43536285Sbrian if (!strcasecmp(arg->argv[arg->argn+1], "on")) 43636285Sbrian arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 1; 43736285Sbrian else if (!strcasecmp(arg->argv[arg->argn+1], "off")) 43836285Sbrian arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 0; 43932614Sbrian else 44032614Sbrian return 2; 44132614Sbrian return 0; 44232614Sbrian } 44332614Sbrian return -1; 44432614Sbrian} 44532614Sbrian 44636285Sbrianvoid 44736285Sbrianipcp_Init(struct ipcp *ipcp, struct bundle *bundle, struct link *l, 44836285Sbrian const struct fsm_parent *parent) 44932614Sbrian{ 45036285Sbrian struct hostent *hp; 45181634Sbrian struct in_addr host; 45274049Sbrian char name[MAXHOSTNAMELEN]; 45355146Sbrian static const char * const timer_names[] = 45436285Sbrian {"IPCP restart", "IPCP openmode", "IPCP stopped"}; 45536285Sbrian 45644305Sbrian fsm_Init(&ipcp->fsm, "IPCP", PROTO_IPCP, 1, IPCP_MAXCODE, LogIPCP, 45736285Sbrian bundle, l, parent, &ipcp_Callbacks, timer_names); 45836285Sbrian 45936285Sbrian ipcp->cfg.vj.slots = DEF_VJ_STATES; 46036285Sbrian ipcp->cfg.vj.slotcomp = 1; 46136285Sbrian memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range); 46281634Sbrian 46381634Sbrian host.s_addr = htonl(INADDR_LOOPBACK); 46481634Sbrian ipcp->cfg.netmask.s_addr = INADDR_ANY; 46536285Sbrian if (gethostname(name, sizeof name) == 0) { 46636285Sbrian hp = gethostbyname(name); 46781634Sbrian if (hp && hp->h_addrtype == AF_INET && hp->h_length == sizeof host.s_addr) 46881634Sbrian memcpy(&host.s_addr, hp->h_addr, sizeof host.s_addr); 46932614Sbrian } 47081634Sbrian ncprange_setip4(&ipcp->cfg.my_range, host, ipcp->cfg.netmask); 47181634Sbrian ncprange_setip4(&ipcp->cfg.peer_range, ipcp->cfg.netmask, ipcp->cfg.netmask); 47281634Sbrian 47336285Sbrian iplist_setsrc(&ipcp->cfg.peer_list, ""); 47436285Sbrian ipcp->cfg.HaveTriggerAddress = 0; 47536285Sbrian 47658044Sbrian ipcp->cfg.ns.dns[0].s_addr = INADDR_NONE; 47758044Sbrian ipcp->cfg.ns.dns[1].s_addr = INADDR_NONE; 47836285Sbrian ipcp->cfg.ns.dns_neg = 0; 47936285Sbrian ipcp->cfg.ns.nbns[0].s_addr = INADDR_ANY; 48036285Sbrian ipcp->cfg.ns.nbns[1].s_addr = INADDR_ANY; 48136285Sbrian 48244305Sbrian ipcp->cfg.fsm.timeout = DEF_FSMRETRY; 48344305Sbrian ipcp->cfg.fsm.maxreq = DEF_FSMTRIES; 48444305Sbrian ipcp->cfg.fsm.maxtrm = DEF_FSMTRIES; 48536285Sbrian ipcp->cfg.vj.neg = NEG_ENABLED|NEG_ACCEPTED; 48636285Sbrian 48736285Sbrian memset(&ipcp->vj, '\0', sizeof ipcp->vj); 48836285Sbrian 48958044Sbrian ipcp->ns.resolv = NULL; 49058044Sbrian ipcp->ns.resolv_nons = NULL; 49158044Sbrian ipcp->ns.writable = 1; 49258044Sbrian ipcp_LoadDNS(ipcp); 49358044Sbrian 49449434Sbrian throughput_init(&ipcp->throughput, SAMPLE_PERIOD); 49538557Sbrian memset(ipcp->Queue, '\0', sizeof ipcp->Queue); 49643313Sbrian ipcp_Setup(ipcp, INADDR_NONE); 49732614Sbrian} 49832614Sbrian 4996059Samuraivoid 50050867Sbrianipcp_Destroy(struct ipcp *ipcp) 50150867Sbrian{ 50281634Sbrian throughput_destroy(&ipcp->throughput); 50381634Sbrian 50458044Sbrian if (ipcp->ns.resolv != NULL) { 50558044Sbrian free(ipcp->ns.resolv); 50658044Sbrian ipcp->ns.resolv = NULL; 50758044Sbrian } 50858044Sbrian if (ipcp->ns.resolv_nons != NULL) { 50958044Sbrian free(ipcp->ns.resolv_nons); 51058044Sbrian ipcp->ns.resolv_nons = NULL; 51158044Sbrian } 51250867Sbrian} 51350867Sbrian 51450867Sbrianvoid 51536285Sbrianipcp_SetLink(struct ipcp *ipcp, struct link *l) 5166059Samurai{ 51736285Sbrian ipcp->fsm.link = l; 51836285Sbrian} 51936285Sbrian 52036285Sbrianvoid 52143313Sbrianipcp_Setup(struct ipcp *ipcp, u_int32_t mask) 52236285Sbrian{ 52340561Sbrian struct iface *iface = ipcp->fsm.bundle->iface; 52481634Sbrian struct ncpaddr ipaddr; 52581634Sbrian struct in_addr peer; 526134789Sbrian int pos; 527134789Sbrian unsigned n; 52836285Sbrian 52936285Sbrian ipcp->fsm.open_mode = 0; 53043313Sbrian ipcp->ifmask.s_addr = mask == INADDR_NONE ? ipcp->cfg.netmask.s_addr : mask; 53136285Sbrian 53236285Sbrian if (iplist_isvalid(&ipcp->cfg.peer_list)) { 53340561Sbrian /* Try to give the peer a previously configured IP address */ 53481634Sbrian for (n = 0; n < iface->addrs; n++) { 53581634Sbrian if (!ncpaddr_getip4(&iface->addr[n].peer, &peer)) 53681634Sbrian continue; 53781634Sbrian if ((pos = iplist_ip2pos(&ipcp->cfg.peer_list, peer)) != -1) { 53881634Sbrian ncpaddr_setip4(&ipaddr, iplist_setcurpos(&ipcp->cfg.peer_list, pos)); 53940561Sbrian break; 54040561Sbrian } 54140561Sbrian } 54281634Sbrian if (n == iface->addrs) 54340561Sbrian /* Ok, so none of 'em fit.... pick a random one */ 54481634Sbrian ncpaddr_setip4(&ipaddr, iplist_setrandpos(&ipcp->cfg.peer_list)); 54540561Sbrian 54681634Sbrian ncprange_sethost(&ipcp->cfg.peer_range, &ipaddr); 5476059Samurai } 5489440Samurai 54936285Sbrian ipcp->heis1172 = 0; 55080476Sbrian ipcp->peer_req = 0; 55181634Sbrian ncprange_getip4addr(&ipcp->cfg.peer_range, &ipcp->peer_ip); 55236285Sbrian ipcp->peer_compproto = 0; 55336285Sbrian 55436285Sbrian if (ipcp->cfg.HaveTriggerAddress) { 55536285Sbrian /* 55636285Sbrian * Some implementations of PPP require that we send a 55736285Sbrian * *special* value as our address, even though the rfc specifies 55836285Sbrian * full negotiation (e.g. "0.0.0.0" or Not "0.0.0.0"). 55936285Sbrian */ 56036285Sbrian ipcp->my_ip = ipcp->cfg.TriggerAddress; 56136285Sbrian log_Printf(LogIPCP, "Using trigger address %s\n", 56236285Sbrian inet_ntoa(ipcp->cfg.TriggerAddress)); 56340561Sbrian } else { 56436285Sbrian /* 56540561Sbrian * Otherwise, if we've used an IP number before and it's still within 56640561Sbrian * the network specified on the ``set ifaddr'' line, we really 56740561Sbrian * want to keep that IP number so that we can keep any existing 56881634Sbrian * connections that are bound to that IP. 56936285Sbrian */ 57081634Sbrian for (n = 0; n < iface->addrs; n++) { 57181634Sbrian ncprange_getaddr(&iface->addr[n].ifa, &ipaddr); 57281634Sbrian if (ncprange_contains(&ipcp->cfg.my_range, &ipaddr)) { 57381634Sbrian ncpaddr_getip4(&ipaddr, &ipcp->my_ip); 57440561Sbrian break; 57540561Sbrian } 57681634Sbrian } 57781634Sbrian if (n == iface->addrs) 57881634Sbrian ncprange_getip4addr(&ipcp->cfg.my_range, &ipcp->my_ip); 57940561Sbrian } 58036285Sbrian 58143313Sbrian if (IsEnabled(ipcp->cfg.vj.neg) 58243313Sbrian#ifndef NORADIUS 58343313Sbrian || (ipcp->fsm.bundle->radius.valid && ipcp->fsm.bundle->radius.vj) 58443313Sbrian#endif 58543313Sbrian ) 58636285Sbrian ipcp->my_compproto = (PROTO_VJCOMP << 16) + 58736285Sbrian ((ipcp->cfg.vj.slots - 1) << 8) + 58836285Sbrian ipcp->cfg.vj.slotcomp; 58936285Sbrian else 59036285Sbrian ipcp->my_compproto = 0; 59136285Sbrian sl_compress_init(&ipcp->vj.cslc, ipcp->cfg.vj.slots - 1); 59236285Sbrian 59336285Sbrian ipcp->peer_reject = 0; 59436285Sbrian ipcp->my_reject = 0; 59558044Sbrian 59681634Sbrian /* Copy startup values into ipcp->ns.dns */ 59758044Sbrian if (ipcp->cfg.ns.dns[0].s_addr != INADDR_NONE) 59881634Sbrian memcpy(ipcp->ns.dns, ipcp->cfg.ns.dns, sizeof ipcp->ns.dns); 59981634Sbrian} 60058044Sbrian 60181634Sbrianstatic int 60281634Sbriannumaddresses(struct in_addr mask) 60381634Sbrian{ 60481634Sbrian u_int32_t bit, haddr; 60581634Sbrian int n; 60681634Sbrian 60781634Sbrian haddr = ntohl(mask.s_addr); 60881634Sbrian bit = 1; 60981634Sbrian n = 1; 61081634Sbrian 61181634Sbrian do { 61281634Sbrian if (!(haddr & bit)) 61381634Sbrian n <<= 1; 61481634Sbrian } while (bit <<= 1); 61581634Sbrian 61681634Sbrian return n; 61736285Sbrian} 61836285Sbrian 61936285Sbrianstatic int 62081634Sbrianipcp_proxyarp(struct ipcp *ipcp, 621134789Sbrian int (*proxyfun)(struct bundle *, struct in_addr), 62281634Sbrian const struct iface_addr *addr) 62340665Sbrian{ 62481634Sbrian struct bundle *bundle = ipcp->fsm.bundle; 62581634Sbrian struct in_addr peer, mask, ip; 626134789Sbrian int n, ret; 62740665Sbrian 62881634Sbrian if (!ncpaddr_getip4(&addr->peer, &peer)) { 62981634Sbrian log_Printf(LogERROR, "Oops, ipcp_proxyarp() called with unexpected addr\n"); 63081634Sbrian return 0; 63181634Sbrian } 63281634Sbrian 63381634Sbrian ret = 0; 63481634Sbrian 63581634Sbrian if (Enabled(bundle, OPT_PROXYALL)) { 63681634Sbrian ncprange_getip4mask(&addr->ifa, &mask); 63781634Sbrian if ((n = numaddresses(mask)) > 256) { 63881634Sbrian log_Printf(LogWARN, "%s: Too many addresses for proxyall\n", 63981634Sbrian ncprange_ntoa(&addr->ifa)); 64081634Sbrian return 0; 64181634Sbrian } 64281634Sbrian ip.s_addr = peer.s_addr & mask.s_addr; 64381634Sbrian if (n >= 4) { 64481634Sbrian ip.s_addr = htonl(ntohl(ip.s_addr) + 1); 64581634Sbrian n -= 2; 64681634Sbrian } 64781634Sbrian while (n) { 64881634Sbrian if (!((ip.s_addr ^ peer.s_addr) & mask.s_addr)) { 649134789Sbrian if (!(ret = (*proxyfun)(bundle, ip))) 65081634Sbrian break; 65181634Sbrian n--; 65240665Sbrian } 65381634Sbrian ip.s_addr = htonl(ntohl(ip.s_addr) + 1); 65440665Sbrian } 65581634Sbrian ret = !n; 65681634Sbrian } else if (Enabled(bundle, OPT_PROXY)) 657134789Sbrian ret = (*proxyfun)(bundle, peer); 65840665Sbrian 65981634Sbrian return ret; 66040665Sbrian} 66140665Sbrian 66240665Sbrianstatic int 66381634Sbrianipcp_SetIPaddress(struct ipcp *ipcp, struct in_addr myaddr, 66481634Sbrian struct in_addr hisaddr) 66536285Sbrian{ 66681634Sbrian struct bundle *bundle = ipcp->fsm.bundle; 66781634Sbrian struct ncpaddr myncpaddr, hisncpaddr; 66881739Sbrian struct ncprange myrange; 66981634Sbrian struct in_addr mask; 67081739Sbrian struct sockaddr_storage ssdst, ssgw, ssmask; 67181739Sbrian struct sockaddr *sadst, *sagw, *samask; 67236285Sbrian 67381739Sbrian sadst = (struct sockaddr *)&ssdst; 67481739Sbrian sagw = (struct sockaddr *)&ssgw; 67581739Sbrian samask = (struct sockaddr *)&ssmask; 67681739Sbrian 67781634Sbrian ncpaddr_setip4(&hisncpaddr, hisaddr); 67881634Sbrian ncpaddr_setip4(&myncpaddr, myaddr); 67981634Sbrian ncprange_sethost(&myrange, &myncpaddr); 68081634Sbrian 68144455Sbrian mask = addr2mask(myaddr); 68236285Sbrian 68381634Sbrian if (ipcp->ifmask.s_addr != INADDR_ANY && 68481634Sbrian (ipcp->ifmask.s_addr & mask.s_addr) == mask.s_addr) 68581634Sbrian ncprange_setip4mask(&myrange, ipcp->ifmask); 68636285Sbrian 68781634Sbrian if (!iface_Add(bundle->iface, &bundle->ncp, &myrange, &hisncpaddr, 68881634Sbrian IFACE_ADD_FIRST|IFACE_FORCE_ADD|IFACE_SYSTEM)) 68981634Sbrian return 0; 69036285Sbrian 69181634Sbrian if (!Enabled(bundle, OPT_IFACEALIAS)) 69281634Sbrian iface_Clear(bundle->iface, &bundle->ncp, AF_INET, 69381634Sbrian IFACE_CLEAR_ALIASES|IFACE_SYSTEM); 69436285Sbrian 69581634Sbrian if (bundle->ncp.cfg.sendpipe > 0 || bundle->ncp.cfg.recvpipe > 0) { 69681739Sbrian ncprange_getsa(&myrange, &ssgw, &ssmask); 69781739Sbrian ncpaddr_getsa(&hisncpaddr, &ssdst); 698191316Sbz rt_Update(bundle, sadst, sagw, samask, NULL, NULL); 69981634Sbrian } 70040665Sbrian 70136285Sbrian if (Enabled(bundle, OPT_SROUTES)) 70281634Sbrian route_Change(bundle, bundle->ncp.route, &myncpaddr, &hisncpaddr); 70336285Sbrian 70443313Sbrian#ifndef NORADIUS 70543313Sbrian if (bundle->radius.valid) 70681634Sbrian route_Change(bundle, bundle->radius.routes, &myncpaddr, &hisncpaddr); 70743313Sbrian#endif 70843313Sbrian 70981634Sbrian return 1; /* Ok */ 7106059Samurai} 7116059Samurai 71236285Sbrianstatic struct in_addr 71340561SbrianChooseHisAddr(struct bundle *bundle, struct in_addr gw) 71436285Sbrian{ 71536285Sbrian struct in_addr try; 71637210Sbrian u_long f; 71736285Sbrian 71836285Sbrian for (f = 0; f < bundle->ncp.ipcp.cfg.peer_list.nItems; f++) { 71936285Sbrian try = iplist_next(&bundle->ncp.ipcp.cfg.peer_list); 72037210Sbrian log_Printf(LogDEBUG, "ChooseHisAddr: Check item %ld (%s)\n", 72136285Sbrian f, inet_ntoa(try)); 72281634Sbrian if (ipcp_SetIPaddress(&bundle->ncp.ipcp, gw, try)) { 72336285Sbrian log_Printf(LogIPCP, "Selected IP address %s\n", inet_ntoa(try)); 72436285Sbrian break; 72536285Sbrian } 72636285Sbrian } 72736285Sbrian 72836285Sbrian if (f == bundle->ncp.ipcp.cfg.peer_list.nItems) { 72936285Sbrian log_Printf(LogDEBUG, "ChooseHisAddr: All addresses in use !\n"); 73036285Sbrian try.s_addr = INADDR_ANY; 73136285Sbrian } 73236285Sbrian 73336285Sbrian return try; 73436285Sbrian} 73536285Sbrian 7366059Samuraistatic void 73744305SbrianIpcpInitRestartCounter(struct fsm *fp, int what) 7386059Samurai{ 73936285Sbrian /* Set fsm timer load */ 74036285Sbrian struct ipcp *ipcp = fsm2ipcp(fp); 74136285Sbrian 74244305Sbrian fp->FsmTimer.load = ipcp->cfg.fsm.timeout * SECTICKS; 74344305Sbrian switch (what) { 74444305Sbrian case FSM_REQ_TIMER: 74544305Sbrian fp->restart = ipcp->cfg.fsm.maxreq; 74644305Sbrian break; 74744305Sbrian case FSM_TRM_TIMER: 74844305Sbrian fp->restart = ipcp->cfg.fsm.maxtrm; 74944305Sbrian break; 75044305Sbrian default: 75144305Sbrian fp->restart = 1; 75244305Sbrian break; 75344305Sbrian } 7546059Samurai} 7556059Samurai 7566059Samuraistatic void 75736285SbrianIpcpSendConfigReq(struct fsm *fp) 7586059Samurai{ 75936285Sbrian /* Send config REQ please */ 76036285Sbrian struct physical *p = link2physical(fp->link); 76136285Sbrian struct ipcp *ipcp = fsm2ipcp(fp); 762139973Sbrian u_char buff[MAX_FSM_OPT_LEN]; 76394894Sbrian struct fsm_opt *o; 7646059Samurai 76594894Sbrian o = (struct fsm_opt *)buff; 76636285Sbrian 76736285Sbrian if ((p && !physical_IsSync(p)) || !REJECTED(ipcp, TY_IPADDR)) { 76838814Sbrian memcpy(o->data, &ipcp->my_ip.s_addr, 4); 76994894Sbrian INC_FSM_OPT(TY_IPADDR, 6, o); 77031514Sbrian } 77131514Sbrian 77236285Sbrian if (ipcp->my_compproto && !REJECTED(ipcp, TY_COMPPROTO)) { 77336285Sbrian if (ipcp->heis1172) { 77438814Sbrian u_int16_t proto = PROTO_VJCOMP; 77538814Sbrian 77638814Sbrian ua_htons(&proto, o->data); 77794894Sbrian INC_FSM_OPT(TY_COMPPROTO, 4, o); 77831514Sbrian } else { 77943545Sbrian struct compreq req; 78043545Sbrian 78143545Sbrian req.proto = htons(ipcp->my_compproto >> 16); 78243545Sbrian req.slots = (ipcp->my_compproto >> 8) & 255; 78343545Sbrian req.compcid = ipcp->my_compproto & 1; 78443545Sbrian memcpy(o->data, &req, 4); 78594894Sbrian INC_FSM_OPT(TY_COMPPROTO, 6, o); 78631514Sbrian } 7876059Samurai } 78836285Sbrian 78981634Sbrian if (IsEnabled(ipcp->cfg.ns.dns_neg)) { 79081634Sbrian if (!REJECTED(ipcp, TY_PRIMARY_DNS - TY_ADJUST_NS)) { 79181634Sbrian memcpy(o->data, &ipcp->ns.dns[0].s_addr, 4); 79294894Sbrian INC_FSM_OPT(TY_PRIMARY_DNS, 6, o); 79381634Sbrian } 79471356Sbrian 79581634Sbrian if (!REJECTED(ipcp, TY_SECONDARY_DNS - TY_ADJUST_NS)) { 79681634Sbrian memcpy(o->data, &ipcp->ns.dns[1].s_addr, 4); 79794894Sbrian INC_FSM_OPT(TY_SECONDARY_DNS, 6, o); 79881634Sbrian } 79936285Sbrian } 80036285Sbrian 80147695Sbrian fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff, 80247695Sbrian MB_IPCPOUT); 8036059Samurai} 8046059Samurai 8056059Samuraistatic void 806134789SbrianIpcpSentTerminateReq(struct fsm *fp __unused) 8076059Samurai{ 80836285Sbrian /* Term REQ just sent by FSM */ 8096059Samurai} 8106059Samurai 8116059Samuraistatic void 81236285SbrianIpcpSendTerminateAck(struct fsm *fp, u_char id) 8136059Samurai{ 81436285Sbrian /* Send Term ACK please */ 81547695Sbrian fsm_Output(fp, CODE_TERMACK, id, NULL, 0, MB_IPCPOUT); 8166059Samurai} 8176059Samurai 8186059Samuraistatic void 81937160SbrianIpcpLayerStart(struct fsm *fp) 8206059Samurai{ 82136285Sbrian /* We're about to start up ! */ 82237160Sbrian struct ipcp *ipcp = fsm2ipcp(fp); 82337160Sbrian 82437210Sbrian log_Printf(LogIPCP, "%s: LayerStart.\n", fp->link->name); 82537160Sbrian throughput_start(&ipcp->throughput, "IPCP throughput", 82637160Sbrian Enabled(fp->bundle, OPT_THROUGHPUT)); 82744305Sbrian fp->more.reqs = fp->more.naks = fp->more.rejs = ipcp->cfg.fsm.maxreq * 3; 82880476Sbrian ipcp->peer_req = 0; 8296059Samurai} 8306059Samurai 8316059Samuraistatic void 83236285SbrianIpcpLayerFinish(struct fsm *fp) 8336059Samurai{ 83436285Sbrian /* We're now down */ 83537160Sbrian struct ipcp *ipcp = fsm2ipcp(fp); 83637160Sbrian 83737210Sbrian log_Printf(LogIPCP, "%s: LayerFinish.\n", fp->link->name); 83837160Sbrian throughput_stop(&ipcp->throughput); 83937160Sbrian throughput_log(&ipcp->throughput, LogIPCP, NULL); 8406059Samurai} 8416059Samurai 84281634Sbrian/* 84381634Sbrian * Called from iface_Add() via ncp_IfaceAddrAdded() 84481634Sbrian */ 84536285Sbrianvoid 84681634Sbrianipcp_IfaceAddrAdded(struct ipcp *ipcp, const struct iface_addr *addr) 8476059Samurai{ 84881634Sbrian struct bundle *bundle = ipcp->fsm.bundle; 84936285Sbrian 85081634Sbrian if (Enabled(bundle, OPT_PROXY) || Enabled(bundle, OPT_PROXYALL)) 85181634Sbrian ipcp_proxyarp(ipcp, arp_SetProxy, addr); 85281634Sbrian} 85336285Sbrian 85481634Sbrian/* 85581634Sbrian * Called from iface_Clear() and iface_Delete() via ncp_IfaceAddrDeleted() 85681634Sbrian */ 85781634Sbrianvoid 85881634Sbrianipcp_IfaceAddrDeleted(struct ipcp *ipcp, const struct iface_addr *addr) 85981634Sbrian{ 86081634Sbrian struct bundle *bundle = ipcp->fsm.bundle; 86181634Sbrian 86281634Sbrian if (Enabled(bundle, OPT_PROXY) || Enabled(bundle, OPT_PROXYALL)) 86381634Sbrian ipcp_proxyarp(ipcp, arp_ClearProxy, addr); 8646059Samurai} 8656059Samurai 8666059Samuraistatic void 86736285SbrianIpcpLayerDown(struct fsm *fp) 8686059Samurai{ 86936285Sbrian /* About to come down */ 87081634Sbrian struct ipcp *ipcp = fsm2ipcp(fp); 87147835Sbrian static int recursing; 87281634Sbrian char addr[16]; 8736059Samurai 87447835Sbrian if (!recursing++) { 87581634Sbrian snprintf(addr, sizeof addr, "%s", inet_ntoa(ipcp->my_ip)); 87681634Sbrian log_Printf(LogIPCP, "%s: LayerDown: %s\n", fp->link->name, addr); 87730187Sbrian 87865178Sbrian#ifndef NORADIUS 879140905Sbrian radius_Flush(&fp->bundle->radius); 88065178Sbrian radius_Account(&fp->bundle->radius, &fp->bundle->radacct, 881116588Sume fp->bundle->links, RAD_STOP, &ipcp->throughput); 88298151Sbrian 883277857Sdim if (*fp->bundle->radius.cfg.file && fp->bundle->radius.filterid) 884132273Sbrian system_Select(fp->bundle, fp->bundle->radius.filterid, LINKDOWNFILE, 885132273Sbrian NULL, NULL); 886132273Sbrian radius_StopTimer(&fp->bundle->radius); 88765178Sbrian#endif 88865178Sbrian 88947835Sbrian /* 89047835Sbrian * XXX this stuff should really live in the FSM. Our config should 89147835Sbrian * associate executable sections in files with events. 89247835Sbrian */ 89381634Sbrian if (system_Select(fp->bundle, addr, LINKDOWNFILE, NULL, NULL) < 0) { 89447835Sbrian if (bundle_GetLabel(fp->bundle)) { 89547835Sbrian if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle), 89647835Sbrian LINKDOWNFILE, NULL, NULL) < 0) 89747835Sbrian system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL); 89847835Sbrian } else 89947835Sbrian system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL); 90047835Sbrian } 90147835Sbrian 90247835Sbrian ipcp_Setup(ipcp, INADDR_NONE); 90336285Sbrian } 90447835Sbrian recursing--; 90536285Sbrian} 90636285Sbrian 90736285Sbrianint 90836285Sbrianipcp_InterfaceUp(struct ipcp *ipcp) 90936285Sbrian{ 91081634Sbrian if (!ipcp_SetIPaddress(ipcp, ipcp->my_ip, ipcp->peer_ip)) { 91137019Sbrian log_Printf(LogERROR, "ipcp_InterfaceUp: unable to set ip address\n"); 91236285Sbrian return 0; 91325630Sbrian } 91436285Sbrian 91576492Sbrian if (!iface_SetFlags(ipcp->fsm.bundle->iface->name, IFF_UP)) { 91676492Sbrian log_Printf(LogERROR, "ipcp_InterfaceUp: Can't set the IFF_UP flag on %s\n", 91776492Sbrian ipcp->fsm.bundle->iface->name); 91876492Sbrian return 0; 91976492Sbrian } 92076492Sbrian 92150059Sbrian#ifndef NONAT 92250059Sbrian if (ipcp->fsm.bundle->NatEnabled) 923177100Spiso LibAliasSetAddress(la, ipcp->my_ip); 92431343Sbrian#endif 92536285Sbrian 92636285Sbrian return 1; 9276059Samurai} 9286059Samurai 92936285Sbrianstatic int 93036285SbrianIpcpLayerUp(struct fsm *fp) 9316059Samurai{ 93236285Sbrian /* We're now up */ 93336285Sbrian struct ipcp *ipcp = fsm2ipcp(fp); 93440561Sbrian char tbuff[16]; 9356059Samurai 93637210Sbrian log_Printf(LogIPCP, "%s: LayerUp.\n", fp->link->name); 93740561Sbrian snprintf(tbuff, sizeof tbuff, "%s", inet_ntoa(ipcp->my_ip)); 93840561Sbrian log_Printf(LogIPCP, "myaddr %s hisaddr = %s\n", 93940561Sbrian tbuff, inet_ntoa(ipcp->peer_ip)); 94036285Sbrian 94136285Sbrian if (ipcp->peer_compproto >> 16 == PROTO_VJCOMP) 94236285Sbrian sl_compress_init(&ipcp->vj.cslc, (ipcp->peer_compproto >> 8) & 255); 94336285Sbrian 94436285Sbrian if (!ipcp_InterfaceUp(ipcp)) 94536285Sbrian return 0; 94636285Sbrian 94765178Sbrian#ifndef NORADIUS 948116588Sume radius_Account_Set_Ip(&fp->bundle->radacct, &ipcp->peer_ip, &ipcp->ifmask); 94998243Sbrian radius_Account(&fp->bundle->radius, &fp->bundle->radacct, fp->bundle->links, 950116588Sume RAD_START, &ipcp->throughput); 95198151Sbrian 952277857Sdim if (*fp->bundle->radius.cfg.file && fp->bundle->radius.filterid) 95398151Sbrian system_Select(fp->bundle, fp->bundle->radius.filterid, LINKUPFILE, 95498151Sbrian NULL, NULL); 955132273Sbrian radius_StartTimer(fp->bundle); 95665178Sbrian#endif 95765178Sbrian 95836285Sbrian /* 95936285Sbrian * XXX this stuff should really live in the FSM. Our config should 96036285Sbrian * associate executable sections in files with events. 96136285Sbrian */ 96240561Sbrian if (system_Select(fp->bundle, tbuff, LINKUPFILE, NULL, NULL) < 0) { 96336285Sbrian if (bundle_GetLabel(fp->bundle)) { 96436285Sbrian if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle), 96537008Sbrian LINKUPFILE, NULL, NULL) < 0) 96637008Sbrian system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL); 96736285Sbrian } else 96837008Sbrian system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL); 96936285Sbrian } 97036285Sbrian 97144305Sbrian fp->more.reqs = fp->more.naks = fp->more.rejs = ipcp->cfg.fsm.maxreq * 3; 97236314Sbrian log_DisplayPrompts(); 97344305Sbrian 97436285Sbrian return 1; 9756059Samurai} 9766059Samurai 9776059Samuraistatic void 97876986Sbrianipcp_ValidateReq(struct ipcp *ipcp, struct in_addr ip, struct fsm_decode *dec) 97976986Sbrian{ 98076986Sbrian struct bundle *bundle = ipcp->fsm.bundle; 98176986Sbrian struct iface *iface = bundle->iface; 98281634Sbrian struct in_addr myaddr, peer; 983134789Sbrian unsigned n; 98476986Sbrian 98576986Sbrian if (iplist_isvalid(&ipcp->cfg.peer_list)) { 98681634Sbrian ncprange_getip4addr(&ipcp->cfg.my_range, &myaddr); 98776986Sbrian if (ip.s_addr == INADDR_ANY || 98876986Sbrian iplist_ip2pos(&ipcp->cfg.peer_list, ip) < 0 || 98981634Sbrian !ipcp_SetIPaddress(ipcp, myaddr, ip)) { 99076986Sbrian log_Printf(LogIPCP, "%s: Address invalid or already in use\n", 99176986Sbrian inet_ntoa(ip)); 99276986Sbrian /* 99376986Sbrian * If we've already had a valid address configured for the peer, 99476986Sbrian * try NAKing with that so that we don't have to upset things 99576986Sbrian * too much. 99676986Sbrian */ 99781634Sbrian for (n = 0; n < iface->addrs; n++) { 99881634Sbrian if (!ncpaddr_getip4(&iface->addr[n].peer, &peer)) 99981634Sbrian continue; 100081634Sbrian if (iplist_ip2pos(&ipcp->cfg.peer_list, peer) >= 0) { 100181634Sbrian ipcp->peer_ip = peer; 100276986Sbrian break; 100376986Sbrian } 100481634Sbrian } 100576986Sbrian 100681634Sbrian if (n == iface->addrs) { 100776986Sbrian /* Just pick an IP number from our list */ 100881634Sbrian ipcp->peer_ip = ChooseHisAddr(bundle, myaddr); 100981634Sbrian } 101076986Sbrian 101176986Sbrian if (ipcp->peer_ip.s_addr == INADDR_ANY) { 101276986Sbrian *dec->rejend++ = TY_IPADDR; 101376986Sbrian *dec->rejend++ = 6; 101476986Sbrian memcpy(dec->rejend, &ip.s_addr, 4); 101576986Sbrian dec->rejend += 4; 101676986Sbrian } else { 101776986Sbrian *dec->nakend++ = TY_IPADDR; 101876986Sbrian *dec->nakend++ = 6; 101976986Sbrian memcpy(dec->nakend, &ipcp->peer_ip.s_addr, 4); 102076986Sbrian dec->nakend += 4; 102176986Sbrian } 102276986Sbrian return; 102376986Sbrian } 1024103875Sbrian } else if (ip.s_addr == INADDR_ANY || 1025103875Sbrian !ncprange_containsip4(&ipcp->cfg.peer_range, ip)) { 102676986Sbrian /* 102776986Sbrian * If the destination address is not acceptable, NAK with what we 102876986Sbrian * want to use. 102976986Sbrian */ 103076986Sbrian *dec->nakend++ = TY_IPADDR; 103176986Sbrian *dec->nakend++ = 6; 103281634Sbrian for (n = 0; n < iface->addrs; n++) 103381634Sbrian if (ncprange_contains(&ipcp->cfg.peer_range, &iface->addr[n].peer)) { 103476986Sbrian /* We prefer the already-configured address */ 103581634Sbrian ncpaddr_getip4addr(&iface->addr[n].peer, (u_int32_t *)dec->nakend); 103676986Sbrian break; 103776986Sbrian } 103876986Sbrian 103981634Sbrian if (n == iface->addrs) 104076986Sbrian memcpy(dec->nakend, &ipcp->peer_ip.s_addr, 4); 104176986Sbrian 104276986Sbrian dec->nakend += 4; 104376986Sbrian return; 104476986Sbrian } 104576986Sbrian 104676986Sbrian ipcp->peer_ip = ip; 104776986Sbrian *dec->ackend++ = TY_IPADDR; 104876986Sbrian *dec->ackend++ = 6; 104976986Sbrian memcpy(dec->ackend, &ip.s_addr, 4); 105076986Sbrian dec->ackend += 4; 105176986Sbrian} 105276986Sbrian 105376986Sbrianstatic void 105494894SbrianIpcpDecodeConfig(struct fsm *fp, u_char *cp, u_char *end, int mode_type, 105536285Sbrian struct fsm_decode *dec) 10566059Samurai{ 105736285Sbrian /* Deal with incoming PROTO_IPCP */ 105881634Sbrian struct ncpaddr ncpaddr; 105936285Sbrian struct ipcp *ipcp = fsm2ipcp(fp); 106094894Sbrian int gotdnsnak; 106136285Sbrian u_int32_t compproto; 1062139973Sbrian struct compreq pcomp; 106358044Sbrian struct in_addr ipaddr, dstipaddr, have_ip; 106436285Sbrian char tbuff[100], tbuff2[100]; 106594894Sbrian struct fsm_opt *opt, nak; 10666059Samurai 106736285Sbrian gotdnsnak = 0; 10686059Samurai 1069134789Sbrian while (end - cp >= (int)sizeof(opt->hdr)) { 107094894Sbrian if ((opt = fsm_readopt(&cp)) == NULL) 107136285Sbrian break; 107236285Sbrian 107394894Sbrian snprintf(tbuff, sizeof tbuff, " %s[%d]", protoname(opt->hdr.id), 107494894Sbrian opt->hdr.len); 10756059Samurai 107694894Sbrian switch (opt->hdr.id) { 10776059Samurai case TY_IPADDR: /* RFC1332 */ 107894894Sbrian memcpy(&ipaddr.s_addr, opt->data, 4); 107936285Sbrian log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 10806059Samurai 108131034Sbrian switch (mode_type) { 10826059Samurai case MODE_REQ: 108380476Sbrian ipcp->peer_req = 1; 108476986Sbrian ipcp_ValidateReq(ipcp, ipaddr, dec); 108594894Sbrian break; 108640561Sbrian 10876059Samurai case MODE_NAK: 108881634Sbrian if (ncprange_containsip4(&ipcp->cfg.my_range, ipaddr)) { 108994894Sbrian /* Use address suggested by peer */ 109094894Sbrian snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s ", tbuff, 109194894Sbrian inet_ntoa(ipcp->my_ip)); 109294894Sbrian log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 109394894Sbrian ipcp->my_ip = ipaddr; 109481634Sbrian ncpaddr_setip4(&ncpaddr, ipcp->my_ip); 109581634Sbrian bundle_AdjustFilters(fp->bundle, &ncpaddr, NULL); 109694894Sbrian } else { 109794894Sbrian log_Printf(log_IsKept(LogIPCP) ? LogIPCP : LogPHASE, 109836285Sbrian "%s: Unacceptable address!\n", inet_ntoa(ipaddr)); 109936285Sbrian fsm_Close(&ipcp->fsm); 110094894Sbrian } 110194894Sbrian break; 110240561Sbrian 11036059Samurai case MODE_REJ: 110494894Sbrian ipcp->peer_reject |= (1 << opt->hdr.id); 110594894Sbrian break; 11066059Samurai } 11076059Samurai break; 110840561Sbrian 11096059Samurai case TY_COMPPROTO: 1110139973Sbrian memcpy(&pcomp, opt->data, sizeof pcomp); 1111139973Sbrian compproto = (ntohs(pcomp.proto) << 16) + ((int)pcomp.slots << 8) + 1112139973Sbrian pcomp.compcid; 111336285Sbrian log_Printf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto)); 11146059Samurai 111531034Sbrian switch (mode_type) { 11166059Samurai case MODE_REQ: 111794894Sbrian if (!IsAccepted(ipcp->cfg.vj.neg)) 111894894Sbrian fsm_rej(dec, opt); 111994894Sbrian else { 112094894Sbrian switch (opt->hdr.len) { 112194894Sbrian case 4: /* RFC1172 */ 1122139973Sbrian if (ntohs(pcomp.proto) == PROTO_VJCOMP) { 112394894Sbrian log_Printf(LogWARN, "Peer is speaking RFC1172 compression " 112443545Sbrian "protocol !\n"); 112594894Sbrian ipcp->heis1172 = 1; 112694894Sbrian ipcp->peer_compproto = compproto; 112794894Sbrian fsm_ack(dec, opt); 112894894Sbrian } else { 1129139973Sbrian pcomp.proto = htons(PROTO_VJCOMP); 113094894Sbrian nak.hdr.id = TY_COMPPROTO; 113194894Sbrian nak.hdr.len = 4; 113294894Sbrian memcpy(nak.data, &pcomp, 2); 113394894Sbrian fsm_nak(dec, &nak); 113494894Sbrian } 113594894Sbrian break; 113694894Sbrian case 6: /* RFC1332 */ 1137139973Sbrian if (ntohs(pcomp.proto) == PROTO_VJCOMP) { 1138139973Sbrian /* We know pcomp.slots' max value == MAX_VJ_STATES */ 1139139973Sbrian if (pcomp.slots >= MIN_VJ_STATES) { 114043545Sbrian /* Ok, we can do that */ 114194894Sbrian ipcp->peer_compproto = compproto; 114294894Sbrian ipcp->heis1172 = 0; 114394894Sbrian fsm_ack(dec, opt); 114494894Sbrian } else { 114543545Sbrian /* Get as close as we can to what he wants */ 114694894Sbrian ipcp->heis1172 = 0; 1147139973Sbrian pcomp.slots = MIN_VJ_STATES; 114894894Sbrian nak.hdr.id = TY_COMPPROTO; 114994894Sbrian nak.hdr.len = 4; 115094894Sbrian memcpy(nak.data, &pcomp, 2); 115194894Sbrian fsm_nak(dec, &nak); 115243545Sbrian } 115394894Sbrian } else { 115443545Sbrian /* What we really want */ 1155139973Sbrian pcomp.proto = htons(PROTO_VJCOMP); 1156139973Sbrian pcomp.slots = DEF_VJ_STATES; 1157139973Sbrian pcomp.compcid = 1; 115894894Sbrian nak.hdr.id = TY_COMPPROTO; 115994894Sbrian nak.hdr.len = 6; 116094894Sbrian memcpy(nak.data, &pcomp, sizeof pcomp); 116194894Sbrian fsm_nak(dec, &nak); 116294894Sbrian } 116394894Sbrian break; 116494894Sbrian default: 116594894Sbrian fsm_rej(dec, opt); 116694894Sbrian break; 116794894Sbrian } 116894894Sbrian } 116994894Sbrian break; 117040561Sbrian 11716059Samurai case MODE_NAK: 1172139973Sbrian if (ntohs(pcomp.proto) == PROTO_VJCOMP) { 1173139973Sbrian /* We know pcomp.slots' max value == MAX_VJ_STATES */ 1174139973Sbrian if (pcomp.slots < MIN_VJ_STATES) 1175139973Sbrian pcomp.slots = MIN_VJ_STATES; 1176139973Sbrian compproto = (ntohs(pcomp.proto) << 16) + (pcomp.slots << 8) + 1177139973Sbrian pcomp.compcid; 117843545Sbrian } else 117943545Sbrian compproto = 0; 118094894Sbrian log_Printf(LogIPCP, "%s changing compproto: %08x --> %08x\n", 118194894Sbrian tbuff, ipcp->my_compproto, compproto); 118243545Sbrian ipcp->my_compproto = compproto; 118394894Sbrian break; 118440561Sbrian 11856059Samurai case MODE_REJ: 118694894Sbrian ipcp->peer_reject |= (1 << opt->hdr.id); 118794894Sbrian break; 11886059Samurai } 11896059Samurai break; 119040561Sbrian 119128679Sbrian case TY_IPADDRS: /* RFC1172 */ 119294894Sbrian memcpy(&ipaddr.s_addr, opt->data, 4); 119394894Sbrian memcpy(&dstipaddr.s_addr, opt->data + 4, 4); 119431962Sbrian snprintf(tbuff2, sizeof tbuff2, "%s %s,", tbuff, inet_ntoa(ipaddr)); 119536285Sbrian log_Printf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr)); 11966059Samurai 119731034Sbrian switch (mode_type) { 11986059Samurai case MODE_REQ: 119994894Sbrian fsm_rej(dec, opt); 120094894Sbrian break; 120140561Sbrian 12026059Samurai case MODE_NAK: 12036059Samurai case MODE_REJ: 120494894Sbrian break; 12056059Samurai } 12066059Samurai break; 120718752Sjkh 120836285Sbrian case TY_PRIMARY_DNS: /* DNS negotiation (rfc1877) */ 120936285Sbrian case TY_SECONDARY_DNS: 121094894Sbrian memcpy(&ipaddr.s_addr, opt->data, 4); 121136285Sbrian log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 121218752Sjkh 121331034Sbrian switch (mode_type) { 121418752Sjkh case MODE_REQ: 121536285Sbrian if (!IsAccepted(ipcp->cfg.ns.dns_neg)) { 121694894Sbrian ipcp->my_reject |= (1 << (opt->hdr.id - TY_ADJUST_NS)); 121794894Sbrian fsm_rej(dec, opt); 121894894Sbrian break; 121936285Sbrian } 122094894Sbrian have_ip = ipcp->ns.dns[opt->hdr.id == TY_PRIMARY_DNS ? 0 : 1]; 122158044Sbrian 122294894Sbrian if (opt->hdr.id == TY_PRIMARY_DNS && ipaddr.s_addr != have_ip.s_addr && 122381634Sbrian ipaddr.s_addr == ipcp->ns.dns[1].s_addr) { 122458044Sbrian /* Swap 'em 'round */ 122581634Sbrian ipcp->ns.dns[0] = ipcp->ns.dns[1]; 122681634Sbrian ipcp->ns.dns[1] = have_ip; 122781634Sbrian have_ip = ipcp->ns.dns[0]; 122836285Sbrian } 122928679Sbrian 123094894Sbrian if (ipaddr.s_addr != have_ip.s_addr) { 123194894Sbrian /* 123294894Sbrian * The client has got the DNS stuff wrong (first request) so 123394894Sbrian * we'll tell 'em how it is 123494894Sbrian */ 123594894Sbrian nak.hdr.id = opt->hdr.id; 123694894Sbrian nak.hdr.len = 6; 123794894Sbrian memcpy(nak.data, &have_ip.s_addr, 4); 123894894Sbrian fsm_nak(dec, &nak); 123994894Sbrian } else { 124094894Sbrian /* 1241108533Sschweikh * Otherwise they have it right (this time) so we send an ack packet 124294894Sbrian * back confirming it... end of story 124394894Sbrian */ 124494894Sbrian fsm_ack(dec, opt); 124536285Sbrian } 124694894Sbrian break; 124740561Sbrian 124858044Sbrian case MODE_NAK: 124936285Sbrian if (IsEnabled(ipcp->cfg.ns.dns_neg)) { 125036285Sbrian gotdnsnak = 1; 125194894Sbrian memcpy(&ipcp->ns.dns[opt->hdr.id == TY_PRIMARY_DNS ? 0 : 1].s_addr, 125294894Sbrian opt->data, 4); 125394894Sbrian } 125494894Sbrian break; 125540561Sbrian 125636285Sbrian case MODE_REJ: /* Can't do much, stop asking */ 125794894Sbrian ipcp->peer_reject |= (1 << (opt->hdr.id - TY_ADJUST_NS)); 125894894Sbrian break; 125918752Sjkh } 126018752Sjkh break; 126118752Sjkh 126236285Sbrian case TY_PRIMARY_NBNS: /* M$ NetBIOS nameserver hack (rfc1877) */ 126318752Sjkh case TY_SECONDARY_NBNS: 126494894Sbrian memcpy(&ipaddr.s_addr, opt->data, 4); 126536285Sbrian log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 126636285Sbrian 126731034Sbrian switch (mode_type) { 126818752Sjkh case MODE_REQ: 126994894Sbrian have_ip.s_addr = 127094894Sbrian ipcp->cfg.ns.nbns[opt->hdr.id == TY_PRIMARY_NBNS ? 0 : 1].s_addr; 127136285Sbrian 127236285Sbrian if (have_ip.s_addr == INADDR_ANY) { 127394894Sbrian log_Printf(LogIPCP, "NBNS REQ - rejected - nbns not set\n"); 127494894Sbrian ipcp->my_reject |= (1 << (opt->hdr.id - TY_ADJUST_NS)); 127594894Sbrian fsm_rej(dec, opt); 127694894Sbrian break; 127736285Sbrian } 127836285Sbrian 127994894Sbrian if (ipaddr.s_addr != have_ip.s_addr) { 128094894Sbrian nak.hdr.id = opt->hdr.id; 128194894Sbrian nak.hdr.len = 6; 128294894Sbrian memcpy(nak.data, &have_ip.s_addr, 4); 128394894Sbrian fsm_nak(dec, &nak); 128494894Sbrian } else 128594894Sbrian fsm_ack(dec, opt); 128694894Sbrian break; 128740561Sbrian 128818752Sjkh case MODE_NAK: 128994894Sbrian log_Printf(LogIPCP, "MS NBNS req %d - NAK??\n", opt->hdr.id); 129094894Sbrian break; 129140561Sbrian 129218752Sjkh case MODE_REJ: 129394894Sbrian log_Printf(LogIPCP, "MS NBNS req %d - REJ??\n", opt->hdr.id); 129494894Sbrian break; 129518752Sjkh } 129618752Sjkh break; 129718752Sjkh 12986059Samurai default: 129936285Sbrian if (mode_type != MODE_NOP) { 130094894Sbrian ipcp->my_reject |= (1 << opt->hdr.id); 130194894Sbrian fsm_rej(dec, opt); 130236285Sbrian } 13036059Samurai break; 13046059Samurai } 13056059Samurai } 130636285Sbrian 130758044Sbrian if (gotdnsnak) { 130858044Sbrian if (ipcp->ns.writable) { 130958044Sbrian log_Printf(LogDEBUG, "Updating resolver\n"); 131058044Sbrian if (!ipcp_WriteDNS(ipcp)) { 131158044Sbrian ipcp->peer_reject |= (1 << (TY_PRIMARY_DNS - TY_ADJUST_NS)); 131258044Sbrian ipcp->peer_reject |= (1 << (TY_SECONDARY_DNS - TY_ADJUST_NS)); 131358044Sbrian } else 131481634Sbrian bundle_AdjustDNS(fp->bundle); 131558044Sbrian } else { 131658044Sbrian log_Printf(LogDEBUG, "Not updating resolver (readonly)\n"); 131781634Sbrian bundle_AdjustDNS(fp->bundle); 131836285Sbrian } 131958044Sbrian } 132036285Sbrian 132136285Sbrian if (mode_type != MODE_NOP) { 132280476Sbrian if (mode_type == MODE_REQ && !ipcp->peer_req) { 132380476Sbrian if (dec->rejend == dec->rej && dec->nakend == dec->nak) { 132480476Sbrian /* 132580476Sbrian * Pretend the peer has requested an IP. 132680476Sbrian * We do this to ensure that we only send one NAK if the only 132780476Sbrian * reason for the NAK is because the peer isn't sending a 132880476Sbrian * TY_IPADDR REQ. This stops us from repeatedly trying to tell 132980476Sbrian * the peer that we have to have an IP address on their end. 133080476Sbrian */ 133180476Sbrian ipcp->peer_req = 1; 133280476Sbrian } 133376986Sbrian ipaddr.s_addr = INADDR_ANY; 133476986Sbrian ipcp_ValidateReq(ipcp, ipaddr, dec); 133576986Sbrian } 133694894Sbrian fsm_opt_normalise(dec); 133736285Sbrian } 13386059Samurai} 13396059Samurai 134046686Sbrianextern struct mbuf * 134146686Sbrianipcp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 13426059Samurai{ 134336285Sbrian /* Got PROTO_IPCP from link */ 134454912Sbrian m_settype(bp, MB_IPCPIN); 134536285Sbrian if (bundle_Phase(bundle) == PHASE_NETWORK) 134646686Sbrian fsm_Input(&bundle->ncp.ipcp.fsm, bp); 134736285Sbrian else { 134836285Sbrian if (bundle_Phase(bundle) < PHASE_NETWORK) 134936285Sbrian log_Printf(LogIPCP, "%s: Error: Unexpected IPCP in phase %s (ignored)\n", 135046686Sbrian l->name, bundle_PhaseName(bundle)); 135154912Sbrian m_freem(bp); 135236285Sbrian } 135346686Sbrian return NULL; 13546059Samurai} 135532267Sbrian 135632267Sbrianint 135743313Sbrianipcp_UseHisIPaddr(struct bundle *bundle, struct in_addr hisaddr) 135843313Sbrian{ 135943313Sbrian struct ipcp *ipcp = &bundle->ncp.ipcp; 136081634Sbrian struct in_addr myaddr; 136143313Sbrian 136243313Sbrian memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 136343313Sbrian iplist_reset(&ipcp->cfg.peer_list); 136481634Sbrian ipcp->peer_ip = hisaddr; 136581634Sbrian ncprange_setip4host(&ipcp->cfg.peer_range, hisaddr); 136681634Sbrian ncprange_getip4addr(&ipcp->cfg.my_range, &myaddr); 136743313Sbrian 136881634Sbrian return ipcp_SetIPaddress(ipcp, myaddr, hisaddr); 136943313Sbrian} 137043313Sbrian 137143313Sbrianint 137236285Sbrianipcp_UseHisaddr(struct bundle *bundle, const char *hisaddr, int setaddr) 137332267Sbrian{ 137481634Sbrian struct in_addr myaddr; 137581634Sbrian struct ncp *ncp = &bundle->ncp; 137681634Sbrian struct ipcp *ipcp = &ncp->ipcp; 137781634Sbrian struct ncpaddr ncpaddr; 137836285Sbrian 137936285Sbrian /* Use `hisaddr' for the peers address (set iface if `setaddr') */ 138036285Sbrian memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 138136285Sbrian iplist_reset(&ipcp->cfg.peer_list); 138232267Sbrian if (strpbrk(hisaddr, ",-")) { 138336285Sbrian iplist_setsrc(&ipcp->cfg.peer_list, hisaddr); 138436285Sbrian if (iplist_isvalid(&ipcp->cfg.peer_list)) { 138536285Sbrian iplist_setrandpos(&ipcp->cfg.peer_list); 138636285Sbrian ipcp->peer_ip = ChooseHisAddr(bundle, ipcp->my_ip); 138736285Sbrian if (ipcp->peer_ip.s_addr == INADDR_ANY) { 138836285Sbrian log_Printf(LogWARN, "%s: None available !\n", ipcp->cfg.peer_list.src); 138947648Sbrian return 0; 139032267Sbrian } 139181634Sbrian ncprange_setip4host(&ipcp->cfg.peer_range, ipcp->peer_ip); 139232267Sbrian } else { 139336285Sbrian log_Printf(LogWARN, "%s: Invalid range !\n", hisaddr); 139432267Sbrian return 0; 139532267Sbrian } 139681634Sbrian } else if (ncprange_aton(&ipcp->cfg.peer_range, ncp, hisaddr) != 0) { 139781634Sbrian if (ncprange_family(&ipcp->cfg.my_range) != AF_INET) { 139881634Sbrian log_Printf(LogWARN, "%s: Not an AF_INET address !\n", hisaddr); 139981634Sbrian return 0; 140081634Sbrian } 140181634Sbrian ncprange_getip4addr(&ipcp->cfg.my_range, &myaddr); 140281634Sbrian ncprange_getip4addr(&ipcp->cfg.peer_range, &ipcp->peer_ip); 140332267Sbrian 140481634Sbrian if (setaddr && !ipcp_SetIPaddress(ipcp, myaddr, ipcp->peer_ip)) 140532267Sbrian return 0; 140632267Sbrian } else 140732267Sbrian return 0; 140832267Sbrian 140981634Sbrian ncpaddr_setip4(&ncpaddr, ipcp->peer_ip); 141081634Sbrian bundle_AdjustFilters(bundle, NULL, &ncpaddr); 141147648Sbrian 141247648Sbrian return 1; /* Ok */ 141332267Sbrian} 141444455Sbrian 141544455Sbrianstruct in_addr 141644455Sbrianaddr2mask(struct in_addr addr) 141744455Sbrian{ 141844455Sbrian u_int32_t haddr = ntohl(addr.s_addr); 141944455Sbrian 142044455Sbrian haddr = IN_CLASSA(haddr) ? IN_CLASSA_NET : 142144455Sbrian IN_CLASSB(haddr) ? IN_CLASSB_NET : 142244455Sbrian IN_CLASSC_NET; 142344455Sbrian addr.s_addr = htonl(haddr); 142444455Sbrian 142544455Sbrian return addr; 142644455Sbrian} 142781634Sbrian 142881634Sbriansize_t 142981634Sbrianipcp_QueueLen(struct ipcp *ipcp) 143081634Sbrian{ 143181634Sbrian struct mqueue *q; 143281634Sbrian size_t result; 143381634Sbrian 143481634Sbrian result = 0; 143581634Sbrian for (q = ipcp->Queue; q < ipcp->Queue + IPCP_QUEUES(ipcp); q++) 143681634Sbrian result += q->len; 143781634Sbrian 143881634Sbrian return result; 143981634Sbrian} 144081634Sbrian 144181634Sbrianint 144281634Sbrianipcp_PushPacket(struct ipcp *ipcp, struct link *l) 144381634Sbrian{ 144481634Sbrian struct bundle *bundle = ipcp->fsm.bundle; 144581634Sbrian struct mqueue *queue; 144681634Sbrian struct mbuf *bp; 144781634Sbrian int m_len; 144881634Sbrian u_int32_t secs = 0; 144981634Sbrian unsigned alivesecs = 0; 145081634Sbrian 145181634Sbrian if (ipcp->fsm.state != ST_OPENED) 145281634Sbrian return 0; 145381634Sbrian 145481634Sbrian /* 145581634Sbrian * If ccp is not open but is required, do nothing. 145681634Sbrian */ 145781634Sbrian if (l->ccp.fsm.state != ST_OPENED && ccp_Required(&l->ccp)) { 145881634Sbrian log_Printf(LogPHASE, "%s: Not transmitting... waiting for CCP\n", l->name); 145981634Sbrian return 0; 146081634Sbrian } 146181634Sbrian 146281634Sbrian queue = ipcp->Queue + IPCP_QUEUES(ipcp) - 1; 146381634Sbrian do { 146481634Sbrian if (queue->top) { 146581634Sbrian bp = m_dequeue(queue); 146681634Sbrian bp = mbuf_Read(bp, &secs, sizeof secs); 146781634Sbrian bp = m_pullup(bp); 146881634Sbrian m_len = m_length(bp); 146981634Sbrian if (!FilterCheck(MBUF_CTOP(bp), AF_INET, &bundle->filter.alive, 147081634Sbrian &alivesecs)) { 147181634Sbrian if (secs == 0) 147281634Sbrian secs = alivesecs; 147381634Sbrian bundle_StartIdleTimer(bundle, secs); 147481634Sbrian } 147581634Sbrian link_PushPacket(l, bp, bundle, 0, PROTO_IP); 147681634Sbrian ipcp_AddOutOctets(ipcp, m_len); 147781634Sbrian return 1; 147881634Sbrian } 147981634Sbrian } while (queue-- != ipcp->Queue); 148081634Sbrian 148181634Sbrian return 0; 148281634Sbrian} 1483