1af57ed9fSAtsushi Murai /* 2af57ed9fSAtsushi Murai * PPP IP Control Protocol (IPCP) Module 3af57ed9fSAtsushi Murai * 4af57ed9fSAtsushi Murai * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 5af57ed9fSAtsushi Murai * 6af57ed9fSAtsushi Murai * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 7af57ed9fSAtsushi Murai * 8af57ed9fSAtsushi Murai * Redistribution and use in source and binary forms are permitted 9af57ed9fSAtsushi Murai * provided that the above copyright notice and this paragraph are 10af57ed9fSAtsushi Murai * duplicated in all such forms and that any documentation, 11af57ed9fSAtsushi Murai * advertising materials, and other materials related to such 12af57ed9fSAtsushi Murai * distribution and use acknowledge that the software was developed 13af57ed9fSAtsushi Murai * by the Internet Initiative Japan, Inc. The name of the 14af57ed9fSAtsushi Murai * IIJ may not be used to endorse or promote products derived 15af57ed9fSAtsushi Murai * from this software without specific prior written permission. 16af57ed9fSAtsushi Murai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17af57ed9fSAtsushi Murai * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18af57ed9fSAtsushi Murai * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19af57ed9fSAtsushi Murai * 2097d92980SPeter Wemm * $FreeBSD$ 21af57ed9fSAtsushi Murai * 22af57ed9fSAtsushi Murai * TODO: 235d9e6103SBrian Somers * o Support IPADDRS properly 245d9e6103SBrian Somers * o Validate the length in IpcpDecodeConfig 25af57ed9fSAtsushi Murai */ 2675240ed1SBrian Somers #include <sys/param.h> 275b4c5b00SBrian Somers #include <netinet/in_systm.h> 285b4c5b00SBrian Somers #include <netinet/in.h> 295b4c5b00SBrian Somers #include <netinet/ip.h> 305b4c5b00SBrian Somers #include <arpa/inet.h> 315b4c5b00SBrian Somers #include <sys/socket.h> 323afe5ccbSBrian Somers #include <net/route.h> 3375240ed1SBrian Somers #include <netdb.h> 341fa665f5SBrian Somers #include <sys/un.h> 3575240ed1SBrian Somers 36119386a3SBrian Somers #include <errno.h> 373edeb0c6SBrian Somers #include <fcntl.h> 383edeb0c6SBrian Somers #include <resolv.h> 39d1a3ea47SBrian Somers #include <stdlib.h> 4075240ed1SBrian Somers #include <string.h> 41d568d6c4SBrian Somers #include <sys/stat.h> 426140ba11SBrian Somers #include <termios.h> 4375240ed1SBrian Somers #include <unistd.h> 4475240ed1SBrian Somers 4567b072f7SBrian Somers #ifndef NONAT 4610e629b9SBrian Somers #ifdef LOCALNAT 477884358fSBrian Somers #include "alias.h" 4810e629b9SBrian Somers #else 4910e629b9SBrian Somers #include <alias.h> 501595bacdSBrian Somers #endif 511595bacdSBrian Somers #endif 5210e629b9SBrian Somers 535d9e6103SBrian Somers #include "layer.h" 549e8ec64bSBrian Somers #include "ua.h" 55c9e11a11SBrian Somers #include "defs.h" 56b6e82f33SBrian Somers #include "command.h" 5775240ed1SBrian Somers #include "mbuf.h" 5875240ed1SBrian Somers #include "log.h" 5975240ed1SBrian Somers #include "timer.h" 60af57ed9fSAtsushi Murai #include "fsm.h" 615d9e6103SBrian Somers #include "proto.h" 62bcc332bdSBrian Somers #include "iplist.h" 639a0b991fSBrian Somers #include "throughput.h" 641ae349f5Scvs2svn #include "slcompress.h" 655a72b6edSBrian Somers #include "lqr.h" 665a72b6edSBrian Somers #include "hdlc.h" 671038894eSBrian Somers #include "lcp.h" 68eaa4df37SBrian Somers #include "ipcp.h" 699c97abd8SBrian Somers #include "filter.h" 702f786681SBrian Somers #include "descriptor.h" 711ae349f5Scvs2svn #include "vjcomp.h" 726140ba11SBrian Somers #include "async.h" 733b0f8d2eSBrian Somers #include "ccp.h" 748c07a7b2SBrian Somers #include "link.h" 7563b73463SBrian Somers #include "physical.h" 763b0f8d2eSBrian Somers #include "mp.h" 77972a1bcfSBrian Somers #ifndef NORADIUS 78972a1bcfSBrian Somers #include "radius.h" 79972a1bcfSBrian Somers #endif 803b0f8d2eSBrian Somers #include "bundle.h" 81455aabc3SBrian Somers #include "id.h" 82455aabc3SBrian Somers #include "arp.h" 83455aabc3SBrian Somers #include "systems.h" 8485b542cfSBrian Somers #include "prompt.h" 85610b185fSBrian Somers #include "route.h" 868fa6ebe4SBrian Somers #include "iface.h" 87442f8495SBrian Somers #include "ip.h" 88af57ed9fSAtsushi Murai 89503a7782SBrian Somers #undef REJECTED 90503a7782SBrian Somers #define REJECTED(p, x) ((p)->peer_reject & (1<<(x))) 913edeb0c6SBrian Somers #define issep(ch) ((ch) == ' ' || (ch) == '\t') 923edeb0c6SBrian Somers #define isip(ch) (((ch) >= '0' && (ch) <= '9') || (ch) == '.') 93d8e55738SJordan K. Hubbard 94da477886SBrian Somers static u_short default_urgent_tcp_ports[] = { 95442f8495SBrian Somers 21, /* ftp */ 96442f8495SBrian Somers 22, /* ssh */ 97442f8495SBrian Somers 23, /* telnet */ 98442f8495SBrian Somers 513, /* login */ 99442f8495SBrian Somers 514, /* shell */ 100442f8495SBrian Somers 543, /* klogin */ 101442f8495SBrian Somers 544 /* kshell */ 102442f8495SBrian Somers }; 103442f8495SBrian Somers 104da477886SBrian Somers static u_short default_urgent_udp_ports[] = { }; 105da477886SBrian Somers 106da477886SBrian Somers #define NDEFTCPPORTS \ 107da477886SBrian Somers (sizeof default_urgent_tcp_ports / sizeof default_urgent_tcp_ports[0]) 108da477886SBrian Somers #define NDEFUDPPORTS \ 109da477886SBrian Somers (sizeof default_urgent_udp_ports / sizeof default_urgent_udp_ports[0]) 110442f8495SBrian Somers 111442f8495SBrian Somers int 112da477886SBrian Somers ipcp_IsUrgentPort(struct port_range *range, u_short src, u_short dst) 113442f8495SBrian Somers { 114442f8495SBrian Somers int f; 115442f8495SBrian Somers 116da477886SBrian Somers for (f = 0; f < range->nports; f++) 117da477886SBrian Somers if (range->port[f] == src || range->port[f] == dst) 118442f8495SBrian Somers return 1; 119442f8495SBrian Somers 120442f8495SBrian Somers return 0; 121442f8495SBrian Somers } 122442f8495SBrian Somers 123442f8495SBrian Somers void 124da477886SBrian Somers ipcp_AddUrgentPort(struct port_range *range, u_short port) 125442f8495SBrian Somers { 126442f8495SBrian Somers u_short *newport; 127442f8495SBrian Somers int p; 128442f8495SBrian Somers 129da477886SBrian Somers if (range->nports == range->maxports) { 130da477886SBrian Somers range->maxports += 10; 131da477886SBrian Somers newport = (u_short *)realloc(range->port, 132da477886SBrian Somers range->maxports * sizeof(u_short)); 133442f8495SBrian Somers if (newport == NULL) { 134442f8495SBrian Somers log_Printf(LogERROR, "ipcp_AddUrgentPort: realloc: %s\n", 135442f8495SBrian Somers strerror(errno)); 136da477886SBrian Somers range->maxports -= 10; 137442f8495SBrian Somers return; 138442f8495SBrian Somers } 139da477886SBrian Somers range->port = newport; 140442f8495SBrian Somers } 141442f8495SBrian Somers 142da477886SBrian Somers for (p = 0; p < range->nports; p++) 143da477886SBrian Somers if (range->port[p] == port) { 144442f8495SBrian Somers log_Printf(LogWARN, "%u: Port already set to urgent\n", port); 145442f8495SBrian Somers break; 146da477886SBrian Somers } else if (range->port[p] > port) { 147da477886SBrian Somers memmove(range->port + p + 1, range->port + p, 148da477886SBrian Somers (range->nports - p) * sizeof(u_short)); 149da477886SBrian Somers range->port[p] = port; 150da477886SBrian Somers range->nports++; 151442f8495SBrian Somers break; 152442f8495SBrian Somers } 153442f8495SBrian Somers 154da477886SBrian Somers if (p == range->nports) 155da477886SBrian Somers range->port[range->nports++] = port; 156442f8495SBrian Somers } 157442f8495SBrian Somers 158442f8495SBrian Somers void 159da477886SBrian Somers ipcp_RemoveUrgentPort(struct port_range *range, u_short port) 160442f8495SBrian Somers { 161442f8495SBrian Somers int p; 162442f8495SBrian Somers 163da477886SBrian Somers for (p = 0; p < range->nports; p++) 164da477886SBrian Somers if (range->port[p] == port) { 165da477886SBrian Somers if (p != range->nports - 1) 166da477886SBrian Somers memmove(range->port + p, range->port + p + 1, 167da477886SBrian Somers (range->nports - p - 1) * sizeof(u_short)); 168da477886SBrian Somers range->nports--; 169442f8495SBrian Somers return; 170442f8495SBrian Somers } 171442f8495SBrian Somers 172da477886SBrian Somers if (p == range->nports) 173442f8495SBrian Somers log_Printf(LogWARN, "%u: Port not set to urgent\n", port); 174442f8495SBrian Somers } 175442f8495SBrian Somers 176442f8495SBrian Somers void 177da477886SBrian Somers ipcp_ClearUrgentPorts(struct port_range *range) 178442f8495SBrian Somers { 179da477886SBrian Somers range->nports = 0; 180442f8495SBrian Somers } 181442f8495SBrian Somers 18229e275ceSBrian Somers struct compreq { 18329e275ceSBrian Somers u_short proto; 18429e275ceSBrian Somers u_char slots; 18529e275ceSBrian Somers u_char compcid; 18629e275ceSBrian Somers }; 18775240ed1SBrian Somers 1886f384573SBrian Somers static int IpcpLayerUp(struct fsm *); 1891ae349f5Scvs2svn static void IpcpLayerDown(struct fsm *); 190927145beSBrian Somers static void IpcpLayerStart(struct fsm *); 191927145beSBrian Somers static void IpcpLayerFinish(struct fsm *); 192479508cfSBrian Somers static void IpcpInitRestartCounter(struct fsm *, int); 1937308ec68SBrian Somers static void IpcpSendConfigReq(struct fsm *); 1942267893fSBrian Somers static void IpcpSentTerminateReq(struct fsm *); 1952267893fSBrian Somers static void IpcpSendTerminateAck(struct fsm *, u_char); 19630c2f2ffSBrian Somers static void IpcpDecodeConfig(struct fsm *, u_char *, int, int, 19730c2f2ffSBrian Somers struct fsm_decode *); 198af57ed9fSAtsushi Murai 19983d1af55SBrian Somers static struct fsm_callbacks ipcp_Callbacks = { 200af57ed9fSAtsushi Murai IpcpLayerUp, 201af57ed9fSAtsushi Murai IpcpLayerDown, 202af57ed9fSAtsushi Murai IpcpLayerStart, 203af57ed9fSAtsushi Murai IpcpLayerFinish, 204af57ed9fSAtsushi Murai IpcpInitRestartCounter, 205af57ed9fSAtsushi Murai IpcpSendConfigReq, 2062267893fSBrian Somers IpcpSentTerminateReq, 207af57ed9fSAtsushi Murai IpcpSendTerminateAck, 208af57ed9fSAtsushi Murai IpcpDecodeConfig, 209dd7e2610SBrian Somers fsm_NullRecvResetReq, 210dd7e2610SBrian Somers fsm_NullRecvResetAck 211af57ed9fSAtsushi Murai }; 212af57ed9fSAtsushi Murai 213d6d3eeabSBrian Somers static const char * 214d6d3eeabSBrian Somers protoname(int proto) 215d6d3eeabSBrian Somers { 216d6d3eeabSBrian Somers static struct { 217d6d3eeabSBrian Somers int id; 218d6d3eeabSBrian Somers const char *txt; 219d6d3eeabSBrian Somers } cftypes[] = { 2209e836af5SBrian Somers /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */ 221d6d3eeabSBrian Somers { 1, "IPADDRS" }, /* IP-Addresses */ /* deprecated */ 222d6d3eeabSBrian Somers { 2, "COMPPROTO" }, /* IP-Compression-Protocol */ 223d6d3eeabSBrian Somers { 3, "IPADDR" }, /* IP-Address */ 224d6d3eeabSBrian Somers { 129, "PRIDNS" }, /* 129: Primary DNS Server Address */ 225d6d3eeabSBrian Somers { 130, "PRINBNS" }, /* 130: Primary NBNS Server Address */ 226d6d3eeabSBrian Somers { 131, "SECDNS" }, /* 131: Secondary DNS Server Address */ 227d6d3eeabSBrian Somers { 132, "SECNBNS" } /* 132: Secondary NBNS Server Address */ 228af57ed9fSAtsushi Murai }; 229d6d3eeabSBrian Somers int f; 230af57ed9fSAtsushi Murai 231d6d3eeabSBrian Somers for (f = 0; f < sizeof cftypes / sizeof *cftypes; f++) 232d6d3eeabSBrian Somers if (cftypes[f].id == proto) 233d6d3eeabSBrian Somers return cftypes[f].txt; 2349e836af5SBrian Somers 235d6d3eeabSBrian Somers return NumStr(proto, NULL, 0); 236d6d3eeabSBrian Somers } 2379e836af5SBrian Somers 2389a0b991fSBrian Somers void 2395828db6dSBrian Somers ipcp_AddInOctets(struct ipcp *ipcp, int n) 240af57ed9fSAtsushi Murai { 2415828db6dSBrian Somers throughput_addin(&ipcp->throughput, n); 242af57ed9fSAtsushi Murai } 243af57ed9fSAtsushi Murai 2449a0b991fSBrian Somers void 2455828db6dSBrian Somers ipcp_AddOutOctets(struct ipcp *ipcp, int n) 246af57ed9fSAtsushi Murai { 2475828db6dSBrian Somers throughput_addout(&ipcp->throughput, n); 2481ae349f5Scvs2svn } 2491ae349f5Scvs2svn 250d568d6c4SBrian Somers void 251d568d6c4SBrian Somers ipcp_LoadDNS(struct ipcp *ipcp) 2523edeb0c6SBrian Somers { 253d568d6c4SBrian Somers int fd; 2543edeb0c6SBrian Somers 255d568d6c4SBrian Somers ipcp->ns.dns[0].s_addr = ipcp->ns.dns[1].s_addr = INADDR_NONE; 256d568d6c4SBrian Somers 257d568d6c4SBrian Somers if (ipcp->ns.resolv != NULL) { 258d568d6c4SBrian Somers free(ipcp->ns.resolv); 259d568d6c4SBrian Somers ipcp->ns.resolv = NULL; 260d568d6c4SBrian Somers } 261d568d6c4SBrian Somers if (ipcp->ns.resolv_nons != NULL) { 262d568d6c4SBrian Somers free(ipcp->ns.resolv_nons); 263d568d6c4SBrian Somers ipcp->ns.resolv_nons = NULL; 264d568d6c4SBrian Somers } 265d568d6c4SBrian Somers ipcp->ns.resolver = 0; 266d568d6c4SBrian Somers 267d568d6c4SBrian Somers if ((fd = open(_PATH_RESCONF, O_RDONLY)) != -1) { 268d568d6c4SBrian Somers struct stat st; 269d568d6c4SBrian Somers 270d568d6c4SBrian Somers if (fstat(fd, &st) == 0) { 271d568d6c4SBrian Somers ssize_t got; 272d568d6c4SBrian Somers 273d568d6c4SBrian Somers if ((ipcp->ns.resolv_nons = (char *)malloc(st.st_size + 1)) == NULL) 274d568d6c4SBrian Somers log_Printf(LogERROR, "Failed to malloc %lu for %s: %s\n", 275d568d6c4SBrian Somers (unsigned long)st.st_size, _PATH_RESCONF, strerror(errno)); 276d568d6c4SBrian Somers else if ((ipcp->ns.resolv = (char *)malloc(st.st_size + 1)) == NULL) { 277d568d6c4SBrian Somers log_Printf(LogERROR, "Failed(2) to malloc %lu for %s: %s\n", 278d568d6c4SBrian Somers (unsigned long)st.st_size, _PATH_RESCONF, strerror(errno)); 279d568d6c4SBrian Somers free(ipcp->ns.resolv_nons); 280d568d6c4SBrian Somers ipcp->ns.resolv_nons = NULL; 281d568d6c4SBrian Somers } else if ((got = read(fd, ipcp->ns.resolv, st.st_size)) != st.st_size) { 282d568d6c4SBrian Somers if (got == -1) 283d568d6c4SBrian Somers log_Printf(LogERROR, "Failed to read %s: %s\n", 284d568d6c4SBrian Somers _PATH_RESCONF, strerror(errno)); 285d568d6c4SBrian Somers else 286d568d6c4SBrian Somers log_Printf(LogERROR, "Failed to read %s, got %lu not %lu\n", 287d568d6c4SBrian Somers _PATH_RESCONF, (unsigned long)got, 288d568d6c4SBrian Somers (unsigned long)st.st_size); 289d568d6c4SBrian Somers free(ipcp->ns.resolv_nons); 290d568d6c4SBrian Somers ipcp->ns.resolv_nons = NULL; 291d568d6c4SBrian Somers free(ipcp->ns.resolv); 292d568d6c4SBrian Somers ipcp->ns.resolv = NULL; 293d568d6c4SBrian Somers } else { 294d568d6c4SBrian Somers char *cp, *cp_nons, *ncp, ch; 2953edeb0c6SBrian Somers int n; 2963edeb0c6SBrian Somers 297d568d6c4SBrian Somers ipcp->ns.resolv[st.st_size] = '\0'; 298d568d6c4SBrian Somers ipcp->ns.resolver = 1; 299d568d6c4SBrian Somers 300d568d6c4SBrian Somers cp_nons = ipcp->ns.resolv_nons; 301d568d6c4SBrian Somers cp = ipcp->ns.resolv; 3023edeb0c6SBrian Somers n = 0; 303d568d6c4SBrian Somers 304d568d6c4SBrian Somers while ((ncp = strstr(cp, "nameserver")) != NULL) { 305d568d6c4SBrian Somers if (ncp != cp) { 306d568d6c4SBrian Somers memcpy(cp_nons, cp, ncp - cp); 307d568d6c4SBrian Somers cp_nons += ncp - cp; 3083edeb0c6SBrian Somers } 309d568d6c4SBrian Somers if ((ncp != cp && ncp[-1] != '\n') || !issep(ncp[10])) { 310d568d6c4SBrian Somers memcpy(cp_nons, ncp, 9); 311d568d6c4SBrian Somers cp_nons += 9; 312d568d6c4SBrian Somers cp = ncp + 9; /* Can't match "nameserver" at cp... */ 313d568d6c4SBrian Somers continue; 3143edeb0c6SBrian Somers } 315d568d6c4SBrian Somers 316d568d6c4SBrian Somers for (cp = ncp + 11; issep(*cp); cp++) /* Skip whitespace */ 317d568d6c4SBrian Somers ; 318d568d6c4SBrian Somers 319d568d6c4SBrian Somers for (ncp = cp; isip(*ncp); ncp++) /* Jump over IP */ 320d568d6c4SBrian Somers ; 321d568d6c4SBrian Somers 322d568d6c4SBrian Somers ch = *ncp; 323d568d6c4SBrian Somers *ncp = '\0'; 324d568d6c4SBrian Somers if (n < 2 && inet_aton(cp, ipcp->ns.dns + n)) 325d568d6c4SBrian Somers n++; 326d568d6c4SBrian Somers *ncp = ch; 327d568d6c4SBrian Somers 328d568d6c4SBrian Somers if ((cp = strchr(ncp, '\n')) == NULL) /* Point at next line */ 329d568d6c4SBrian Somers cp = ncp + strlen(ncp); 330d568d6c4SBrian Somers else 331d568d6c4SBrian Somers cp++; 332d568d6c4SBrian Somers } 333d568d6c4SBrian Somers strcpy(cp_nons, cp); /* Copy the end - including the NUL */ 334d568d6c4SBrian Somers cp_nons += strlen(cp_nons) - 1; 335d568d6c4SBrian Somers while (cp_nons >= ipcp->ns.resolv_nons && *cp_nons == '\n') 336d568d6c4SBrian Somers *cp_nons-- = '\0'; 337d568d6c4SBrian Somers if (n == 2 && ipcp->ns.dns[0].s_addr == INADDR_ANY) { 338d568d6c4SBrian Somers ipcp->ns.dns[0].s_addr = ipcp->ns.dns[1].s_addr; 339d568d6c4SBrian Somers ipcp->ns.dns[1].s_addr = INADDR_ANY; 340d568d6c4SBrian Somers } 341d568d6c4SBrian Somers bundle_AdjustDNS(ipcp->fsm.bundle, ipcp->ns.dns); 342d568d6c4SBrian Somers } 343d568d6c4SBrian Somers } else 344d568d6c4SBrian Somers log_Printf(LogERROR, "Failed to stat opened %s: %s\n", 345d568d6c4SBrian Somers _PATH_RESCONF, strerror(errno)); 346d568d6c4SBrian Somers 347d568d6c4SBrian Somers close(fd); 3483edeb0c6SBrian Somers } 3493edeb0c6SBrian Somers } 3503edeb0c6SBrian Somers 351d568d6c4SBrian Somers int 352d568d6c4SBrian Somers ipcp_WriteDNS(struct ipcp *ipcp) 3533edeb0c6SBrian Somers { 354d568d6c4SBrian Somers const char *paddr; 355d568d6c4SBrian Somers mode_t mask; 3563edeb0c6SBrian Somers FILE *fp; 3573edeb0c6SBrian Somers 358d568d6c4SBrian Somers if (ipcp->ns.dns[0].s_addr == INADDR_ANY && 359d568d6c4SBrian Somers ipcp->ns.dns[1].s_addr == INADDR_ANY) { 360d568d6c4SBrian Somers log_Printf(LogIPCP, "%s not modified: All nameservers NAKd\n", 3613edeb0c6SBrian Somers _PATH_RESCONF); 3623edeb0c6SBrian Somers return 0; 3633edeb0c6SBrian Somers } 3643edeb0c6SBrian Somers 365d568d6c4SBrian Somers if (ipcp->ns.dns[0].s_addr == INADDR_ANY) { 366d568d6c4SBrian Somers ipcp->ns.dns[0].s_addr = ipcp->ns.dns[1].s_addr; 367d568d6c4SBrian Somers ipcp->ns.dns[1].s_addr = INADDR_ANY; 368d568d6c4SBrian Somers } 3693edeb0c6SBrian Somers 3707fe0b592SBrian Somers mask = umask(022); 371d568d6c4SBrian Somers if ((fp = ID0fopen(_PATH_RESCONF, "w")) != NULL) { 372d568d6c4SBrian Somers umask(mask); 373682cb20fSBrian Somers if (ipcp->ns.resolv_nons) 374d568d6c4SBrian Somers fputs(ipcp->ns.resolv_nons, fp); 375d568d6c4SBrian Somers paddr = inet_ntoa(ipcp->ns.dns[0]); 376d568d6c4SBrian Somers log_Printf(LogIPCP, "Primary nameserver set to %s\n", paddr); 377d568d6c4SBrian Somers fprintf(fp, "\nnameserver %s\n", paddr); 378d568d6c4SBrian Somers if (ipcp->ns.dns[1].s_addr != INADDR_ANY && 379d568d6c4SBrian Somers ipcp->ns.dns[1].s_addr != INADDR_NONE && 380d568d6c4SBrian Somers ipcp->ns.dns[1].s_addr != ipcp->ns.dns[0].s_addr) { 381d568d6c4SBrian Somers paddr = inet_ntoa(ipcp->ns.dns[1]); 382d568d6c4SBrian Somers log_Printf(LogIPCP, "Secondary nameserver set to %s\n", paddr); 383d568d6c4SBrian Somers fprintf(fp, "nameserver %s\n", paddr); 384d568d6c4SBrian Somers } 385d568d6c4SBrian Somers if (fclose(fp) == EOF) { 386d568d6c4SBrian Somers log_Printf(LogERROR, "write(): Failed updating %s: %s\n", _PATH_RESCONF, 387d568d6c4SBrian Somers strerror(errno)); 3883edeb0c6SBrian Somers return 0; 3893edeb0c6SBrian Somers } 390d568d6c4SBrian Somers } else 391d568d6c4SBrian Somers umask(mask); 3923edeb0c6SBrian Somers 3933edeb0c6SBrian Somers return 1; 394af57ed9fSAtsushi Murai } 395af57ed9fSAtsushi Murai 396d568d6c4SBrian Somers void 397d568d6c4SBrian Somers ipcp_RestoreDNS(struct ipcp *ipcp) 398d568d6c4SBrian Somers { 399d568d6c4SBrian Somers if (ipcp->ns.resolver) { 400d568d6c4SBrian Somers ssize_t got; 401d568d6c4SBrian Somers size_t len; 402d568d6c4SBrian Somers int fd; 403d568d6c4SBrian Somers 404d568d6c4SBrian Somers if ((fd = ID0open(_PATH_RESCONF, O_WRONLY|O_TRUNC, 0644)) != -1) { 405d568d6c4SBrian Somers len = strlen(ipcp->ns.resolv); 406d568d6c4SBrian Somers if ((got = write(fd, ipcp->ns.resolv, len)) != len) { 407d568d6c4SBrian Somers if (got == -1) 408d568d6c4SBrian Somers log_Printf(LogERROR, "Failed rewriting %s: write: %s\n", 409d568d6c4SBrian Somers _PATH_RESCONF, strerror(errno)); 410d568d6c4SBrian Somers else 411d568d6c4SBrian Somers log_Printf(LogERROR, "Failed rewriting %s: wrote %lu of %lu\n", 412d568d6c4SBrian Somers _PATH_RESCONF, (unsigned long)got, (unsigned long)len); 413d568d6c4SBrian Somers } 414d568d6c4SBrian Somers close(fd); 415d568d6c4SBrian Somers } else 416d568d6c4SBrian Somers log_Printf(LogERROR, "Failed rewriting %s: open: %s\n", _PATH_RESCONF, 417d568d6c4SBrian Somers strerror(errno)); 418d568d6c4SBrian Somers } else if (remove(_PATH_RESCONF) == -1) 419d568d6c4SBrian Somers log_Printf(LogERROR, "Failed removing %s: %s\n", _PATH_RESCONF, 420d568d6c4SBrian Somers strerror(errno)); 421d568d6c4SBrian Somers 422d568d6c4SBrian Somers } 423d568d6c4SBrian Somers 424274e766cSBrian Somers int 425dd7e2610SBrian Somers ipcp_Show(struct cmdargs const *arg) 426af57ed9fSAtsushi Murai { 427610b185fSBrian Somers struct ipcp *ipcp = &arg->bundle->ncp.ipcp; 428442f8495SBrian Somers int p; 429af57ed9fSAtsushi Murai 430610b185fSBrian Somers prompt_Printf(arg->prompt, "%s [%s]\n", ipcp->fsm.name, 431610b185fSBrian Somers State2Nam(ipcp->fsm.state)); 432610b185fSBrian Somers if (ipcp->fsm.state == ST_OPENED) { 433b6217683SBrian Somers prompt_Printf(arg->prompt, " His side: %s, %s\n", 434610b185fSBrian Somers inet_ntoa(ipcp->peer_ip), vj2asc(ipcp->peer_compproto)); 435b6217683SBrian Somers prompt_Printf(arg->prompt, " My side: %s, %s\n", 436610b185fSBrian Somers inet_ntoa(ipcp->my_ip), vj2asc(ipcp->my_compproto)); 437209dc102SBrian Somers prompt_Printf(arg->prompt, " Queued packets: %lu\n", 438209dc102SBrian Somers (unsigned long)ip_QueueLen(ipcp)); 439d1a3ea47SBrian Somers } 4405b4c5b00SBrian Somers 441610b185fSBrian Somers if (ipcp->route) { 442610b185fSBrian Somers prompt_Printf(arg->prompt, "\n"); 443972a1bcfSBrian Somers route_ShowSticky(arg->prompt, ipcp->route, "Sticky routes", 1); 4441ae349f5Scvs2svn } 445927145beSBrian Somers 446b6217683SBrian Somers prompt_Printf(arg->prompt, "\nDefaults:\n"); 447479508cfSBrian Somers prompt_Printf(arg->prompt, " FSM retry = %us, max %u Config" 448479508cfSBrian Somers " REQ%s, %u Term REQ%s\n", ipcp->cfg.fsm.timeout, 449479508cfSBrian Somers ipcp->cfg.fsm.maxreq, ipcp->cfg.fsm.maxreq == 1 ? "" : "s", 450479508cfSBrian Somers ipcp->cfg.fsm.maxtrm, ipcp->cfg.fsm.maxtrm == 1 ? "" : "s"); 45150abd4c8SBrian Somers prompt_Printf(arg->prompt, " My Address: %s/%d", 452610b185fSBrian Somers inet_ntoa(ipcp->cfg.my_range.ipaddr), ipcp->cfg.my_range.width); 453bc76350eSBrian Somers prompt_Printf(arg->prompt, ", netmask %s\n", inet_ntoa(ipcp->cfg.netmask)); 454610b185fSBrian Somers if (ipcp->cfg.HaveTriggerAddress) 455bc76350eSBrian Somers prompt_Printf(arg->prompt, " Trigger address: %s\n", 456610b185fSBrian Somers inet_ntoa(ipcp->cfg.TriggerAddress)); 457bc76350eSBrian Somers 458bc76350eSBrian Somers prompt_Printf(arg->prompt, " VJ compression: %s (%d slots %s slot " 459610b185fSBrian Somers "compression)\n", command_ShowNegval(ipcp->cfg.vj.neg), 460610b185fSBrian Somers ipcp->cfg.vj.slots, ipcp->cfg.vj.slotcomp ? "with" : "without"); 46150abd4c8SBrian Somers 462610b185fSBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) 463b6217683SBrian Somers prompt_Printf(arg->prompt, " His Address: %s\n", 464610b185fSBrian Somers ipcp->cfg.peer_list.src); 4651ae349f5Scvs2svn else 466b6217683SBrian Somers prompt_Printf(arg->prompt, " His Address: %s/%d\n", 467610b185fSBrian Somers inet_ntoa(ipcp->cfg.peer_range.ipaddr), 468610b185fSBrian Somers ipcp->cfg.peer_range.width); 46950abd4c8SBrian Somers 470d568d6c4SBrian Somers prompt_Printf(arg->prompt, " DNS: %s", 471d568d6c4SBrian Somers ipcp->cfg.ns.dns[0].s_addr == INADDR_NONE ? 472d568d6c4SBrian Somers "none" : inet_ntoa(ipcp->cfg.ns.dns[0])); 473d568d6c4SBrian Somers if (ipcp->cfg.ns.dns[1].s_addr != INADDR_NONE) 474d568d6c4SBrian Somers prompt_Printf(arg->prompt, ", %s", inet_ntoa(ipcp->cfg.ns.dns[1])); 475d568d6c4SBrian Somers prompt_Printf(arg->prompt, ", %s\n", 476610b185fSBrian Somers command_ShowNegval(ipcp->cfg.ns.dns_neg)); 477d568d6c4SBrian Somers prompt_Printf(arg->prompt, " Resolver DNS: %s", 478d568d6c4SBrian Somers ipcp->ns.dns[0].s_addr == INADDR_NONE ? 479d568d6c4SBrian Somers "none" : inet_ntoa(ipcp->ns.dns[0])); 480d568d6c4SBrian Somers if (ipcp->ns.dns[1].s_addr != INADDR_NONE && 481d568d6c4SBrian Somers ipcp->ns.dns[1].s_addr != ipcp->ns.dns[0].s_addr) 482d568d6c4SBrian Somers prompt_Printf(arg->prompt, ", %s", inet_ntoa(ipcp->ns.dns[1])); 483d568d6c4SBrian Somers prompt_Printf(arg->prompt, "\n NetBIOS NS: %s, ", 484610b185fSBrian Somers inet_ntoa(ipcp->cfg.ns.nbns[0])); 485610b185fSBrian Somers prompt_Printf(arg->prompt, "%s\n", inet_ntoa(ipcp->cfg.ns.nbns[1])); 4861342caedSBrian Somers 487da477886SBrian Somers prompt_Printf(arg->prompt, " Urgent ports\n"); 488da477886SBrian Somers prompt_Printf(arg->prompt, " TCP: "); 489da477886SBrian Somers if (ipcp->cfg.urgent.tcp.nports == 0) 490442f8495SBrian Somers prompt_Printf(arg->prompt, "none"); 491442f8495SBrian Somers else 492da477886SBrian Somers for (p = 0; p < ipcp->cfg.urgent.tcp.nports; p++) { 493442f8495SBrian Somers if (p) 494442f8495SBrian Somers prompt_Printf(arg->prompt, ", "); 495da477886SBrian Somers prompt_Printf(arg->prompt, "%u", ipcp->cfg.urgent.tcp.port[p]); 496da477886SBrian Somers } 497da477886SBrian Somers prompt_Printf(arg->prompt, "\n UDP: "); 498da477886SBrian Somers if (ipcp->cfg.urgent.udp.nports == 0) 499da477886SBrian Somers prompt_Printf(arg->prompt, "none"); 500da477886SBrian Somers else 501da477886SBrian Somers for (p = 0; p < ipcp->cfg.urgent.udp.nports; p++) { 502da477886SBrian Somers if (p) 503da477886SBrian Somers prompt_Printf(arg->prompt, ", "); 504da477886SBrian Somers prompt_Printf(arg->prompt, "%u", ipcp->cfg.urgent.udp.port[p]); 505442f8495SBrian Somers } 5064c240437SBrian Somers prompt_Printf(arg->prompt, "\n TOS: %s\n\n", 5074c240437SBrian Somers ipcp->cfg.urgent.tos ? "yes" : "no"); 508442f8495SBrian Somers 509610b185fSBrian Somers throughput_disp(&ipcp->throughput, arg->prompt); 5109a0b991fSBrian Somers 511927145beSBrian Somers return 0; 512af57ed9fSAtsushi Murai } 513af57ed9fSAtsushi Murai 514d1a3ea47SBrian Somers int 515dd7e2610SBrian Somers ipcp_vjset(struct cmdargs const *arg) 516d1a3ea47SBrian Somers { 51725092092SBrian Somers if (arg->argc != arg->argn+2) 518d1a3ea47SBrian Somers return -1; 51925092092SBrian Somers if (!strcasecmp(arg->argv[arg->argn], "slots")) { 520d1a3ea47SBrian Somers int slots; 521d1a3ea47SBrian Somers 52225092092SBrian Somers slots = atoi(arg->argv[arg->argn+1]); 523d1a3ea47SBrian Somers if (slots < 4 || slots > 16) 524d1a3ea47SBrian Somers return 1; 5251342caedSBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slots = slots; 526d1a3ea47SBrian Somers return 0; 52725092092SBrian Somers } else if (!strcasecmp(arg->argv[arg->argn], "slotcomp")) { 52825092092SBrian Somers if (!strcasecmp(arg->argv[arg->argn+1], "on")) 5291342caedSBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 1; 53025092092SBrian Somers else if (!strcasecmp(arg->argv[arg->argn+1], "off")) 5311342caedSBrian Somers arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 0; 532d1a3ea47SBrian Somers else 533d1a3ea47SBrian Somers return 2; 534d1a3ea47SBrian Somers return 0; 535d1a3ea47SBrian Somers } 536d1a3ea47SBrian Somers return -1; 537d1a3ea47SBrian Somers } 538d1a3ea47SBrian Somers 5391ae349f5Scvs2svn void 5406d666775SBrian Somers ipcp_Init(struct ipcp *ipcp, struct bundle *bundle, struct link *l, 5416d666775SBrian Somers const struct fsm_parent *parent) 542d1a3ea47SBrian Somers { 543503a7782SBrian Somers struct hostent *hp; 544503a7782SBrian Somers char name[MAXHOSTNAMELEN]; 545182c898aSBrian Somers static const char * const timer_names[] = 5463b0f8d2eSBrian Somers {"IPCP restart", "IPCP openmode", "IPCP stopped"}; 54729e275ceSBrian Somers 548479508cfSBrian Somers fsm_Init(&ipcp->fsm, "IPCP", PROTO_IPCP, 1, IPCP_MAXCODE, LogIPCP, 5493b0f8d2eSBrian Somers bundle, l, parent, &ipcp_Callbacks, timer_names); 550503a7782SBrian Somers 551610b185fSBrian Somers ipcp->route = NULL; 5521342caedSBrian Somers ipcp->cfg.vj.slots = DEF_VJ_STATES; 5531342caedSBrian Somers ipcp->cfg.vj.slotcomp = 1; 554503a7782SBrian Somers memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range); 555503a7782SBrian Somers if (gethostname(name, sizeof name) == 0) { 556503a7782SBrian Somers hp = gethostbyname(name); 5578fa6ebe4SBrian Somers if (hp && hp->h_addrtype == AF_INET) 558503a7782SBrian Somers memcpy(&ipcp->cfg.my_range.ipaddr.s_addr, hp->h_addr, hp->h_length); 559503a7782SBrian Somers } 56030c2f2ffSBrian Somers ipcp->cfg.netmask.s_addr = INADDR_ANY; 561503a7782SBrian Somers memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 562503a7782SBrian Somers iplist_setsrc(&ipcp->cfg.peer_list, ""); 563503a7782SBrian Somers ipcp->cfg.HaveTriggerAddress = 0; 564503a7782SBrian Somers 565d568d6c4SBrian Somers ipcp->cfg.ns.dns[0].s_addr = INADDR_NONE; 566d568d6c4SBrian Somers ipcp->cfg.ns.dns[1].s_addr = INADDR_NONE; 5673edeb0c6SBrian Somers ipcp->cfg.ns.dns_neg = 0; 5683edeb0c6SBrian Somers ipcp->cfg.ns.nbns[0].s_addr = INADDR_ANY; 5693edeb0c6SBrian Somers ipcp->cfg.ns.nbns[1].s_addr = INADDR_ANY; 570cd9647a1SBrian Somers 571da477886SBrian Somers ipcp->cfg.urgent.tcp.nports = ipcp->cfg.urgent.tcp.maxports = NDEFTCPPORTS; 572da477886SBrian Somers ipcp->cfg.urgent.tcp.port = (u_short *)malloc(NDEFTCPPORTS * sizeof(u_short)); 573da477886SBrian Somers memcpy(ipcp->cfg.urgent.tcp.port, default_urgent_tcp_ports, 574da477886SBrian Somers NDEFTCPPORTS * sizeof(u_short)); 5754c240437SBrian Somers ipcp->cfg.urgent.tos = 1; 576da477886SBrian Somers 577da477886SBrian Somers ipcp->cfg.urgent.udp.nports = ipcp->cfg.urgent.udp.maxports = NDEFUDPPORTS; 578da477886SBrian Somers ipcp->cfg.urgent.udp.port = (u_short *)malloc(NDEFUDPPORTS * sizeof(u_short)); 579da477886SBrian Somers memcpy(ipcp->cfg.urgent.udp.port, default_urgent_udp_ports, 580da477886SBrian Somers NDEFUDPPORTS * sizeof(u_short)); 581442f8495SBrian Somers 582479508cfSBrian Somers ipcp->cfg.fsm.timeout = DEF_FSMRETRY; 583479508cfSBrian Somers ipcp->cfg.fsm.maxreq = DEF_FSMTRIES; 584479508cfSBrian Somers ipcp->cfg.fsm.maxtrm = DEF_FSMTRIES; 5851342caedSBrian Somers ipcp->cfg.vj.neg = NEG_ENABLED|NEG_ACCEPTED; 586503a7782SBrian Somers 587eaa4df37SBrian Somers memset(&ipcp->vj, '\0', sizeof ipcp->vj); 588eaa4df37SBrian Somers 589d568d6c4SBrian Somers ipcp->ns.resolv = NULL; 590d568d6c4SBrian Somers ipcp->ns.resolv_nons = NULL; 591d568d6c4SBrian Somers ipcp->ns.writable = 1; 592d568d6c4SBrian Somers ipcp_LoadDNS(ipcp); 593d568d6c4SBrian Somers 594ab2de065SBrian Somers throughput_init(&ipcp->throughput, SAMPLE_PERIOD); 5955a72b6edSBrian Somers memset(ipcp->Queue, '\0', sizeof ipcp->Queue); 596972a1bcfSBrian Somers ipcp_Setup(ipcp, INADDR_NONE); 597d1a3ea47SBrian Somers } 598d1a3ea47SBrian Somers 599af57ed9fSAtsushi Murai void 600442f8495SBrian Somers ipcp_Destroy(struct ipcp *ipcp) 601442f8495SBrian Somers { 602da477886SBrian Somers if (ipcp->cfg.urgent.tcp.maxports) { 603da477886SBrian Somers ipcp->cfg.urgent.tcp.nports = ipcp->cfg.urgent.tcp.maxports = 0; 604da477886SBrian Somers free(ipcp->cfg.urgent.tcp.port); 605da477886SBrian Somers ipcp->cfg.urgent.tcp.port = NULL; 606da477886SBrian Somers } 607da477886SBrian Somers if (ipcp->cfg.urgent.udp.maxports) { 608da477886SBrian Somers ipcp->cfg.urgent.udp.nports = ipcp->cfg.urgent.udp.maxports = 0; 609da477886SBrian Somers free(ipcp->cfg.urgent.udp.port); 610da477886SBrian Somers ipcp->cfg.urgent.udp.port = NULL; 611442f8495SBrian Somers } 612d568d6c4SBrian Somers if (ipcp->ns.resolv != NULL) { 613d568d6c4SBrian Somers free(ipcp->ns.resolv); 614d568d6c4SBrian Somers ipcp->ns.resolv = NULL; 615d568d6c4SBrian Somers } 616d568d6c4SBrian Somers if (ipcp->ns.resolv_nons != NULL) { 617d568d6c4SBrian Somers free(ipcp->ns.resolv_nons); 618d568d6c4SBrian Somers ipcp->ns.resolv_nons = NULL; 619d568d6c4SBrian Somers } 620442f8495SBrian Somers } 621442f8495SBrian Somers 622442f8495SBrian Somers void 623ce828a6eSBrian Somers ipcp_SetLink(struct ipcp *ipcp, struct link *l) 624af57ed9fSAtsushi Murai { 625ce828a6eSBrian Somers ipcp->fsm.link = l; 626af57ed9fSAtsushi Murai } 627549d663dSAtsushi Murai 628ce828a6eSBrian Somers void 629972a1bcfSBrian Somers ipcp_Setup(struct ipcp *ipcp, u_int32_t mask) 630503a7782SBrian Somers { 6318fa6ebe4SBrian Somers struct iface *iface = ipcp->fsm.bundle->iface; 6328fa6ebe4SBrian Somers int pos, n; 633503a7782SBrian Somers 634503a7782SBrian Somers ipcp->fsm.open_mode = 0; 635972a1bcfSBrian Somers ipcp->ifmask.s_addr = mask == INADDR_NONE ? ipcp->cfg.netmask.s_addr : mask; 636503a7782SBrian Somers 637503a7782SBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 6388fa6ebe4SBrian Somers /* Try to give the peer a previously configured IP address */ 6398fa6ebe4SBrian Somers for (n = 0; n < iface->in_addrs; n++) { 6408fa6ebe4SBrian Somers pos = iplist_ip2pos(&ipcp->cfg.peer_list, iface->in_addr[n].brd); 6418fa6ebe4SBrian Somers if (pos != -1) { 6428fa6ebe4SBrian Somers ipcp->cfg.peer_range.ipaddr = 6438fa6ebe4SBrian Somers iplist_setcurpos(&ipcp->cfg.peer_list, pos); 6448fa6ebe4SBrian Somers break; 6458fa6ebe4SBrian Somers } 6468fa6ebe4SBrian Somers } 6478fa6ebe4SBrian Somers if (n == iface->in_addrs) 6488fa6ebe4SBrian Somers /* Ok, so none of 'em fit.... pick a random one */ 649503a7782SBrian Somers ipcp->cfg.peer_range.ipaddr = iplist_setrandpos(&ipcp->cfg.peer_list); 6508fa6ebe4SBrian Somers 651503a7782SBrian Somers ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 652503a7782SBrian Somers ipcp->cfg.peer_range.width = 32; 653503a7782SBrian Somers } 654503a7782SBrian Somers 655503a7782SBrian Somers ipcp->heis1172 = 0; 656503a7782SBrian Somers 657503a7782SBrian Somers ipcp->peer_ip = ipcp->cfg.peer_range.ipaddr; 658503a7782SBrian Somers ipcp->peer_compproto = 0; 6591ae349f5Scvs2svn 6608390b576SBrian Somers if (ipcp->cfg.HaveTriggerAddress) { 661549d663dSAtsushi Murai /* 6625b4c5b00SBrian Somers * Some implementations of PPP require that we send a 6635b4c5b00SBrian Somers * *special* value as our address, even though the rfc specifies 6645b4c5b00SBrian Somers * full negotiation (e.g. "0.0.0.0" or Not "0.0.0.0"). 665549d663dSAtsushi Murai */ 666503a7782SBrian Somers ipcp->my_ip = ipcp->cfg.TriggerAddress; 667dd7e2610SBrian Somers log_Printf(LogIPCP, "Using trigger address %s\n", 668503a7782SBrian Somers inet_ntoa(ipcp->cfg.TriggerAddress)); 6698fa6ebe4SBrian Somers } else { 6708390b576SBrian Somers /* 6718fa6ebe4SBrian Somers * Otherwise, if we've used an IP number before and it's still within 6728fa6ebe4SBrian Somers * the network specified on the ``set ifaddr'' line, we really 6738fa6ebe4SBrian Somers * want to keep that IP number so that we can keep any existing 6748fa6ebe4SBrian Somers * connections that are bound to that IP (assuming we're not 6758fa6ebe4SBrian Somers * ``iface-alias''ing). 6768390b576SBrian Somers */ 6778fa6ebe4SBrian Somers for (n = 0; n < iface->in_addrs; n++) 6788fa6ebe4SBrian Somers if ((iface->in_addr[n].ifa.s_addr & ipcp->cfg.my_range.mask.s_addr) == 6798fa6ebe4SBrian Somers (ipcp->cfg.my_range.ipaddr.s_addr & ipcp->cfg.my_range.mask.s_addr)) { 6808fa6ebe4SBrian Somers ipcp->my_ip = iface->in_addr[n].ifa; 6818fa6ebe4SBrian Somers break; 6828fa6ebe4SBrian Somers } 6838fa6ebe4SBrian Somers if (n == iface->in_addrs) 684503a7782SBrian Somers ipcp->my_ip = ipcp->cfg.my_range.ipaddr; 6858fa6ebe4SBrian Somers } 68629e275ceSBrian Somers 687972a1bcfSBrian Somers if (IsEnabled(ipcp->cfg.vj.neg) 688972a1bcfSBrian Somers #ifndef NORADIUS 689972a1bcfSBrian Somers || (ipcp->fsm.bundle->radius.valid && ipcp->fsm.bundle->radius.vj) 690972a1bcfSBrian Somers #endif 691972a1bcfSBrian Somers ) 692503a7782SBrian Somers ipcp->my_compproto = (PROTO_VJCOMP << 16) + 6931342caedSBrian Somers ((ipcp->cfg.vj.slots - 1) << 8) + 6941342caedSBrian Somers ipcp->cfg.vj.slotcomp; 6951ae349f5Scvs2svn else 696503a7782SBrian Somers ipcp->my_compproto = 0; 6971342caedSBrian Somers sl_compress_init(&ipcp->vj.cslc, ipcp->cfg.vj.slots - 1); 69829e275ceSBrian Somers 699503a7782SBrian Somers ipcp->peer_reject = 0; 700503a7782SBrian Somers ipcp->my_reject = 0; 701d568d6c4SBrian Somers 702d568d6c4SBrian Somers /* Copy startup values into ipcp->dns? */ 703d568d6c4SBrian Somers if (ipcp->cfg.ns.dns[0].s_addr != INADDR_NONE) 704d568d6c4SBrian Somers memcpy(ipcp->dns, ipcp->cfg.ns.dns, sizeof ipcp->dns); 705d568d6c4SBrian Somers else if (ipcp->ns.dns[0].s_addr != INADDR_NONE) 706d568d6c4SBrian Somers memcpy(ipcp->dns, ipcp->ns.dns, sizeof ipcp->dns); 707d568d6c4SBrian Somers else 708d568d6c4SBrian Somers ipcp->dns[0].s_addr = ipcp->dns[1].s_addr = INADDR_ANY; 709d568d6c4SBrian Somers 710d568d6c4SBrian Somers if (ipcp->dns[1].s_addr == INADDR_NONE) 711d568d6c4SBrian Somers ipcp->dns[1] = ipcp->dns[0]; 7121ae349f5Scvs2svn } 7131ae349f5Scvs2svn 714455aabc3SBrian Somers static int 7153afe5ccbSBrian Somers ipcp_doproxyall(struct bundle *bundle, 7163afe5ccbSBrian Somers int (*proxyfun)(struct bundle *, struct in_addr, int), int s) 7173afe5ccbSBrian Somers { 7183afe5ccbSBrian Somers int n, ret; 7193afe5ccbSBrian Somers struct sticky_route *rp; 7203afe5ccbSBrian Somers struct in_addr addr; 7213afe5ccbSBrian Somers struct ipcp *ipcp; 7223afe5ccbSBrian Somers 7233afe5ccbSBrian Somers ipcp = &bundle->ncp.ipcp; 7243afe5ccbSBrian Somers for (rp = ipcp->route; rp != NULL; rp = rp->next) { 725bc76350eSBrian Somers if (rp->mask.s_addr == INADDR_BROADCAST) 7263afe5ccbSBrian Somers continue; 727bc76350eSBrian Somers n = ntohl(INADDR_BROADCAST) - ntohl(rp->mask.s_addr) - 1; 7283afe5ccbSBrian Somers if (n > 0 && n <= 254 && rp->dst.s_addr != INADDR_ANY) { 7293afe5ccbSBrian Somers addr = rp->dst; 7303afe5ccbSBrian Somers while (n--) { 7313afe5ccbSBrian Somers addr.s_addr = htonl(ntohl(addr.s_addr) + 1); 7323afe5ccbSBrian Somers log_Printf(LogDEBUG, "ipcp_doproxyall: %s\n", inet_ntoa(addr)); 7333afe5ccbSBrian Somers ret = (*proxyfun)(bundle, addr, s); 7343afe5ccbSBrian Somers if (!ret) 7353afe5ccbSBrian Somers return ret; 7363afe5ccbSBrian Somers } 7373afe5ccbSBrian Somers } 7383afe5ccbSBrian Somers } 7393afe5ccbSBrian Somers 7403afe5ccbSBrian Somers return 0; 7413afe5ccbSBrian Somers } 7423afe5ccbSBrian Somers 7433afe5ccbSBrian Somers static int 74430c2f2ffSBrian Somers ipcp_SetIPaddress(struct bundle *bundle, struct in_addr myaddr, 74530c2f2ffSBrian Somers struct in_addr hisaddr, int silent) 746455aabc3SBrian Somers { 74768645f39SBrian Somers struct in_addr mask, oaddr, none = { INADDR_ANY }; 748455aabc3SBrian Somers 749bc76350eSBrian Somers mask = addr2mask(myaddr); 750455aabc3SBrian Somers 751972a1bcfSBrian Somers if (bundle->ncp.ipcp.ifmask.s_addr != INADDR_ANY && 752bc76350eSBrian Somers (bundle->ncp.ipcp.ifmask.s_addr & mask.s_addr) == mask.s_addr) 753bc76350eSBrian Somers mask.s_addr = bundle->ncp.ipcp.ifmask.s_addr; 754455aabc3SBrian Somers 7558fa6ebe4SBrian Somers oaddr.s_addr = bundle->iface->in_addrs ? 7568fa6ebe4SBrian Somers bundle->iface->in_addr[0].ifa.s_addr : INADDR_ANY; 7578fa6ebe4SBrian Somers if (!iface_inAdd(bundle->iface, myaddr, mask, hisaddr, 7588fa6ebe4SBrian Somers IFACE_ADD_FIRST|IFACE_FORCE_ADD)) 7598fa6ebe4SBrian Somers return -1; 760455aabc3SBrian Somers 7618fa6ebe4SBrian Somers if (!Enabled(bundle, OPT_IFACEALIAS) && bundle->iface->in_addrs > 1 7628fa6ebe4SBrian Somers && myaddr.s_addr != oaddr.s_addr) 7638fa6ebe4SBrian Somers /* Nuke the old one */ 7648fa6ebe4SBrian Somers iface_inDelete(bundle->iface, oaddr); 765455aabc3SBrian Somers 7663afe5ccbSBrian Somers if (bundle->ncp.ipcp.cfg.sendpipe > 0 || bundle->ncp.ipcp.cfg.recvpipe > 0) 7673afe5ccbSBrian Somers bundle_SetRoute(bundle, RTM_CHANGE, hisaddr, myaddr, none, 0, 0); 7683afe5ccbSBrian Somers 769610b185fSBrian Somers if (Enabled(bundle, OPT_SROUTES)) 770d568d6c4SBrian Somers route_Change(bundle, bundle->ncp.ipcp.route, myaddr, hisaddr, 771d568d6c4SBrian Somers bundle->ncp.ipcp.ns.dns); 772610b185fSBrian Somers 773972a1bcfSBrian Somers #ifndef NORADIUS 774972a1bcfSBrian Somers if (bundle->radius.valid) 775d568d6c4SBrian Somers route_Change(bundle, bundle->radius.routes, myaddr, hisaddr, 776d568d6c4SBrian Somers bundle->ncp.ipcp.ns.dns); 777972a1bcfSBrian Somers #endif 778972a1bcfSBrian Somers 7793afe5ccbSBrian Somers if (Enabled(bundle, OPT_PROXY) || Enabled(bundle, OPT_PROXYALL)) { 7808fa6ebe4SBrian Somers int s = ID0socket(AF_INET, SOCK_DGRAM, 0); 7818fa6ebe4SBrian Somers if (s < 0) 7828fa6ebe4SBrian Somers log_Printf(LogERROR, "ipcp_SetIPaddress: socket(): %s\n", 7838fa6ebe4SBrian Somers strerror(errno)); 7848fa6ebe4SBrian Somers else { 7853afe5ccbSBrian Somers if (Enabled(bundle, OPT_PROXYALL)) 7863afe5ccbSBrian Somers ipcp_doproxyall(bundle, arp_SetProxy, s); 7873afe5ccbSBrian Somers else if (Enabled(bundle, OPT_PROXY)) 7888fa6ebe4SBrian Somers arp_SetProxy(bundle, hisaddr, s); 789455aabc3SBrian Somers close(s); 7908fa6ebe4SBrian Somers } 7918fa6ebe4SBrian Somers } 7928fa6ebe4SBrian Somers 7938fa6ebe4SBrian Somers return 0; 794455aabc3SBrian Somers } 795455aabc3SBrian Somers 796455aabc3SBrian Somers static struct in_addr 7978fa6ebe4SBrian Somers ChooseHisAddr(struct bundle *bundle, struct in_addr gw) 798455aabc3SBrian Somers { 799455aabc3SBrian Somers struct in_addr try; 8003a2e4f62SBrian Somers u_long f; 801455aabc3SBrian Somers 8025828db6dSBrian Somers for (f = 0; f < bundle->ncp.ipcp.cfg.peer_list.nItems; f++) { 8035828db6dSBrian Somers try = iplist_next(&bundle->ncp.ipcp.cfg.peer_list); 8043a2e4f62SBrian Somers log_Printf(LogDEBUG, "ChooseHisAddr: Check item %ld (%s)\n", 805455aabc3SBrian Somers f, inet_ntoa(try)); 80630c2f2ffSBrian Somers if (ipcp_SetIPaddress(bundle, gw, try, 1) == 0) { 807dd7e2610SBrian Somers log_Printf(LogIPCP, "Selected IP address %s\n", inet_ntoa(try)); 808455aabc3SBrian Somers break; 809455aabc3SBrian Somers } 810455aabc3SBrian Somers } 811455aabc3SBrian Somers 8125828db6dSBrian Somers if (f == bundle->ncp.ipcp.cfg.peer_list.nItems) { 813dd7e2610SBrian Somers log_Printf(LogDEBUG, "ChooseHisAddr: All addresses in use !\n"); 814455aabc3SBrian Somers try.s_addr = INADDR_ANY; 815455aabc3SBrian Somers } 816455aabc3SBrian Somers 817455aabc3SBrian Somers return try; 818af57ed9fSAtsushi Murai } 819af57ed9fSAtsushi Murai 820af57ed9fSAtsushi Murai static void 821479508cfSBrian Somers IpcpInitRestartCounter(struct fsm *fp, int what) 822af57ed9fSAtsushi Murai { 8237308ec68SBrian Somers /* Set fsm timer load */ 824cd9647a1SBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 825cd9647a1SBrian Somers 826479508cfSBrian Somers fp->FsmTimer.load = ipcp->cfg.fsm.timeout * SECTICKS; 827479508cfSBrian Somers switch (what) { 828479508cfSBrian Somers case FSM_REQ_TIMER: 829479508cfSBrian Somers fp->restart = ipcp->cfg.fsm.maxreq; 830479508cfSBrian Somers break; 831479508cfSBrian Somers case FSM_TRM_TIMER: 832479508cfSBrian Somers fp->restart = ipcp->cfg.fsm.maxtrm; 833479508cfSBrian Somers break; 834479508cfSBrian Somers default: 835479508cfSBrian Somers fp->restart = 1; 836479508cfSBrian Somers break; 837479508cfSBrian Somers } 838af57ed9fSAtsushi Murai } 839af57ed9fSAtsushi Murai 840af57ed9fSAtsushi Murai static void 841944f7098SBrian Somers IpcpSendConfigReq(struct fsm *fp) 842af57ed9fSAtsushi Murai { 8437308ec68SBrian Somers /* Send config REQ please */ 8448c07a7b2SBrian Somers struct physical *p = link2physical(fp->link); 845aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 8463edeb0c6SBrian Somers u_char buff[24]; 8472267893fSBrian Somers struct lcp_opt *o; 848af57ed9fSAtsushi Murai 8492267893fSBrian Somers o = (struct lcp_opt *)buff; 85030c2f2ffSBrian Somers 851dd7e2610SBrian Somers if ((p && !physical_IsSync(p)) || !REJECTED(ipcp, TY_IPADDR)) { 8529e8ec64bSBrian Somers memcpy(o->data, &ipcp->my_ip.s_addr, 4); 8532267893fSBrian Somers INC_LCP_OPT(TY_IPADDR, 6, o); 8540053cc58SBrian Somers } 8550053cc58SBrian Somers 856e43ebac1SBrian Somers if (ipcp->my_compproto && !REJECTED(ipcp, TY_COMPPROTO)) { 85783d1af55SBrian Somers if (ipcp->heis1172) { 8589e8ec64bSBrian Somers u_int16_t proto = PROTO_VJCOMP; 8599e8ec64bSBrian Somers 8609e8ec64bSBrian Somers ua_htons(&proto, o->data); 8612267893fSBrian Somers INC_LCP_OPT(TY_COMPPROTO, 4, o); 8620053cc58SBrian Somers } else { 8637686a200SBrian Somers struct compreq req; 8647686a200SBrian Somers 8657686a200SBrian Somers req.proto = htons(ipcp->my_compproto >> 16); 8667686a200SBrian Somers req.slots = (ipcp->my_compproto >> 8) & 255; 8677686a200SBrian Somers req.compcid = ipcp->my_compproto & 1; 8687686a200SBrian Somers memcpy(o->data, &req, 4); 8692267893fSBrian Somers INC_LCP_OPT(TY_COMPPROTO, 6, o); 8700053cc58SBrian Somers } 871af57ed9fSAtsushi Murai } 8722267893fSBrian Somers 8733edeb0c6SBrian Somers if (IsEnabled(ipcp->cfg.ns.dns_neg) && 8747d39b1e3SBrian Somers !REJECTED(ipcp, TY_PRIMARY_DNS - TY_ADJUST_NS)) { 875d568d6c4SBrian Somers memcpy(o->data, &ipcp->dns[0].s_addr, 4); 8763edeb0c6SBrian Somers INC_LCP_OPT(TY_PRIMARY_DNS, 6, o); 8777d39b1e3SBrian Somers } 8787d39b1e3SBrian Somers 8797d39b1e3SBrian Somers if (IsEnabled(ipcp->cfg.ns.dns_neg) && 8807d39b1e3SBrian Somers !REJECTED(ipcp, TY_SECONDARY_DNS - TY_ADJUST_NS)) { 881d568d6c4SBrian Somers memcpy(o->data, &ipcp->dns[1].s_addr, 4); 8823edeb0c6SBrian Somers INC_LCP_OPT(TY_SECONDARY_DNS, 6, o); 8833edeb0c6SBrian Somers } 8843edeb0c6SBrian Somers 885411675baSBrian Somers fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff, 886411675baSBrian Somers MB_IPCPOUT); 887af57ed9fSAtsushi Murai } 888af57ed9fSAtsushi Murai 889af57ed9fSAtsushi Murai static void 8902267893fSBrian Somers IpcpSentTerminateReq(struct fsm *fp) 891af57ed9fSAtsushi Murai { 8927308ec68SBrian Somers /* Term REQ just sent by FSM */ 893af57ed9fSAtsushi Murai } 894af57ed9fSAtsushi Murai 895af57ed9fSAtsushi Murai static void 8962267893fSBrian Somers IpcpSendTerminateAck(struct fsm *fp, u_char id) 897af57ed9fSAtsushi Murai { 8987308ec68SBrian Somers /* Send Term ACK please */ 899411675baSBrian Somers fsm_Output(fp, CODE_TERMACK, id, NULL, 0, MB_IPCPOUT); 900af57ed9fSAtsushi Murai } 901af57ed9fSAtsushi Murai 902af57ed9fSAtsushi Murai static void 903944f7098SBrian Somers IpcpLayerStart(struct fsm *fp) 904af57ed9fSAtsushi Murai { 9057308ec68SBrian Somers /* We're about to start up ! */ 906897f9429SBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 907897f9429SBrian Somers 9083a2e4f62SBrian Somers log_Printf(LogIPCP, "%s: LayerStart.\n", fp->link->name); 909897f9429SBrian Somers throughput_start(&ipcp->throughput, "IPCP throughput", 910897f9429SBrian Somers Enabled(fp->bundle, OPT_THROUGHPUT)); 911479508cfSBrian Somers fp->more.reqs = fp->more.naks = fp->more.rejs = ipcp->cfg.fsm.maxreq * 3; 912af57ed9fSAtsushi Murai } 913af57ed9fSAtsushi Murai 914af57ed9fSAtsushi Murai static void 915944f7098SBrian Somers IpcpLayerFinish(struct fsm *fp) 916af57ed9fSAtsushi Murai { 9177308ec68SBrian Somers /* We're now down */ 918897f9429SBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 919897f9429SBrian Somers 9203a2e4f62SBrian Somers log_Printf(LogIPCP, "%s: LayerFinish.\n", fp->link->name); 921897f9429SBrian Somers throughput_stop(&ipcp->throughput); 922897f9429SBrian Somers throughput_log(&ipcp->throughput, LogIPCP, NULL); 9231ae349f5Scvs2svn } 9241ae349f5Scvs2svn 92568a0f0ccSBrian Somers void 926dd7e2610SBrian Somers ipcp_CleanInterface(struct ipcp *ipcp) 92768a0f0ccSBrian Somers { 9288fa6ebe4SBrian Somers struct iface *iface = ipcp->fsm.bundle->iface; 92968a0f0ccSBrian Somers 9303afe5ccbSBrian Somers if (iface->in_addrs && (Enabled(ipcp->fsm.bundle, OPT_PROXY) || 9313afe5ccbSBrian Somers Enabled(ipcp->fsm.bundle, OPT_PROXYALL))) { 9328fa6ebe4SBrian Somers int s = ID0socket(AF_INET, SOCK_DGRAM, 0); 9338fa6ebe4SBrian Somers if (s < 0) 9348fa6ebe4SBrian Somers log_Printf(LogERROR, "ipcp_CleanInterface: socket: %s\n", 93568a0f0ccSBrian Somers strerror(errno)); 9368fa6ebe4SBrian Somers else { 9373afe5ccbSBrian Somers if (Enabled(ipcp->fsm.bundle, OPT_PROXYALL)) 9383afe5ccbSBrian Somers ipcp_doproxyall(ipcp->fsm.bundle, arp_ClearProxy, s); 9393afe5ccbSBrian Somers else if (Enabled(ipcp->fsm.bundle, OPT_PROXY)) 9408fa6ebe4SBrian Somers arp_ClearProxy(ipcp->fsm.bundle, iface->in_addr[0].brd, s); 9418fa6ebe4SBrian Somers close(s); 9428fa6ebe4SBrian Somers } 94368a0f0ccSBrian Somers } 94468a0f0ccSBrian Somers 9458fa6ebe4SBrian Somers iface_inClear(ipcp->fsm.bundle->iface, IFACE_CLEAR_ALL); 946af57ed9fSAtsushi Murai } 947af57ed9fSAtsushi Murai 948af57ed9fSAtsushi Murai static void 949944f7098SBrian Somers IpcpLayerDown(struct fsm *fp) 950af57ed9fSAtsushi Murai { 9517308ec68SBrian Somers /* About to come down */ 952aa857470SBrian Somers static int recursing; 953aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 954455aabc3SBrian Somers const char *s; 955455aabc3SBrian Somers 956aa857470SBrian Somers if (!recursing++) { 9578fa6ebe4SBrian Somers if (ipcp->fsm.bundle->iface->in_addrs) 9588fa6ebe4SBrian Somers s = inet_ntoa(ipcp->fsm.bundle->iface->in_addr[0].ifa); 9598fa6ebe4SBrian Somers else 9608fa6ebe4SBrian Somers s = "Interface configuration error !"; 9613a2e4f62SBrian Somers log_Printf(LogIPCP, "%s: LayerDown: %s\n", fp->link->name, s); 962455aabc3SBrian Somers 963794c9bbcSBrian Somers #ifndef NORADIUS 964794c9bbcSBrian Somers radius_Account(&fp->bundle->radius, &fp->bundle->radacct, 965794c9bbcSBrian Somers fp->bundle->links, RAD_STOP, &ipcp->peer_ip, &ipcp->ifmask, 966794c9bbcSBrian Somers &ipcp->throughput); 967794c9bbcSBrian Somers #endif 968794c9bbcSBrian Somers 969455aabc3SBrian Somers /* 970455aabc3SBrian Somers * XXX this stuff should really live in the FSM. Our config should 971455aabc3SBrian Somers * associate executable sections in files with events. 972455aabc3SBrian Somers */ 97330291ffbSBrian Somers if (system_Select(fp->bundle, s, LINKDOWNFILE, NULL, NULL) < 0) { 97449052c95SBrian Somers if (bundle_GetLabel(fp->bundle)) { 975dd7e2610SBrian Somers if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle), 97630291ffbSBrian Somers LINKDOWNFILE, NULL, NULL) < 0) 97730291ffbSBrian Somers system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL); 978455aabc3SBrian Somers } else 97930291ffbSBrian Somers system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL); 980af57ed9fSAtsushi Murai } 981af57ed9fSAtsushi Murai 982972a1bcfSBrian Somers ipcp_Setup(ipcp, INADDR_NONE); 9831ae349f5Scvs2svn } 984aa857470SBrian Somers recursing--; 985aa857470SBrian Somers } 9861ae349f5Scvs2svn 987dd0645c5SBrian Somers int 988dd0645c5SBrian Somers ipcp_InterfaceUp(struct ipcp *ipcp) 989dd0645c5SBrian Somers { 990dd0645c5SBrian Somers if (ipcp_SetIPaddress(ipcp->fsm.bundle, ipcp->my_ip, ipcp->peer_ip, 0) < 0) { 991a33b2ef7SBrian Somers log_Printf(LogERROR, "ipcp_InterfaceUp: unable to set ip address\n"); 992dd0645c5SBrian Somers return 0; 993dd0645c5SBrian Somers } 994dd0645c5SBrian Somers 99567b072f7SBrian Somers #ifndef NONAT 99667b072f7SBrian Somers if (ipcp->fsm.bundle->NatEnabled) 997615ad4f9SBrian Somers PacketAliasSetAddress(ipcp->my_ip); 998dd0645c5SBrian Somers #endif 999dd0645c5SBrian Somers 1000dd0645c5SBrian Somers return 1; 1001dd0645c5SBrian Somers } 1002dd0645c5SBrian Somers 10036f384573SBrian Somers static int 1004944f7098SBrian Somers IpcpLayerUp(struct fsm *fp) 1005af57ed9fSAtsushi Murai { 10067308ec68SBrian Somers /* We're now up */ 1007aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 10088fa6ebe4SBrian Somers char tbuff[16]; 1009af57ed9fSAtsushi Murai 10103a2e4f62SBrian Somers log_Printf(LogIPCP, "%s: LayerUp.\n", fp->link->name); 10118fa6ebe4SBrian Somers snprintf(tbuff, sizeof tbuff, "%s", inet_ntoa(ipcp->my_ip)); 10128fa6ebe4SBrian Somers log_Printf(LogIPCP, "myaddr %s hisaddr = %s\n", 10138fa6ebe4SBrian Somers tbuff, inet_ntoa(ipcp->peer_ip)); 101403604f35SBrian Somers 1015503a7782SBrian Somers if (ipcp->peer_compproto >> 16 == PROTO_VJCOMP) 1016eaa4df37SBrian Somers sl_compress_init(&ipcp->vj.cslc, (ipcp->peer_compproto >> 8) & 255); 101703604f35SBrian Somers 1018dd0645c5SBrian Somers if (!ipcp_InterfaceUp(ipcp)) 10196f384573SBrian Somers return 0; 1020455aabc3SBrian Somers 1021794c9bbcSBrian Somers #ifndef NORADIUS 1022794c9bbcSBrian Somers radius_Account(&fp->bundle->radius, &fp->bundle->radacct, fp->bundle->links, 1023794c9bbcSBrian Somers RAD_START, &ipcp->peer_ip, &ipcp->ifmask, &ipcp->throughput); 1024794c9bbcSBrian Somers #endif 1025794c9bbcSBrian Somers 1026455aabc3SBrian Somers /* 1027455aabc3SBrian Somers * XXX this stuff should really live in the FSM. Our config should 1028455aabc3SBrian Somers * associate executable sections in files with events. 1029455aabc3SBrian Somers */ 10308fa6ebe4SBrian Somers if (system_Select(fp->bundle, tbuff, LINKUPFILE, NULL, NULL) < 0) { 103149052c95SBrian Somers if (bundle_GetLabel(fp->bundle)) { 1032dd7e2610SBrian Somers if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle), 103330291ffbSBrian Somers LINKUPFILE, NULL, NULL) < 0) 103430291ffbSBrian Somers system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL); 1035455aabc3SBrian Somers } else 103630291ffbSBrian Somers system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL); 1037af57ed9fSAtsushi Murai } 1038af57ed9fSAtsushi Murai 1039479508cfSBrian Somers fp->more.reqs = fp->more.naks = fp->more.rejs = ipcp->cfg.fsm.maxreq * 3; 10400f2f3eb3SBrian Somers log_DisplayPrompts(); 1041479508cfSBrian Somers 10426f384573SBrian Somers return 1; 1043af57ed9fSAtsushi Murai } 1044af57ed9fSAtsushi Murai 1045af57ed9fSAtsushi Murai static int 10468fa6ebe4SBrian Somers AcceptableAddr(const struct in_range *prange, struct in_addr ipaddr) 1047af57ed9fSAtsushi Murai { 10487308ec68SBrian Somers /* Is the given IP in the given range ? */ 1049057df964SBrian Somers return (prange->ipaddr.s_addr & prange->mask.s_addr) == 1050057df964SBrian Somers (ipaddr.s_addr & prange->mask.s_addr) && ipaddr.s_addr; 1051af57ed9fSAtsushi Murai } 1052af57ed9fSAtsushi Murai 1053af57ed9fSAtsushi Murai static void 105430c2f2ffSBrian Somers IpcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, 105530c2f2ffSBrian Somers struct fsm_decode *dec) 1056af57ed9fSAtsushi Murai { 10577308ec68SBrian Somers /* Deal with incoming PROTO_IPCP */ 10588fa6ebe4SBrian Somers struct iface *iface = fp->bundle->iface; 1059aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 1060d568d6c4SBrian Somers int type, length, gotdnsnak, n; 1061fe3125a0SBrian Somers u_int32_t compproto; 1062af57ed9fSAtsushi Murai struct compreq *pcomp; 1063d568d6c4SBrian Somers struct in_addr ipaddr, dstipaddr, have_ip; 106430c2f2ffSBrian Somers char tbuff[100], tbuff2[100]; 1065af57ed9fSAtsushi Murai 10663edeb0c6SBrian Somers gotdnsnak = 0; 1067af57ed9fSAtsushi Murai 1068af57ed9fSAtsushi Murai while (plen >= sizeof(struct fsmconfig)) { 1069af57ed9fSAtsushi Murai type = *cp; 1070af57ed9fSAtsushi Murai length = cp[1]; 1071d47dceb8SBrian Somers 1072d47dceb8SBrian Somers if (length == 0) { 1073dd7e2610SBrian Somers log_Printf(LogIPCP, "%s: IPCP size zero\n", fp->link->name); 1074d47dceb8SBrian Somers break; 1075d47dceb8SBrian Somers } 1076d47dceb8SBrian Somers 1077d6d3eeabSBrian Somers snprintf(tbuff, sizeof tbuff, " %s[%d] ", protoname(type), length); 1078af57ed9fSAtsushi Murai 1079af57ed9fSAtsushi Murai switch (type) { 1080af57ed9fSAtsushi Murai case TY_IPADDR: /* RFC1332 */ 10819e8ec64bSBrian Somers memcpy(&ipaddr.s_addr, cp + 2, 4); 1082dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 1083af57ed9fSAtsushi Murai 10849780ef31SBrian Somers switch (mode_type) { 1085af57ed9fSAtsushi Murai case MODE_REQ: 1086503a7782SBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 1087f5fb6bd0SBrian Somers if (ipaddr.s_addr == INADDR_ANY || 1088503a7782SBrian Somers iplist_ip2pos(&ipcp->cfg.peer_list, ipaddr) < 0 || 108930c2f2ffSBrian Somers ipcp_SetIPaddress(fp->bundle, ipcp->cfg.my_range.ipaddr, 109030c2f2ffSBrian Somers ipaddr, 1)) { 1091dd7e2610SBrian Somers log_Printf(LogIPCP, "%s: Address invalid or already in use\n", 1092bcc332bdSBrian Somers inet_ntoa(ipaddr)); 10938390b576SBrian Somers /* 10948fa6ebe4SBrian Somers * If we've already had a valid address configured for the peer, 10958fa6ebe4SBrian Somers * try NAKing with that so that we don't have to upset things 10968fa6ebe4SBrian Somers * too much. 10978390b576SBrian Somers */ 10988fa6ebe4SBrian Somers for (n = 0; n < iface->in_addrs; n++) 10998fa6ebe4SBrian Somers if (iplist_ip2pos(&ipcp->cfg.peer_list, iface->in_addr[n].brd) 11008fa6ebe4SBrian Somers >=0) { 11018fa6ebe4SBrian Somers ipcp->peer_ip = iface->in_addr[n].brd; 11028fa6ebe4SBrian Somers break; 11038fa6ebe4SBrian Somers } 11048fa6ebe4SBrian Somers 11058fa6ebe4SBrian Somers if (n == iface->in_addrs) 11068390b576SBrian Somers /* Just pick an IP number from our list */ 1107503a7782SBrian Somers ipcp->peer_ip = ChooseHisAddr 110830c2f2ffSBrian Somers (fp->bundle, ipcp->cfg.my_range.ipaddr); 11098390b576SBrian Somers 1110503a7782SBrian Somers if (ipcp->peer_ip.s_addr == INADDR_ANY) { 111130c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 111230c2f2ffSBrian Somers dec->rejend += length; 1113bcc332bdSBrian Somers } else { 111430c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 111530c2f2ffSBrian Somers memcpy(dec->nakend + 2, &ipcp->peer_ip.s_addr, length - 2); 111630c2f2ffSBrian Somers dec->nakend += length; 1117bcc332bdSBrian Somers } 1118bcc332bdSBrian Somers break; 1119bcc332bdSBrian Somers } 1120503a7782SBrian Somers } else if (!AcceptableAddr(&ipcp->cfg.peer_range, ipaddr)) { 1121af57ed9fSAtsushi Murai /* 11228390b576SBrian Somers * If destination address is not acceptable, NAK with what we 1123944f7098SBrian Somers * want to use. 1124af57ed9fSAtsushi Murai */ 112530c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 11268fa6ebe4SBrian Somers for (n = 0; n < iface->in_addrs; n++) 11278fa6ebe4SBrian Somers if ((iface->in_addr[n].brd.s_addr & 11288fa6ebe4SBrian Somers ipcp->cfg.peer_range.mask.s_addr) 11298fa6ebe4SBrian Somers == (ipcp->cfg.peer_range.ipaddr.s_addr & 11308fa6ebe4SBrian Somers ipcp->cfg.peer_range.mask.s_addr)) { 11318390b576SBrian Somers /* We prefer the already-configured address */ 11328fa6ebe4SBrian Somers memcpy(dec->nakend + 2, &iface->in_addr[n].brd.s_addr, 11338fa6ebe4SBrian Somers length - 2); 11348fa6ebe4SBrian Somers break; 11358fa6ebe4SBrian Somers } 11368fa6ebe4SBrian Somers 11378fa6ebe4SBrian Somers if (n == iface->in_addrs) 113830c2f2ffSBrian Somers memcpy(dec->nakend + 2, &ipcp->peer_ip.s_addr, length - 2); 11398fa6ebe4SBrian Somers 114030c2f2ffSBrian Somers dec->nakend += length; 1141af57ed9fSAtsushi Murai break; 1142af57ed9fSAtsushi Murai } 1143503a7782SBrian Somers ipcp->peer_ip = ipaddr; 114430c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 114530c2f2ffSBrian Somers dec->ackend += length; 1146af57ed9fSAtsushi Murai break; 11478fa6ebe4SBrian Somers 1148af57ed9fSAtsushi Murai case MODE_NAK: 1149503a7782SBrian Somers if (AcceptableAddr(&ipcp->cfg.my_range, ipaddr)) { 1150bcc332bdSBrian Somers /* Use address suggested by peer */ 115170ee81ffSBrian Somers snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s ", tbuff, 1152503a7782SBrian Somers inet_ntoa(ipcp->my_ip)); 1153dd7e2610SBrian Somers log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 1154503a7782SBrian Somers ipcp->my_ip = ipaddr; 11551d1fc017SBrian Somers bundle_AdjustFilters(fp->bundle, &ipcp->my_ip, NULL); 1156bcc332bdSBrian Somers } else { 1157dd7e2610SBrian Somers log_Printf(log_IsKept(LogIPCP) ? LogIPCP : LogPHASE, 11588390b576SBrian Somers "%s: Unacceptable address!\n", inet_ntoa(ipaddr)); 1159dd7e2610SBrian Somers fsm_Close(&ipcp->fsm); 1160af57ed9fSAtsushi Murai } 1161af57ed9fSAtsushi Murai break; 11628fa6ebe4SBrian Somers 1163af57ed9fSAtsushi Murai case MODE_REJ: 1164503a7782SBrian Somers ipcp->peer_reject |= (1 << type); 1165af57ed9fSAtsushi Murai break; 1166af57ed9fSAtsushi Murai } 1167af57ed9fSAtsushi Murai break; 11688fa6ebe4SBrian Somers 1169af57ed9fSAtsushi Murai case TY_COMPPROTO: 11707686a200SBrian Somers pcomp = (struct compreq *)(cp + 2); 11717686a200SBrian Somers compproto = (ntohs(pcomp->proto) << 16) + (pcomp->slots << 8) + 11727686a200SBrian Somers pcomp->compcid; 1173dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto)); 1174af57ed9fSAtsushi Murai 11759780ef31SBrian Somers switch (mode_type) { 1176af57ed9fSAtsushi Murai case MODE_REQ: 11771342caedSBrian Somers if (!IsAccepted(ipcp->cfg.vj.neg)) { 117830c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 117930c2f2ffSBrian Somers dec->rejend += length; 1180af57ed9fSAtsushi Murai } else { 1181af57ed9fSAtsushi Murai switch (length) { 1182af57ed9fSAtsushi Murai case 4: /* RFC1172 */ 1183af57ed9fSAtsushi Murai if (ntohs(pcomp->proto) == PROTO_VJCOMP) { 11847686a200SBrian Somers log_Printf(LogWARN, "Peer is speaking RFC1172 compression " 11857686a200SBrian Somers "protocol !\n"); 118683d1af55SBrian Somers ipcp->heis1172 = 1; 1187503a7782SBrian Somers ipcp->peer_compproto = compproto; 118830c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 118930c2f2ffSBrian Somers dec->ackend += length; 1190af57ed9fSAtsushi Murai } else { 119130c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 1192af57ed9fSAtsushi Murai pcomp->proto = htons(PROTO_VJCOMP); 119330c2f2ffSBrian Somers memcpy(dec->nakend+2, &pcomp, 2); 119430c2f2ffSBrian Somers dec->nakend += length; 1195af57ed9fSAtsushi Murai } 1196af57ed9fSAtsushi Murai break; 1197af57ed9fSAtsushi Murai case 6: /* RFC1332 */ 11987686a200SBrian Somers if (ntohs(pcomp->proto) == PROTO_VJCOMP) { 11997686a200SBrian Somers if (pcomp->slots <= MAX_VJ_STATES 1200503a7782SBrian Somers && pcomp->slots >= MIN_VJ_STATES) { 12017686a200SBrian Somers /* Ok, we can do that */ 1202503a7782SBrian Somers ipcp->peer_compproto = compproto; 120383d1af55SBrian Somers ipcp->heis1172 = 0; 120430c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 120530c2f2ffSBrian Somers dec->ackend += length; 1206af57ed9fSAtsushi Murai } else { 12077686a200SBrian Somers /* Get as close as we can to what he wants */ 12087686a200SBrian Somers ipcp->heis1172 = 0; 12097686a200SBrian Somers memcpy(dec->nakend, cp, 2); 12107686a200SBrian Somers pcomp->slots = pcomp->slots < MIN_VJ_STATES ? 12117686a200SBrian Somers MIN_VJ_STATES : MAX_VJ_STATES; 12127686a200SBrian Somers memcpy(dec->nakend+2, &pcomp, sizeof pcomp); 12137686a200SBrian Somers dec->nakend += length; 12147686a200SBrian Somers } 12157686a200SBrian Somers } else { 12167686a200SBrian Somers /* What we really want */ 121730c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 1218af57ed9fSAtsushi Murai pcomp->proto = htons(PROTO_VJCOMP); 1219503a7782SBrian Somers pcomp->slots = DEF_VJ_STATES; 12207686a200SBrian Somers pcomp->compcid = 1; 122130c2f2ffSBrian Somers memcpy(dec->nakend+2, &pcomp, sizeof pcomp); 122230c2f2ffSBrian Somers dec->nakend += length; 1223af57ed9fSAtsushi Murai } 1224af57ed9fSAtsushi Murai break; 1225af57ed9fSAtsushi Murai default: 122630c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 122730c2f2ffSBrian Somers dec->rejend += length; 1228af57ed9fSAtsushi Murai break; 1229af57ed9fSAtsushi Murai } 1230af57ed9fSAtsushi Murai } 1231af57ed9fSAtsushi Murai break; 12328fa6ebe4SBrian Somers 1233af57ed9fSAtsushi Murai case MODE_NAK: 12347686a200SBrian Somers if (ntohs(pcomp->proto) == PROTO_VJCOMP) { 12357686a200SBrian Somers if (pcomp->slots > MAX_VJ_STATES) 12367686a200SBrian Somers pcomp->slots = MAX_VJ_STATES; 12377686a200SBrian Somers else if (pcomp->slots < MIN_VJ_STATES) 12387686a200SBrian Somers pcomp->slots = MIN_VJ_STATES; 12397686a200SBrian Somers compproto = (ntohs(pcomp->proto) << 16) + (pcomp->slots << 8) + 12407686a200SBrian Somers pcomp->compcid; 12417686a200SBrian Somers } else 12427686a200SBrian Somers compproto = 0; 1243dd7e2610SBrian Somers log_Printf(LogIPCP, "%s changing compproto: %08x --> %08x\n", 1244503a7782SBrian Somers tbuff, ipcp->my_compproto, compproto); 1245503a7782SBrian Somers ipcp->my_compproto = compproto; 1246af57ed9fSAtsushi Murai break; 12478fa6ebe4SBrian Somers 1248af57ed9fSAtsushi Murai case MODE_REJ: 1249503a7782SBrian Somers ipcp->peer_reject |= (1 << type); 1250af57ed9fSAtsushi Murai break; 1251af57ed9fSAtsushi Murai } 1252af57ed9fSAtsushi Murai break; 12538fa6ebe4SBrian Somers 1254af57ed9fSAtsushi Murai case TY_IPADDRS: /* RFC1172 */ 12559e8ec64bSBrian Somers memcpy(&ipaddr.s_addr, cp + 2, 4); 12569e8ec64bSBrian Somers memcpy(&dstipaddr.s_addr, cp + 6, 4); 125770ee81ffSBrian Somers snprintf(tbuff2, sizeof tbuff2, "%s %s,", tbuff, inet_ntoa(ipaddr)); 1258dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr)); 1259af57ed9fSAtsushi Murai 12609780ef31SBrian Somers switch (mode_type) { 1261af57ed9fSAtsushi Murai case MODE_REQ: 12625d9e6103SBrian Somers memcpy(dec->rejend, cp, length); 12635d9e6103SBrian Somers dec->rejend += length; 1264af57ed9fSAtsushi Murai break; 12658fa6ebe4SBrian Somers 1266af57ed9fSAtsushi Murai case MODE_NAK: 1267af57ed9fSAtsushi Murai case MODE_REJ: 1268af57ed9fSAtsushi Murai break; 1269af57ed9fSAtsushi Murai } 1270af57ed9fSAtsushi Murai break; 1271d8e55738SJordan K. Hubbard 12723edeb0c6SBrian Somers case TY_PRIMARY_DNS: /* DNS negotiation (rfc1877) */ 1273d8e55738SJordan K. Hubbard case TY_SECONDARY_DNS: 12749e8ec64bSBrian Somers memcpy(&ipaddr.s_addr, cp + 2, 4); 1275dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 12763edeb0c6SBrian Somers 12779780ef31SBrian Somers switch (mode_type) { 1278d8e55738SJordan K. Hubbard case MODE_REQ: 12793edeb0c6SBrian Somers if (!IsAccepted(ipcp->cfg.ns.dns_neg)) { 12803edeb0c6SBrian Somers ipcp->my_reject |= (1 << (type - TY_ADJUST_NS)); 128130c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 128230c2f2ffSBrian Somers dec->rejend += length; 1283d8e55738SJordan K. Hubbard break; 1284d8e55738SJordan K. Hubbard } 1285d568d6c4SBrian Somers have_ip = ipcp->dns[type == TY_PRIMARY_DNS ? 0 : 1]; 1286d568d6c4SBrian Somers 1287d568d6c4SBrian Somers if (type == TY_PRIMARY_DNS && ipaddr.s_addr != have_ip.s_addr && 1288d568d6c4SBrian Somers ipaddr.s_addr == ipcp->dns[1].s_addr) { 1289d568d6c4SBrian Somers /* Swap 'em 'round */ 1290d568d6c4SBrian Somers ipcp->dns[0] = ipcp->dns[1]; 1291d568d6c4SBrian Somers ipcp->dns[1] = have_ip; 1292d568d6c4SBrian Somers have_ip = ipcp->dns[0]; 12933edeb0c6SBrian Somers } 1294944f7098SBrian Somers 12953edeb0c6SBrian Somers if (ipaddr.s_addr != have_ip.s_addr) { 12961ae349f5Scvs2svn /* 12973edeb0c6SBrian Somers * The client has got the DNS stuff wrong (first request) so 12981ae349f5Scvs2svn * we'll tell 'em how it is 12991ae349f5Scvs2svn */ 130030c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); /* copy first two (type/length) */ 13013edeb0c6SBrian Somers memcpy(dec->nakend + 2, &have_ip.s_addr, length - 2); 130230c2f2ffSBrian Somers dec->nakend += length; 13033edeb0c6SBrian Somers } else { 1304d8e55738SJordan K. Hubbard /* 1305944f7098SBrian Somers * Otherwise they have it right (this time) so we send a ack packet 1306944f7098SBrian Somers * back confirming it... end of story 1307d8e55738SJordan K. Hubbard */ 130830c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 130930c2f2ffSBrian Somers dec->ackend += length; 13103edeb0c6SBrian Somers } 1311d8e55738SJordan K. Hubbard break; 13128fa6ebe4SBrian Somers 1313d568d6c4SBrian Somers case MODE_NAK: 13143edeb0c6SBrian Somers if (IsEnabled(ipcp->cfg.ns.dns_neg)) { 13153edeb0c6SBrian Somers gotdnsnak = 1; 1316d568d6c4SBrian Somers memcpy(&ipcp->dns[type == TY_PRIMARY_DNS ? 0 : 1].s_addr, cp + 2, 4); 13173edeb0c6SBrian Somers } 1318d8e55738SJordan K. Hubbard break; 13198fa6ebe4SBrian Somers 13203edeb0c6SBrian Somers case MODE_REJ: /* Can't do much, stop asking */ 13213edeb0c6SBrian Somers ipcp->peer_reject |= (1 << (type - TY_ADJUST_NS)); 1322d8e55738SJordan K. Hubbard break; 1323d8e55738SJordan K. Hubbard } 1324d8e55738SJordan K. Hubbard break; 1325d8e55738SJordan K. Hubbard 13263edeb0c6SBrian Somers case TY_PRIMARY_NBNS: /* M$ NetBIOS nameserver hack (rfc1877) */ 1327d8e55738SJordan K. Hubbard case TY_SECONDARY_NBNS: 13289e8ec64bSBrian Somers memcpy(&ipaddr.s_addr, cp + 2, 4); 1329dd7e2610SBrian Somers log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 13303edeb0c6SBrian Somers 13319780ef31SBrian Somers switch (mode_type) { 1332d8e55738SJordan K. Hubbard case MODE_REQ: 13333edeb0c6SBrian Somers have_ip.s_addr = 13343edeb0c6SBrian Somers ipcp->cfg.ns.nbns[type == TY_PRIMARY_NBNS ? 0 : 1].s_addr; 13353edeb0c6SBrian Somers 13363edeb0c6SBrian Somers if (have_ip.s_addr == INADDR_ANY) { 1337dd7e2610SBrian Somers log_Printf(LogIPCP, "NBNS REQ - rejected - nbns not set\n"); 13383edeb0c6SBrian Somers ipcp->my_reject |= (1 << (type - TY_ADJUST_NS)); 133930c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 134030c2f2ffSBrian Somers dec->rejend += length; 1341d8e55738SJordan K. Hubbard break; 1342d8e55738SJordan K. Hubbard } 13433edeb0c6SBrian Somers 13443edeb0c6SBrian Somers if (ipaddr.s_addr != have_ip.s_addr) { 134530c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 13463edeb0c6SBrian Somers memcpy(dec->nakend+2, &have_ip.s_addr, length); 134730c2f2ffSBrian Somers dec->nakend += length; 13483edeb0c6SBrian Somers } else { 134930c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 135030c2f2ffSBrian Somers dec->ackend += length; 13513edeb0c6SBrian Somers } 1352d8e55738SJordan K. Hubbard break; 13538fa6ebe4SBrian Somers 1354d8e55738SJordan K. Hubbard case MODE_NAK: 1355dd7e2610SBrian Somers log_Printf(LogIPCP, "MS NBNS req %d - NAK??\n", type); 1356d8e55738SJordan K. Hubbard break; 13578fa6ebe4SBrian Somers 1358d8e55738SJordan K. Hubbard case MODE_REJ: 1359dd7e2610SBrian Somers log_Printf(LogIPCP, "MS NBNS req %d - REJ??\n", type); 1360d8e55738SJordan K. Hubbard break; 1361d8e55738SJordan K. Hubbard } 1362d8e55738SJordan K. Hubbard break; 1363d8e55738SJordan K. Hubbard 1364af57ed9fSAtsushi Murai default: 136530c2f2ffSBrian Somers if (mode_type != MODE_NOP) { 136683d1af55SBrian Somers ipcp->my_reject |= (1 << type); 136730c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 136830c2f2ffSBrian Somers dec->rejend += length; 136930c2f2ffSBrian Somers } 1370af57ed9fSAtsushi Murai break; 1371af57ed9fSAtsushi Murai } 1372af57ed9fSAtsushi Murai plen -= length; 1373af57ed9fSAtsushi Murai cp += length; 1374af57ed9fSAtsushi Murai } 13751342caedSBrian Somers 1376d568d6c4SBrian Somers if (gotdnsnak) { 1377d568d6c4SBrian Somers memcpy(ipcp->ns.dns, ipcp->dns, sizeof ipcp->ns.dns); 1378d568d6c4SBrian Somers if (ipcp->ns.writable) { 1379d568d6c4SBrian Somers log_Printf(LogDEBUG, "Updating resolver\n"); 1380d568d6c4SBrian Somers if (!ipcp_WriteDNS(ipcp)) { 13813edeb0c6SBrian Somers ipcp->peer_reject |= (1 << (TY_PRIMARY_DNS - TY_ADJUST_NS)); 13823edeb0c6SBrian Somers ipcp->peer_reject |= (1 << (TY_SECONDARY_DNS - TY_ADJUST_NS)); 1383d568d6c4SBrian Somers } else 1384d568d6c4SBrian Somers bundle_AdjustDNS(fp->bundle, ipcp->dns); 1385d568d6c4SBrian Somers } else { 1386d568d6c4SBrian Somers log_Printf(LogDEBUG, "Not updating resolver (readonly)\n"); 1387d568d6c4SBrian Somers bundle_AdjustDNS(fp->bundle, ipcp->dns); 1388d568d6c4SBrian Somers } 13893edeb0c6SBrian Somers } 13903edeb0c6SBrian Somers 1391e43ebac1SBrian Somers if (mode_type != MODE_NOP) { 13921342caedSBrian Somers if (dec->rejend != dec->rej) { 13931342caedSBrian Somers /* rejects are preferred */ 13941342caedSBrian Somers dec->ackend = dec->ack; 13951342caedSBrian Somers dec->nakend = dec->nak; 13961342caedSBrian Somers } else if (dec->nakend != dec->nak) 13971342caedSBrian Somers /* then NAKs */ 13981342caedSBrian Somers dec->ackend = dec->ack; 13991ae349f5Scvs2svn } 1400af57ed9fSAtsushi Murai } 1401af57ed9fSAtsushi Murai 14025d9e6103SBrian Somers extern struct mbuf * 14035d9e6103SBrian Somers ipcp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 1404af57ed9fSAtsushi Murai { 14057308ec68SBrian Somers /* Got PROTO_IPCP from link */ 140626af0ae9SBrian Somers m_settype(bp, MB_IPCPIN); 1407641684cdSBrian Somers if (bundle_Phase(bundle) == PHASE_NETWORK) 14085d9e6103SBrian Somers fsm_Input(&bundle->ncp.ipcp.fsm, bp); 1409641684cdSBrian Somers else { 1410641684cdSBrian Somers if (bundle_Phase(bundle) < PHASE_NETWORK) 1411641684cdSBrian Somers log_Printf(LogIPCP, "%s: Error: Unexpected IPCP in phase %s (ignored)\n", 14125d9e6103SBrian Somers l->name, bundle_PhaseName(bundle)); 141326af0ae9SBrian Somers m_freem(bp); 1414641684cdSBrian Somers } 14155d9e6103SBrian Somers return NULL; 1416af57ed9fSAtsushi Murai } 14179c97abd8SBrian Somers 14189c97abd8SBrian Somers int 1419972a1bcfSBrian Somers ipcp_UseHisIPaddr(struct bundle *bundle, struct in_addr hisaddr) 1420972a1bcfSBrian Somers { 1421972a1bcfSBrian Somers struct ipcp *ipcp = &bundle->ncp.ipcp; 1422972a1bcfSBrian Somers 1423972a1bcfSBrian Somers memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 1424972a1bcfSBrian Somers iplist_reset(&ipcp->cfg.peer_list); 1425972a1bcfSBrian Somers ipcp->peer_ip = ipcp->cfg.peer_range.ipaddr = hisaddr; 1426972a1bcfSBrian Somers ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 1427972a1bcfSBrian Somers ipcp->cfg.peer_range.width = 32; 1428972a1bcfSBrian Somers 1429972a1bcfSBrian Somers if (ipcp_SetIPaddress(bundle, ipcp->cfg.my_range.ipaddr, hisaddr, 0) < 0) 1430972a1bcfSBrian Somers return 0; 1431972a1bcfSBrian Somers 1432972a1bcfSBrian Somers return 1; /* Ok */ 1433972a1bcfSBrian Somers } 1434972a1bcfSBrian Somers 1435972a1bcfSBrian Somers int 1436dd7e2610SBrian Somers ipcp_UseHisaddr(struct bundle *bundle, const char *hisaddr, int setaddr) 14379c97abd8SBrian Somers { 14385828db6dSBrian Somers struct ipcp *ipcp = &bundle->ncp.ipcp; 14395828db6dSBrian Somers 14407308ec68SBrian Somers /* Use `hisaddr' for the peers address (set iface if `setaddr') */ 14415828db6dSBrian Somers memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 14425828db6dSBrian Somers iplist_reset(&ipcp->cfg.peer_list); 14439c97abd8SBrian Somers if (strpbrk(hisaddr, ",-")) { 14445828db6dSBrian Somers iplist_setsrc(&ipcp->cfg.peer_list, hisaddr); 14455828db6dSBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 14465828db6dSBrian Somers iplist_setrandpos(&ipcp->cfg.peer_list); 144730c2f2ffSBrian Somers ipcp->peer_ip = ChooseHisAddr(bundle, ipcp->my_ip); 14485828db6dSBrian Somers if (ipcp->peer_ip.s_addr == INADDR_ANY) { 1449dd7e2610SBrian Somers log_Printf(LogWARN, "%s: None available !\n", ipcp->cfg.peer_list.src); 14501d1fc017SBrian Somers return 0; 14519c97abd8SBrian Somers } 14525828db6dSBrian Somers ipcp->cfg.peer_range.ipaddr.s_addr = ipcp->peer_ip.s_addr; 14535828db6dSBrian Somers ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 14545828db6dSBrian Somers ipcp->cfg.peer_range.width = 32; 14559c97abd8SBrian Somers } else { 1456dd7e2610SBrian Somers log_Printf(LogWARN, "%s: Invalid range !\n", hisaddr); 14579c97abd8SBrian Somers return 0; 14589c97abd8SBrian Somers } 1459972a1bcfSBrian Somers } else if (ParseAddr(ipcp, hisaddr, &ipcp->cfg.peer_range.ipaddr, 14605828db6dSBrian Somers &ipcp->cfg.peer_range.mask, 14615828db6dSBrian Somers &ipcp->cfg.peer_range.width) != 0) { 14625828db6dSBrian Somers ipcp->peer_ip.s_addr = ipcp->cfg.peer_range.ipaddr.s_addr; 14639c97abd8SBrian Somers 146430c2f2ffSBrian Somers if (setaddr && ipcp_SetIPaddress(bundle, ipcp->cfg.my_range.ipaddr, 14658fa6ebe4SBrian Somers ipcp->cfg.peer_range.ipaddr, 0) < 0) 14669c97abd8SBrian Somers return 0; 14679c97abd8SBrian Somers } else 14689c97abd8SBrian Somers return 0; 14699c97abd8SBrian Somers 14701d1fc017SBrian Somers bundle_AdjustFilters(bundle, NULL, &ipcp->peer_ip); 14711d1fc017SBrian Somers 14721d1fc017SBrian Somers return 1; /* Ok */ 14739c97abd8SBrian Somers } 1474bc76350eSBrian Somers 1475bc76350eSBrian Somers struct in_addr 1476bc76350eSBrian Somers addr2mask(struct in_addr addr) 1477bc76350eSBrian Somers { 1478bc76350eSBrian Somers u_int32_t haddr = ntohl(addr.s_addr); 1479bc76350eSBrian Somers 1480bc76350eSBrian Somers haddr = IN_CLASSA(haddr) ? IN_CLASSA_NET : 1481bc76350eSBrian Somers IN_CLASSB(haddr) ? IN_CLASSB_NET : 1482bc76350eSBrian Somers IN_CLASSC_NET; 1483bc76350eSBrian Somers addr.s_addr = htonl(haddr); 1484bc76350eSBrian Somers 1485bc76350eSBrian Somers return addr; 1486bc76350eSBrian Somers } 1487