ipcp.c revision 54912
16059Samurai/* 26059Samurai * PPP IP Control Protocol (IPCP) Module 36059Samurai * 46059Samurai * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 56059Samurai * 66059Samurai * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 76059Samurai * 86059Samurai * Redistribution and use in source and binary forms are permitted 96059Samurai * provided that the above copyright notice and this paragraph are 106059Samurai * duplicated in all such forms and that any documentation, 116059Samurai * advertising materials, and other materials related to such 126059Samurai * distribution and use acknowledge that the software was developed 136059Samurai * by the Internet Initiative Japan, Inc. The name of the 146059Samurai * IIJ may not be used to endorse or promote products derived 156059Samurai * from this software without specific prior written permission. 166059Samurai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 176059Samurai * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 186059Samurai * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 196059Samurai * 2050479Speter * $FreeBSD: head/usr.sbin/ppp/ipcp.c 54912 1999-12-20 20:29:47Z brian $ 218857Srgrimes * 226059Samurai * TODO: 2346686Sbrian * o Support IPADDRS properly 2446686Sbrian * o Validate the length in IpcpDecodeConfig 256059Samurai */ 2630715Sbrian#include <sys/param.h> 276059Samurai#include <netinet/in_systm.h> 2829048Sbrian#include <netinet/in.h> 296059Samurai#include <netinet/ip.h> 306059Samurai#include <arpa/inet.h> 316059Samurai#include <sys/socket.h> 3240665Sbrian#include <net/route.h> 3330715Sbrian#include <netdb.h> 3436285Sbrian#include <sys/un.h> 3530715Sbrian 3646085Sbrian#include <errno.h> 3736285Sbrian#include <fcntl.h> 3836285Sbrian#include <resolv.h> 3932614Sbrian#include <stdlib.h> 4030715Sbrian#include <string.h> 4136285Sbrian#include <termios.h> 4230715Sbrian#include <unistd.h> 4330715Sbrian 4450059Sbrian#ifndef NONAT 4546086Sbrian#ifdef __FreeBSD__ 4646086Sbrian#include <alias.h> 4746086Sbrian#else 4839395Sbrian#include "alias.h" 4939395Sbrian#endif 5039395Sbrian#endif 5146686Sbrian#include "layer.h" 5238814Sbrian#include "ua.h" 5337009Sbrian#include "defs.h" 5431343Sbrian#include "command.h" 5530715Sbrian#include "mbuf.h" 5630715Sbrian#include "log.h" 5730715Sbrian#include "timer.h" 5829048Sbrian#include "fsm.h" 5946686Sbrian#include "proto.h" 6029048Sbrian#include "lcp.h" 6131690Sbrian#include "iplist.h" 6236285Sbrian#include "throughput.h" 6336285Sbrian#include "slcompress.h" 6438557Sbrian#include "lqr.h" 6538557Sbrian#include "hdlc.h" 6629048Sbrian#include "ipcp.h" 6736285Sbrian#include "filter.h" 6836285Sbrian#include "descriptor.h" 6930715Sbrian#include "vjcomp.h" 7036285Sbrian#include "async.h" 7136285Sbrian#include "ccp.h" 7236285Sbrian#include "link.h" 7336285Sbrian#include "physical.h" 7436285Sbrian#include "mp.h" 7543313Sbrian#ifndef NORADIUS 7643313Sbrian#include "radius.h" 7743313Sbrian#endif 7836285Sbrian#include "bundle.h" 7936285Sbrian#include "id.h" 8036285Sbrian#include "arp.h" 8136285Sbrian#include "systems.h" 8236285Sbrian#include "prompt.h" 8331690Sbrian#include "route.h" 8440561Sbrian#include "iface.h" 8550867Sbrian#include "ip.h" 866059Samurai 8736285Sbrian#undef REJECTED 8836285Sbrian#define REJECTED(p, x) ((p)->peer_reject & (1<<(x))) 8936285Sbrian#define issep(ch) ((ch) == ' ' || (ch) == '\t') 9036285Sbrian#define isip(ch) (((ch) >= '0' && (ch) <= '9') || (ch) == '.') 916059Samurai 9251048Sbrianstatic u_short default_urgent_tcp_ports[] = { 9350867Sbrian 21, /* ftp */ 9450867Sbrian 22, /* ssh */ 9550867Sbrian 23, /* telnet */ 9650867Sbrian 513, /* login */ 9750867Sbrian 514, /* shell */ 9850867Sbrian 543, /* klogin */ 9950867Sbrian 544 /* kshell */ 10050867Sbrian}; 10150867Sbrian 10251048Sbrianstatic u_short default_urgent_udp_ports[] = { }; 10350867Sbrian 10451048Sbrian#define NDEFTCPPORTS \ 10551048Sbrian (sizeof default_urgent_tcp_ports / sizeof default_urgent_tcp_ports[0]) 10651048Sbrian#define NDEFUDPPORTS \ 10751048Sbrian (sizeof default_urgent_udp_ports / sizeof default_urgent_udp_ports[0]) 10851048Sbrian 10950867Sbrianint 11051048Sbrianipcp_IsUrgentPort(struct port_range *range, u_short src, u_short dst) 11150867Sbrian{ 11250867Sbrian int f; 11350867Sbrian 11451048Sbrian for (f = 0; f < range->nports; f++) 11551048Sbrian if (range->port[f] == src || range->port[f] == dst) 11650867Sbrian return 1; 11750867Sbrian 11850867Sbrian return 0; 11950867Sbrian} 12050867Sbrian 12150867Sbrianvoid 12251048Sbrianipcp_AddUrgentPort(struct port_range *range, u_short port) 12350867Sbrian{ 12450867Sbrian u_short *newport; 12550867Sbrian int p; 12650867Sbrian 12751048Sbrian if (range->nports == range->maxports) { 12851048Sbrian range->maxports += 10; 12951048Sbrian newport = (u_short *)realloc(range->port, 13051048Sbrian range->maxports * sizeof(u_short)); 13150867Sbrian if (newport == NULL) { 13250867Sbrian log_Printf(LogERROR, "ipcp_AddUrgentPort: realloc: %s\n", 13350867Sbrian strerror(errno)); 13451048Sbrian range->maxports -= 10; 13550867Sbrian return; 13650867Sbrian } 13751048Sbrian range->port = newport; 13850867Sbrian } 13950867Sbrian 14051048Sbrian for (p = 0; p < range->nports; p++) 14151048Sbrian if (range->port[p] == port) { 14250867Sbrian log_Printf(LogWARN, "%u: Port already set to urgent\n", port); 14350867Sbrian break; 14451048Sbrian } else if (range->port[p] > port) { 14551048Sbrian memmove(range->port + p + 1, range->port + p, 14651048Sbrian (range->nports - p) * sizeof(u_short)); 14751048Sbrian range->port[p] = port; 14851048Sbrian range->nports++; 14950867Sbrian break; 15050867Sbrian } 15150867Sbrian 15251048Sbrian if (p == range->nports) 15351048Sbrian range->port[range->nports++] = port; 15450867Sbrian} 15550867Sbrian 15650867Sbrianvoid 15751048Sbrianipcp_RemoveUrgentPort(struct port_range *range, u_short port) 15850867Sbrian{ 15950867Sbrian int p; 16050867Sbrian 16151048Sbrian for (p = 0; p < range->nports; p++) 16251048Sbrian if (range->port[p] == port) { 16351048Sbrian if (p != range->nports - 1) 16451048Sbrian memmove(range->port + p, range->port + p + 1, 16551048Sbrian (range->nports - p - 1) * sizeof(u_short)); 16651048Sbrian range->nports--; 16750867Sbrian return; 16850867Sbrian } 16950867Sbrian 17051048Sbrian if (p == range->nports) 17150867Sbrian log_Printf(LogWARN, "%u: Port not set to urgent\n", port); 17250867Sbrian} 17350867Sbrian 17450867Sbrianvoid 17551048Sbrianipcp_ClearUrgentPorts(struct port_range *range) 17650867Sbrian{ 17751048Sbrian range->nports = 0; 17850867Sbrian} 17950867Sbrian 18036285Sbrianstruct compreq { 18136285Sbrian u_short proto; 18236285Sbrian u_char slots; 18336285Sbrian u_char compcid; 18436285Sbrian}; 1856059Samurai 18636285Sbrianstatic int IpcpLayerUp(struct fsm *); 18736285Sbrianstatic void IpcpLayerDown(struct fsm *); 18826516Sbrianstatic void IpcpLayerStart(struct fsm *); 18926516Sbrianstatic void IpcpLayerFinish(struct fsm *); 19044305Sbrianstatic void IpcpInitRestartCounter(struct fsm *, int); 19136285Sbrianstatic void IpcpSendConfigReq(struct fsm *); 19236285Sbrianstatic void IpcpSentTerminateReq(struct fsm *); 19336285Sbrianstatic void IpcpSendTerminateAck(struct fsm *, u_char); 19436285Sbrianstatic void IpcpDecodeConfig(struct fsm *, u_char *, int, int, 19536285Sbrian struct fsm_decode *); 1966059Samurai 19736285Sbrianstatic struct fsm_callbacks ipcp_Callbacks = { 1986059Samurai IpcpLayerUp, 1996059Samurai IpcpLayerDown, 2006059Samurai IpcpLayerStart, 2016059Samurai IpcpLayerFinish, 2026059Samurai IpcpInitRestartCounter, 2036059Samurai IpcpSendConfigReq, 20436285Sbrian IpcpSentTerminateReq, 2056059Samurai IpcpSendTerminateAck, 2066059Samurai IpcpDecodeConfig, 20736285Sbrian fsm_NullRecvResetReq, 20836285Sbrian fsm_NullRecvResetAck 2096059Samurai}; 2106059Samurai 21131343Sbrianstatic const char *cftypes[] = { 21231171Sbrian /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */ 21331171Sbrian "???", 21431171Sbrian "IPADDRS", /* 1: IP-Addresses */ /* deprecated */ 21531171Sbrian "COMPPROTO", /* 2: IP-Compression-Protocol */ 21631171Sbrian "IPADDR", /* 3: IP-Address */ 2176059Samurai}; 2186059Samurai 21931962Sbrian#define NCFTYPES (sizeof cftypes/sizeof cftypes[0]) 22031171Sbrian 22131343Sbrianstatic const char *cftypes128[] = { 22231171Sbrian /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */ 22331171Sbrian "???", 22431171Sbrian "PRIDNS", /* 129: Primary DNS Server Address */ 22531171Sbrian "PRINBNS", /* 130: Primary NBNS Server Address */ 22631171Sbrian "SECDNS", /* 131: Secondary DNS Server Address */ 22731171Sbrian "SECNBNS", /* 132: Secondary NBNS Server Address */ 22831171Sbrian}; 22931171Sbrian 23031962Sbrian#define NCFTYPES128 (sizeof cftypes128/sizeof cftypes128[0]) 23131171Sbrian 23231272Sbrianvoid 23336285Sbrianipcp_AddInOctets(struct ipcp *ipcp, int n) 2346059Samurai{ 23536285Sbrian throughput_addin(&ipcp->throughput, n); 2366059Samurai} 2376059Samurai 23831272Sbrianvoid 23936285Sbrianipcp_AddOutOctets(struct ipcp *ipcp, int n) 2406059Samurai{ 24136285Sbrian throughput_addout(&ipcp->throughput, n); 2426059Samurai} 2436059Samurai 24436285Sbrianstatic void 24536285Sbriangetdns(struct ipcp *ipcp, struct in_addr addr[2]) 2466059Samurai{ 24736285Sbrian FILE *fp; 2486059Samurai 24936285Sbrian addr[0].s_addr = addr[1].s_addr = INADDR_ANY; 25036285Sbrian if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { 25136285Sbrian char buf[LINE_LEN], *cp, *end; 25236285Sbrian int n; 25336285Sbrian 25436285Sbrian n = 0; 25536285Sbrian buf[sizeof buf - 1] = '\0'; 25636285Sbrian while (fgets(buf, sizeof buf - 1, fp)) { 25736285Sbrian if (!strncmp(buf, "nameserver", 10) && issep(buf[10])) { 25836285Sbrian for (cp = buf + 11; issep(*cp); cp++) 25936285Sbrian ; 26036285Sbrian for (end = cp; isip(*end); end++) 26136285Sbrian ; 26236285Sbrian *end = '\0'; 26336285Sbrian if (inet_aton(cp, addr+n) && ++n == 2) 26436285Sbrian break; 26536285Sbrian } 26636285Sbrian } 26736285Sbrian if (n == 1) 26836285Sbrian addr[1] = addr[0]; 26936285Sbrian fclose(fp); 27032614Sbrian } 27136285Sbrian} 27229048Sbrian 27336285Sbrianstatic int 27436285Sbriansetdns(struct ipcp *ipcp, struct in_addr addr[2]) 27536285Sbrian{ 27636285Sbrian FILE *fp; 27736285Sbrian char wbuf[LINE_LEN + 54]; 27836285Sbrian int wlen; 27926516Sbrian 28036285Sbrian if (addr[0].s_addr == INADDR_ANY || addr[1].s_addr == INADDR_ANY) { 28136285Sbrian struct in_addr old[2]; 28231272Sbrian 28336285Sbrian getdns(ipcp, old); 28436285Sbrian if (addr[0].s_addr == INADDR_ANY) 28536285Sbrian addr[0] = old[0]; 28636285Sbrian if (addr[1].s_addr == INADDR_ANY) 28736285Sbrian addr[1] = old[1]; 28836285Sbrian } 28936285Sbrian 29036285Sbrian if (addr[0].s_addr == INADDR_ANY && addr[1].s_addr == INADDR_ANY) { 29136285Sbrian log_Printf(LogWARN, "%s not modified: All nameservers NAKd\n", 29236285Sbrian _PATH_RESCONF); 29336285Sbrian return 0; 29436285Sbrian } 29536285Sbrian 29636285Sbrian wlen = 0; 29736285Sbrian if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { 29836285Sbrian char buf[LINE_LEN]; 29936285Sbrian int len; 30036285Sbrian 30136285Sbrian buf[sizeof buf - 1] = '\0'; 30236285Sbrian while (fgets(buf, sizeof buf - 1, fp)) { 30336285Sbrian if (strncmp(buf, "nameserver", 10) || !issep(buf[10])) { 30436285Sbrian len = strlen(buf); 30536285Sbrian if (len > sizeof wbuf - wlen) { 30636285Sbrian log_Printf(LogWARN, "%s: Can only cope with max file size %d\n", 30736285Sbrian _PATH_RESCONF, LINE_LEN); 30836285Sbrian fclose(fp); 30936285Sbrian return 0; 31036285Sbrian } 31136285Sbrian memcpy(wbuf + wlen, buf, len); 31236285Sbrian wlen += len; 31336285Sbrian } 31436285Sbrian } 31536285Sbrian fclose(fp); 31636285Sbrian } 31736285Sbrian 31836285Sbrian if (addr[0].s_addr != INADDR_ANY) { 31936285Sbrian snprintf(wbuf + wlen, sizeof wbuf - wlen, "nameserver %s\n", 32036285Sbrian inet_ntoa(addr[0])); 32136285Sbrian log_Printf(LogIPCP, "Primary nameserver set to %s", wbuf + wlen + 11); 32236285Sbrian wlen += strlen(wbuf + wlen); 32336285Sbrian } 32436285Sbrian 32536285Sbrian if (addr[1].s_addr != INADDR_ANY && addr[1].s_addr != addr[0].s_addr) { 32636285Sbrian snprintf(wbuf + wlen, sizeof wbuf - wlen, "nameserver %s\n", 32736285Sbrian inet_ntoa(addr[1])); 32836285Sbrian log_Printf(LogIPCP, "Secondary nameserver set to %s", wbuf + wlen + 11); 32936285Sbrian wlen += strlen(wbuf + wlen); 33036285Sbrian } 33136285Sbrian 33236285Sbrian if (wlen) { 33336285Sbrian int fd; 33436285Sbrian 33536285Sbrian if ((fd = ID0open(_PATH_RESCONF, O_WRONLY|O_CREAT, 0644)) != -1) { 33636285Sbrian if (write(fd, wbuf, wlen) != wlen) { 33736285Sbrian log_Printf(LogERROR, "setdns: write(): %s\n", strerror(errno)); 33836285Sbrian close(fd); 33936285Sbrian return 0; 34036285Sbrian } 34136285Sbrian if (ftruncate(fd, wlen) == -1) { 34236285Sbrian log_Printf(LogERROR, "setdns: truncate(): %s\n", strerror(errno)); 34336285Sbrian close(fd); 34436285Sbrian return 0; 34536285Sbrian } 34636285Sbrian close(fd); 34736285Sbrian } else { 34836285Sbrian log_Printf(LogERROR, "setdns: open(): %s\n", strerror(errno)); 34936285Sbrian return 0; 35036285Sbrian } 35136285Sbrian } 35236285Sbrian 35336285Sbrian return 1; 3546059Samurai} 3556059Samurai 35636285Sbrianint 35736285Sbrianipcp_Show(struct cmdargs const *arg) 3586059Samurai{ 35936285Sbrian struct ipcp *ipcp = &arg->bundle->ncp.ipcp; 36050867Sbrian int p; 3616059Samurai 36236285Sbrian prompt_Printf(arg->prompt, "%s [%s]\n", ipcp->fsm.name, 36336285Sbrian State2Nam(ipcp->fsm.state)); 36436285Sbrian if (ipcp->fsm.state == ST_OPENED) { 36536285Sbrian prompt_Printf(arg->prompt, " His side: %s, %s\n", 36636285Sbrian inet_ntoa(ipcp->peer_ip), vj2asc(ipcp->peer_compproto)); 36736285Sbrian prompt_Printf(arg->prompt, " My side: %s, %s\n", 36836285Sbrian inet_ntoa(ipcp->my_ip), vj2asc(ipcp->my_compproto)); 36950867Sbrian prompt_Printf(arg->prompt, " Queued packets: %d\n", ip_QueueLen(ipcp)); 3706059Samurai } 37136285Sbrian 37236285Sbrian if (ipcp->route) { 37336285Sbrian prompt_Printf(arg->prompt, "\n"); 37443313Sbrian route_ShowSticky(arg->prompt, ipcp->route, "Sticky routes", 1); 37536285Sbrian } 37636285Sbrian 37736285Sbrian prompt_Printf(arg->prompt, "\nDefaults:\n"); 37844305Sbrian prompt_Printf(arg->prompt, " FSM retry = %us, max %u Config" 37944305Sbrian " REQ%s, %u Term REQ%s\n", ipcp->cfg.fsm.timeout, 38044305Sbrian ipcp->cfg.fsm.maxreq, ipcp->cfg.fsm.maxreq == 1 ? "" : "s", 38144305Sbrian ipcp->cfg.fsm.maxtrm, ipcp->cfg.fsm.maxtrm == 1 ? "" : "s"); 38236285Sbrian prompt_Printf(arg->prompt, " My Address: %s/%d", 38336285Sbrian inet_ntoa(ipcp->cfg.my_range.ipaddr), ipcp->cfg.my_range.width); 38444455Sbrian prompt_Printf(arg->prompt, ", netmask %s\n", inet_ntoa(ipcp->cfg.netmask)); 38536285Sbrian if (ipcp->cfg.HaveTriggerAddress) 38644455Sbrian prompt_Printf(arg->prompt, " Trigger address: %s\n", 38736285Sbrian inet_ntoa(ipcp->cfg.TriggerAddress)); 38844455Sbrian 38944455Sbrian prompt_Printf(arg->prompt, " VJ compression: %s (%d slots %s slot " 39036285Sbrian "compression)\n", command_ShowNegval(ipcp->cfg.vj.neg), 39136285Sbrian ipcp->cfg.vj.slots, ipcp->cfg.vj.slotcomp ? "with" : "without"); 39236285Sbrian 39336285Sbrian if (iplist_isvalid(&ipcp->cfg.peer_list)) 39436285Sbrian prompt_Printf(arg->prompt, " His Address: %s\n", 39536285Sbrian ipcp->cfg.peer_list.src); 39636285Sbrian else 39736285Sbrian prompt_Printf(arg->prompt, " His Address: %s/%d\n", 39836285Sbrian inet_ntoa(ipcp->cfg.peer_range.ipaddr), 39936285Sbrian ipcp->cfg.peer_range.width); 40036285Sbrian 40136285Sbrian prompt_Printf(arg->prompt, " DNS: %s, ", 40236285Sbrian inet_ntoa(ipcp->cfg.ns.dns[0])); 40336285Sbrian prompt_Printf(arg->prompt, "%s, %s\n", inet_ntoa(ipcp->cfg.ns.dns[1]), 40436285Sbrian command_ShowNegval(ipcp->cfg.ns.dns_neg)); 40536285Sbrian prompt_Printf(arg->prompt, " NetBIOS NS: %s, ", 40636285Sbrian inet_ntoa(ipcp->cfg.ns.nbns[0])); 40736285Sbrian prompt_Printf(arg->prompt, "%s\n", inet_ntoa(ipcp->cfg.ns.nbns[1])); 40836285Sbrian 40951048Sbrian prompt_Printf(arg->prompt, " Urgent ports\n"); 41051048Sbrian prompt_Printf(arg->prompt, " TCP: "); 41151048Sbrian if (ipcp->cfg.urgent.tcp.nports == 0) 41250867Sbrian prompt_Printf(arg->prompt, "none"); 41350867Sbrian else 41451048Sbrian for (p = 0; p < ipcp->cfg.urgent.tcp.nports; p++) { 41550867Sbrian if (p) 41650867Sbrian prompt_Printf(arg->prompt, ", "); 41751048Sbrian prompt_Printf(arg->prompt, "%u", ipcp->cfg.urgent.tcp.port[p]); 41850867Sbrian } 41951048Sbrian prompt_Printf(arg->prompt, "\n UDP: "); 42051048Sbrian if (ipcp->cfg.urgent.udp.nports == 0) 42151048Sbrian prompt_Printf(arg->prompt, "none"); 42251048Sbrian else 42351048Sbrian for (p = 0; p < ipcp->cfg.urgent.udp.nports; p++) { 42451048Sbrian if (p) 42551048Sbrian prompt_Printf(arg->prompt, ", "); 42651048Sbrian prompt_Printf(arg->prompt, "%u", ipcp->cfg.urgent.udp.port[p]); 42751048Sbrian } 42850867Sbrian 42950867Sbrian prompt_Printf(arg->prompt, "\n\n"); 43036285Sbrian throughput_disp(&ipcp->throughput, arg->prompt); 43136285Sbrian 43236285Sbrian return 0; 4336059Samurai} 4346059Samurai 43532614Sbrianint 43636285Sbrianipcp_vjset(struct cmdargs const *arg) 43732614Sbrian{ 43836285Sbrian if (arg->argc != arg->argn+2) 43932614Sbrian return -1; 44036285Sbrian if (!strcasecmp(arg->argv[arg->argn], "slots")) { 44132614Sbrian int slots; 44232614Sbrian 44336285Sbrian slots = atoi(arg->argv[arg->argn+1]); 44432614Sbrian if (slots < 4 || slots > 16) 44532614Sbrian return 1; 44636285Sbrian arg->bundle->ncp.ipcp.cfg.vj.slots = slots; 44732614Sbrian return 0; 44836285Sbrian } else if (!strcasecmp(arg->argv[arg->argn], "slotcomp")) { 44936285Sbrian if (!strcasecmp(arg->argv[arg->argn+1], "on")) 45036285Sbrian arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 1; 45136285Sbrian else if (!strcasecmp(arg->argv[arg->argn+1], "off")) 45236285Sbrian arg->bundle->ncp.ipcp.cfg.vj.slotcomp = 0; 45332614Sbrian else 45432614Sbrian return 2; 45532614Sbrian return 0; 45632614Sbrian } 45732614Sbrian return -1; 45832614Sbrian} 45932614Sbrian 46036285Sbrianvoid 46136285Sbrianipcp_Init(struct ipcp *ipcp, struct bundle *bundle, struct link *l, 46236285Sbrian const struct fsm_parent *parent) 46332614Sbrian{ 46436285Sbrian struct hostent *hp; 46536285Sbrian char name[MAXHOSTNAMELEN]; 46636285Sbrian static const char *timer_names[] = 46736285Sbrian {"IPCP restart", "IPCP openmode", "IPCP stopped"}; 46836285Sbrian 46944305Sbrian fsm_Init(&ipcp->fsm, "IPCP", PROTO_IPCP, 1, IPCP_MAXCODE, LogIPCP, 47036285Sbrian bundle, l, parent, &ipcp_Callbacks, timer_names); 47136285Sbrian 47236285Sbrian ipcp->route = NULL; 47336285Sbrian ipcp->cfg.vj.slots = DEF_VJ_STATES; 47436285Sbrian ipcp->cfg.vj.slotcomp = 1; 47536285Sbrian memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range); 47636285Sbrian if (gethostname(name, sizeof name) == 0) { 47736285Sbrian hp = gethostbyname(name); 47840561Sbrian if (hp && hp->h_addrtype == AF_INET) 47936285Sbrian memcpy(&ipcp->cfg.my_range.ipaddr.s_addr, hp->h_addr, hp->h_length); 48032614Sbrian } 48136285Sbrian ipcp->cfg.netmask.s_addr = INADDR_ANY; 48236285Sbrian memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 48336285Sbrian iplist_setsrc(&ipcp->cfg.peer_list, ""); 48436285Sbrian ipcp->cfg.HaveTriggerAddress = 0; 48536285Sbrian 48636285Sbrian ipcp->cfg.ns.dns[0].s_addr = INADDR_ANY; 48736285Sbrian ipcp->cfg.ns.dns[1].s_addr = INADDR_ANY; 48836285Sbrian ipcp->cfg.ns.dns_neg = 0; 48936285Sbrian ipcp->cfg.ns.nbns[0].s_addr = INADDR_ANY; 49036285Sbrian ipcp->cfg.ns.nbns[1].s_addr = INADDR_ANY; 49136285Sbrian 49251048Sbrian ipcp->cfg.urgent.tcp.nports = ipcp->cfg.urgent.tcp.maxports = NDEFTCPPORTS; 49351048Sbrian ipcp->cfg.urgent.tcp.port = (u_short *)malloc(NDEFTCPPORTS * sizeof(u_short)); 49451048Sbrian memcpy(ipcp->cfg.urgent.tcp.port, default_urgent_tcp_ports, 49551048Sbrian NDEFTCPPORTS * sizeof(u_short)); 49650867Sbrian 49751048Sbrian ipcp->cfg.urgent.udp.nports = ipcp->cfg.urgent.udp.maxports = NDEFUDPPORTS; 49851048Sbrian ipcp->cfg.urgent.udp.port = (u_short *)malloc(NDEFUDPPORTS * sizeof(u_short)); 49951048Sbrian memcpy(ipcp->cfg.urgent.udp.port, default_urgent_udp_ports, 50051048Sbrian NDEFUDPPORTS * sizeof(u_short)); 50151048Sbrian 50244305Sbrian ipcp->cfg.fsm.timeout = DEF_FSMRETRY; 50344305Sbrian ipcp->cfg.fsm.maxreq = DEF_FSMTRIES; 50444305Sbrian ipcp->cfg.fsm.maxtrm = DEF_FSMTRIES; 50536285Sbrian ipcp->cfg.vj.neg = NEG_ENABLED|NEG_ACCEPTED; 50636285Sbrian 50736285Sbrian memset(&ipcp->vj, '\0', sizeof ipcp->vj); 50836285Sbrian 50949434Sbrian throughput_init(&ipcp->throughput, SAMPLE_PERIOD); 51038557Sbrian memset(ipcp->Queue, '\0', sizeof ipcp->Queue); 51143313Sbrian ipcp_Setup(ipcp, INADDR_NONE); 51232614Sbrian} 51332614Sbrian 5146059Samuraivoid 51550867Sbrianipcp_Destroy(struct ipcp *ipcp) 51650867Sbrian{ 51751048Sbrian if (ipcp->cfg.urgent.tcp.maxports) { 51851048Sbrian ipcp->cfg.urgent.tcp.nports = ipcp->cfg.urgent.tcp.maxports = 0; 51951048Sbrian free(ipcp->cfg.urgent.tcp.port); 52051048Sbrian ipcp->cfg.urgent.tcp.port = NULL; 52150867Sbrian } 52251048Sbrian if (ipcp->cfg.urgent.udp.maxports) { 52351048Sbrian ipcp->cfg.urgent.udp.nports = ipcp->cfg.urgent.udp.maxports = 0; 52451048Sbrian free(ipcp->cfg.urgent.udp.port); 52551048Sbrian ipcp->cfg.urgent.udp.port = NULL; 52651048Sbrian } 52750867Sbrian} 52850867Sbrian 52950867Sbrianvoid 53036285Sbrianipcp_SetLink(struct ipcp *ipcp, struct link *l) 5316059Samurai{ 53236285Sbrian ipcp->fsm.link = l; 53336285Sbrian} 53436285Sbrian 53536285Sbrianvoid 53643313Sbrianipcp_Setup(struct ipcp *ipcp, u_int32_t mask) 53736285Sbrian{ 53840561Sbrian struct iface *iface = ipcp->fsm.bundle->iface; 53940561Sbrian int pos, n; 54036285Sbrian 54136285Sbrian ipcp->fsm.open_mode = 0; 54243313Sbrian ipcp->ifmask.s_addr = mask == INADDR_NONE ? ipcp->cfg.netmask.s_addr : mask; 54336285Sbrian 54436285Sbrian if (iplist_isvalid(&ipcp->cfg.peer_list)) { 54540561Sbrian /* Try to give the peer a previously configured IP address */ 54640561Sbrian for (n = 0; n < iface->in_addrs; n++) { 54740561Sbrian pos = iplist_ip2pos(&ipcp->cfg.peer_list, iface->in_addr[n].brd); 54840561Sbrian if (pos != -1) { 54940561Sbrian ipcp->cfg.peer_range.ipaddr = 55040561Sbrian iplist_setcurpos(&ipcp->cfg.peer_list, pos); 55140561Sbrian break; 55240561Sbrian } 55340561Sbrian } 55440561Sbrian if (n == iface->in_addrs) 55540561Sbrian /* Ok, so none of 'em fit.... pick a random one */ 55636285Sbrian ipcp->cfg.peer_range.ipaddr = iplist_setrandpos(&ipcp->cfg.peer_list); 55740561Sbrian 55836285Sbrian ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 55936285Sbrian ipcp->cfg.peer_range.width = 32; 5606059Samurai } 5619440Samurai 56236285Sbrian ipcp->heis1172 = 0; 56336285Sbrian 56436285Sbrian ipcp->peer_ip = ipcp->cfg.peer_range.ipaddr; 56536285Sbrian ipcp->peer_compproto = 0; 56636285Sbrian 56736285Sbrian if (ipcp->cfg.HaveTriggerAddress) { 56836285Sbrian /* 56936285Sbrian * Some implementations of PPP require that we send a 57036285Sbrian * *special* value as our address, even though the rfc specifies 57136285Sbrian * full negotiation (e.g. "0.0.0.0" or Not "0.0.0.0"). 57236285Sbrian */ 57336285Sbrian ipcp->my_ip = ipcp->cfg.TriggerAddress; 57436285Sbrian log_Printf(LogIPCP, "Using trigger address %s\n", 57536285Sbrian inet_ntoa(ipcp->cfg.TriggerAddress)); 57640561Sbrian } else { 57736285Sbrian /* 57840561Sbrian * Otherwise, if we've used an IP number before and it's still within 57940561Sbrian * the network specified on the ``set ifaddr'' line, we really 58040561Sbrian * want to keep that IP number so that we can keep any existing 58140561Sbrian * connections that are bound to that IP (assuming we're not 58240561Sbrian * ``iface-alias''ing). 58336285Sbrian */ 58440561Sbrian for (n = 0; n < iface->in_addrs; n++) 58540561Sbrian if ((iface->in_addr[n].ifa.s_addr & ipcp->cfg.my_range.mask.s_addr) == 58640561Sbrian (ipcp->cfg.my_range.ipaddr.s_addr & ipcp->cfg.my_range.mask.s_addr)) { 58740561Sbrian ipcp->my_ip = iface->in_addr[n].ifa; 58840561Sbrian break; 58940561Sbrian } 59040561Sbrian if (n == iface->in_addrs) 59140561Sbrian ipcp->my_ip = ipcp->cfg.my_range.ipaddr; 59240561Sbrian } 59336285Sbrian 59443313Sbrian if (IsEnabled(ipcp->cfg.vj.neg) 59543313Sbrian#ifndef NORADIUS 59643313Sbrian || (ipcp->fsm.bundle->radius.valid && ipcp->fsm.bundle->radius.vj) 59743313Sbrian#endif 59843313Sbrian ) 59936285Sbrian ipcp->my_compproto = (PROTO_VJCOMP << 16) + 60036285Sbrian ((ipcp->cfg.vj.slots - 1) << 8) + 60136285Sbrian ipcp->cfg.vj.slotcomp; 60236285Sbrian else 60336285Sbrian ipcp->my_compproto = 0; 60436285Sbrian sl_compress_init(&ipcp->vj.cslc, ipcp->cfg.vj.slots - 1); 60536285Sbrian 60636285Sbrian ipcp->peer_reject = 0; 60736285Sbrian ipcp->my_reject = 0; 60836285Sbrian} 60936285Sbrian 61036285Sbrianstatic int 61140665Sbrianipcp_doproxyall(struct bundle *bundle, 61240665Sbrian int (*proxyfun)(struct bundle *, struct in_addr, int), int s) 61340665Sbrian{ 61440665Sbrian int n, ret; 61540665Sbrian struct sticky_route *rp; 61640665Sbrian struct in_addr addr; 61740665Sbrian struct ipcp *ipcp; 61840665Sbrian 61940665Sbrian ipcp = &bundle->ncp.ipcp; 62040665Sbrian for (rp = ipcp->route; rp != NULL; rp = rp->next) { 62144455Sbrian if (rp->mask.s_addr == INADDR_BROADCAST) 62240665Sbrian continue; 62344455Sbrian n = ntohl(INADDR_BROADCAST) - ntohl(rp->mask.s_addr) - 1; 62440665Sbrian if (n > 0 && n <= 254 && rp->dst.s_addr != INADDR_ANY) { 62540665Sbrian addr = rp->dst; 62640665Sbrian while (n--) { 62740665Sbrian addr.s_addr = htonl(ntohl(addr.s_addr) + 1); 62840665Sbrian log_Printf(LogDEBUG, "ipcp_doproxyall: %s\n", inet_ntoa(addr)); 62940665Sbrian ret = (*proxyfun)(bundle, addr, s); 63040665Sbrian if (!ret) 63140665Sbrian return ret; 63240665Sbrian } 63340665Sbrian } 63440665Sbrian } 63540665Sbrian 63640665Sbrian return 0; 63740665Sbrian} 63840665Sbrian 63940665Sbrianstatic int 64036285Sbrianipcp_SetIPaddress(struct bundle *bundle, struct in_addr myaddr, 64136285Sbrian struct in_addr hisaddr, int silent) 64236285Sbrian{ 64347844Sbrian struct in_addr mask, oaddr, none = { INADDR_ANY }; 64436285Sbrian 64544455Sbrian mask = addr2mask(myaddr); 64636285Sbrian 64743313Sbrian if (bundle->ncp.ipcp.ifmask.s_addr != INADDR_ANY && 64844455Sbrian (bundle->ncp.ipcp.ifmask.s_addr & mask.s_addr) == mask.s_addr) 64944455Sbrian mask.s_addr = bundle->ncp.ipcp.ifmask.s_addr; 65036285Sbrian 65140561Sbrian oaddr.s_addr = bundle->iface->in_addrs ? 65240561Sbrian bundle->iface->in_addr[0].ifa.s_addr : INADDR_ANY; 65340561Sbrian if (!iface_inAdd(bundle->iface, myaddr, mask, hisaddr, 65440561Sbrian IFACE_ADD_FIRST|IFACE_FORCE_ADD)) 65540561Sbrian return -1; 65636285Sbrian 65740561Sbrian if (!Enabled(bundle, OPT_IFACEALIAS) && bundle->iface->in_addrs > 1 65840561Sbrian && myaddr.s_addr != oaddr.s_addr) 65940561Sbrian /* Nuke the old one */ 66040561Sbrian iface_inDelete(bundle->iface, oaddr); 66136285Sbrian 66240665Sbrian if (bundle->ncp.ipcp.cfg.sendpipe > 0 || bundle->ncp.ipcp.cfg.recvpipe > 0) 66340665Sbrian bundle_SetRoute(bundle, RTM_CHANGE, hisaddr, myaddr, none, 0, 0); 66440665Sbrian 66536285Sbrian if (Enabled(bundle, OPT_SROUTES)) 66636285Sbrian route_Change(bundle, bundle->ncp.ipcp.route, myaddr, hisaddr); 66736285Sbrian 66843313Sbrian#ifndef NORADIUS 66943313Sbrian if (bundle->radius.valid) 67043313Sbrian route_Change(bundle, bundle->radius.routes, myaddr, hisaddr); 67143313Sbrian#endif 67243313Sbrian 67340665Sbrian if (Enabled(bundle, OPT_PROXY) || Enabled(bundle, OPT_PROXYALL)) { 67440561Sbrian int s = ID0socket(AF_INET, SOCK_DGRAM, 0); 67540561Sbrian if (s < 0) 67640561Sbrian log_Printf(LogERROR, "ipcp_SetIPaddress: socket(): %s\n", 67740561Sbrian strerror(errno)); 67840561Sbrian else { 67940665Sbrian if (Enabled(bundle, OPT_PROXYALL)) 68040665Sbrian ipcp_doproxyall(bundle, arp_SetProxy, s); 68140665Sbrian else if (Enabled(bundle, OPT_PROXY)) 68240665Sbrian arp_SetProxy(bundle, hisaddr, s); 68340561Sbrian close(s); 68440561Sbrian } 68540561Sbrian } 68636285Sbrian 68740561Sbrian return 0; 6886059Samurai} 6896059Samurai 69036285Sbrianstatic struct in_addr 69140561SbrianChooseHisAddr(struct bundle *bundle, struct in_addr gw) 69236285Sbrian{ 69336285Sbrian struct in_addr try; 69437210Sbrian u_long f; 69536285Sbrian 69636285Sbrian for (f = 0; f < bundle->ncp.ipcp.cfg.peer_list.nItems; f++) { 69736285Sbrian try = iplist_next(&bundle->ncp.ipcp.cfg.peer_list); 69837210Sbrian log_Printf(LogDEBUG, "ChooseHisAddr: Check item %ld (%s)\n", 69936285Sbrian f, inet_ntoa(try)); 70036285Sbrian if (ipcp_SetIPaddress(bundle, gw, try, 1) == 0) { 70136285Sbrian log_Printf(LogIPCP, "Selected IP address %s\n", inet_ntoa(try)); 70236285Sbrian break; 70336285Sbrian } 70436285Sbrian } 70536285Sbrian 70636285Sbrian if (f == bundle->ncp.ipcp.cfg.peer_list.nItems) { 70736285Sbrian log_Printf(LogDEBUG, "ChooseHisAddr: All addresses in use !\n"); 70836285Sbrian try.s_addr = INADDR_ANY; 70936285Sbrian } 71036285Sbrian 71136285Sbrian return try; 71236285Sbrian} 71336285Sbrian 7146059Samuraistatic void 71544305SbrianIpcpInitRestartCounter(struct fsm *fp, int what) 7166059Samurai{ 71736285Sbrian /* Set fsm timer load */ 71836285Sbrian struct ipcp *ipcp = fsm2ipcp(fp); 71936285Sbrian 72044305Sbrian fp->FsmTimer.load = ipcp->cfg.fsm.timeout * SECTICKS; 72144305Sbrian switch (what) { 72244305Sbrian case FSM_REQ_TIMER: 72344305Sbrian fp->restart = ipcp->cfg.fsm.maxreq; 72444305Sbrian break; 72544305Sbrian case FSM_TRM_TIMER: 72644305Sbrian fp->restart = ipcp->cfg.fsm.maxtrm; 72744305Sbrian break; 72844305Sbrian default: 72944305Sbrian fp->restart = 1; 73044305Sbrian break; 73144305Sbrian } 7326059Samurai} 7336059Samurai 7346059Samuraistatic void 73536285SbrianIpcpSendConfigReq(struct fsm *fp) 7366059Samurai{ 73736285Sbrian /* Send config REQ please */ 73836285Sbrian struct physical *p = link2physical(fp->link); 73936285Sbrian struct ipcp *ipcp = fsm2ipcp(fp); 74036285Sbrian u_char buff[24]; 74136285Sbrian struct lcp_opt *o; 7426059Samurai 74336285Sbrian o = (struct lcp_opt *)buff; 74436285Sbrian 74536285Sbrian if ((p && !physical_IsSync(p)) || !REJECTED(ipcp, TY_IPADDR)) { 74638814Sbrian memcpy(o->data, &ipcp->my_ip.s_addr, 4); 74736285Sbrian INC_LCP_OPT(TY_IPADDR, 6, o); 74831514Sbrian } 74931514Sbrian 75036285Sbrian if (ipcp->my_compproto && !REJECTED(ipcp, TY_COMPPROTO)) { 75136285Sbrian if (ipcp->heis1172) { 75238814Sbrian u_int16_t proto = PROTO_VJCOMP; 75338814Sbrian 75438814Sbrian ua_htons(&proto, o->data); 75536285Sbrian INC_LCP_OPT(TY_COMPPROTO, 4, o); 75631514Sbrian } else { 75743545Sbrian struct compreq req; 75843545Sbrian 75943545Sbrian req.proto = htons(ipcp->my_compproto >> 16); 76043545Sbrian req.slots = (ipcp->my_compproto >> 8) & 255; 76143545Sbrian req.compcid = ipcp->my_compproto & 1; 76243545Sbrian memcpy(o->data, &req, 4); 76336285Sbrian INC_LCP_OPT(TY_COMPPROTO, 6, o); 76431514Sbrian } 7656059Samurai } 76636285Sbrian 76736285Sbrian if (IsEnabled(ipcp->cfg.ns.dns_neg) && 76836285Sbrian !REJECTED(ipcp, TY_PRIMARY_DNS - TY_ADJUST_NS) && 76936285Sbrian !REJECTED(ipcp, TY_SECONDARY_DNS - TY_ADJUST_NS)) { 77036285Sbrian struct in_addr dns[2]; 77136285Sbrian getdns(ipcp, dns); 77238814Sbrian memcpy(o->data, &dns[0].s_addr, 4); 77336285Sbrian INC_LCP_OPT(TY_PRIMARY_DNS, 6, o); 77438814Sbrian memcpy(o->data, &dns[1].s_addr, 4); 77536285Sbrian INC_LCP_OPT(TY_SECONDARY_DNS, 6, o); 77636285Sbrian } 77736285Sbrian 77847695Sbrian fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff, 77947695Sbrian MB_IPCPOUT); 7806059Samurai} 7816059Samurai 7826059Samuraistatic void 78344305SbrianIpcpSentTerminateReq(struct fsm *fp) 7846059Samurai{ 78536285Sbrian /* Term REQ just sent by FSM */ 7866059Samurai} 7876059Samurai 7886059Samuraistatic void 78936285SbrianIpcpSendTerminateAck(struct fsm *fp, u_char id) 7906059Samurai{ 79136285Sbrian /* Send Term ACK please */ 79247695Sbrian fsm_Output(fp, CODE_TERMACK, id, NULL, 0, MB_IPCPOUT); 7936059Samurai} 7946059Samurai 7956059Samuraistatic void 79637160SbrianIpcpLayerStart(struct fsm *fp) 7976059Samurai{ 79836285Sbrian /* We're about to start up ! */ 79937160Sbrian struct ipcp *ipcp = fsm2ipcp(fp); 80037160Sbrian 80137210Sbrian log_Printf(LogIPCP, "%s: LayerStart.\n", fp->link->name); 80237160Sbrian throughput_start(&ipcp->throughput, "IPCP throughput", 80337160Sbrian Enabled(fp->bundle, OPT_THROUGHPUT)); 80444305Sbrian fp->more.reqs = fp->more.naks = fp->more.rejs = ipcp->cfg.fsm.maxreq * 3; 8056059Samurai} 8066059Samurai 8076059Samuraistatic void 80836285SbrianIpcpLayerFinish(struct fsm *fp) 8096059Samurai{ 81036285Sbrian /* We're now down */ 81137160Sbrian struct ipcp *ipcp = fsm2ipcp(fp); 81237160Sbrian 81337210Sbrian log_Printf(LogIPCP, "%s: LayerFinish.\n", fp->link->name); 81437160Sbrian throughput_stop(&ipcp->throughput); 81537160Sbrian throughput_log(&ipcp->throughput, LogIPCP, NULL); 8166059Samurai} 8176059Samurai 81836285Sbrianvoid 81936285Sbrianipcp_CleanInterface(struct ipcp *ipcp) 8206059Samurai{ 82140561Sbrian struct iface *iface = ipcp->fsm.bundle->iface; 82236285Sbrian 82336285Sbrian route_Clean(ipcp->fsm.bundle, ipcp->route); 82436285Sbrian 82540665Sbrian if (iface->in_addrs && (Enabled(ipcp->fsm.bundle, OPT_PROXY) || 82640665Sbrian Enabled(ipcp->fsm.bundle, OPT_PROXYALL))) { 82740561Sbrian int s = ID0socket(AF_INET, SOCK_DGRAM, 0); 82840561Sbrian if (s < 0) 82940561Sbrian log_Printf(LogERROR, "ipcp_CleanInterface: socket: %s\n", 83040561Sbrian strerror(errno)); 83140561Sbrian else { 83240665Sbrian if (Enabled(ipcp->fsm.bundle, OPT_PROXYALL)) 83340665Sbrian ipcp_doproxyall(ipcp->fsm.bundle, arp_ClearProxy, s); 83440665Sbrian else if (Enabled(ipcp->fsm.bundle, OPT_PROXY)) 83540665Sbrian arp_ClearProxy(ipcp->fsm.bundle, iface->in_addr[0].brd, s); 83640561Sbrian close(s); 83740561Sbrian } 83836285Sbrian } 83936285Sbrian 84040561Sbrian iface_inClear(ipcp->fsm.bundle->iface, IFACE_CLEAR_ALL); 8416059Samurai} 8426059Samurai 8436059Samuraistatic void 84436285SbrianIpcpLayerDown(struct fsm *fp) 8456059Samurai{ 84636285Sbrian /* About to come down */ 84747835Sbrian static int recursing; 84836285Sbrian struct ipcp *ipcp = fsm2ipcp(fp); 84936285Sbrian const char *s; 8506059Samurai 85147835Sbrian if (!recursing++) { 85247835Sbrian if (ipcp->fsm.bundle->iface->in_addrs) 85347835Sbrian s = inet_ntoa(ipcp->fsm.bundle->iface->in_addr[0].ifa); 85447835Sbrian else 85547835Sbrian s = "Interface configuration error !"; 85647835Sbrian log_Printf(LogIPCP, "%s: LayerDown: %s\n", fp->link->name, s); 85730187Sbrian 85847835Sbrian /* 85947835Sbrian * XXX this stuff should really live in the FSM. Our config should 86047835Sbrian * associate executable sections in files with events. 86147835Sbrian */ 86247835Sbrian if (system_Select(fp->bundle, s, LINKDOWNFILE, NULL, NULL) < 0) { 86347835Sbrian if (bundle_GetLabel(fp->bundle)) { 86447835Sbrian if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle), 86547835Sbrian LINKDOWNFILE, NULL, NULL) < 0) 86647835Sbrian system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL); 86747835Sbrian } else 86847835Sbrian system_Select(fp->bundle, "MYADDR", LINKDOWNFILE, NULL, NULL); 86947835Sbrian } 87047835Sbrian 87147835Sbrian ipcp_Setup(ipcp, INADDR_NONE); 87236285Sbrian } 87347835Sbrian recursing--; 87436285Sbrian} 87536285Sbrian 87636285Sbrianint 87736285Sbrianipcp_InterfaceUp(struct ipcp *ipcp) 87836285Sbrian{ 87936285Sbrian if (ipcp_SetIPaddress(ipcp->fsm.bundle, ipcp->my_ip, ipcp->peer_ip, 0) < 0) { 88037019Sbrian log_Printf(LogERROR, "ipcp_InterfaceUp: unable to set ip address\n"); 88136285Sbrian return 0; 88225630Sbrian } 88336285Sbrian 88450059Sbrian#ifndef NONAT 88550059Sbrian if (ipcp->fsm.bundle->NatEnabled) 88637191Sbrian PacketAliasSetAddress(ipcp->my_ip); 88731343Sbrian#endif 88836285Sbrian 88936285Sbrian return 1; 8906059Samurai} 8916059Samurai 89236285Sbrianstatic int 89336285SbrianIpcpLayerUp(struct fsm *fp) 8946059Samurai{ 89536285Sbrian /* We're now up */ 89636285Sbrian struct ipcp *ipcp = fsm2ipcp(fp); 89740561Sbrian char tbuff[16]; 8986059Samurai 89937210Sbrian log_Printf(LogIPCP, "%s: LayerUp.\n", fp->link->name); 90040561Sbrian snprintf(tbuff, sizeof tbuff, "%s", inet_ntoa(ipcp->my_ip)); 90140561Sbrian log_Printf(LogIPCP, "myaddr %s hisaddr = %s\n", 90240561Sbrian tbuff, inet_ntoa(ipcp->peer_ip)); 90336285Sbrian 90436285Sbrian if (ipcp->peer_compproto >> 16 == PROTO_VJCOMP) 90536285Sbrian sl_compress_init(&ipcp->vj.cslc, (ipcp->peer_compproto >> 8) & 255); 90636285Sbrian 90736285Sbrian if (!ipcp_InterfaceUp(ipcp)) 90836285Sbrian return 0; 90936285Sbrian 91036285Sbrian /* 91136285Sbrian * XXX this stuff should really live in the FSM. Our config should 91236285Sbrian * associate executable sections in files with events. 91336285Sbrian */ 91440561Sbrian if (system_Select(fp->bundle, tbuff, LINKUPFILE, NULL, NULL) < 0) { 91536285Sbrian if (bundle_GetLabel(fp->bundle)) { 91636285Sbrian if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle), 91737008Sbrian LINKUPFILE, NULL, NULL) < 0) 91837008Sbrian system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL); 91936285Sbrian } else 92037008Sbrian system_Select(fp->bundle, "MYADDR", LINKUPFILE, NULL, NULL); 92136285Sbrian } 92236285Sbrian 92344305Sbrian fp->more.reqs = fp->more.naks = fp->more.rejs = ipcp->cfg.fsm.maxreq * 3; 92436314Sbrian log_DisplayPrompts(); 92544305Sbrian 92636285Sbrian return 1; 9276059Samurai} 9286059Samurai 9296059Samuraistatic int 93040561SbrianAcceptableAddr(const struct in_range *prange, struct in_addr ipaddr) 9316059Samurai{ 93236285Sbrian /* Is the given IP in the given range ? */ 93325661Sbrian return (prange->ipaddr.s_addr & prange->mask.s_addr) == 93428679Sbrian (ipaddr.s_addr & prange->mask.s_addr) && ipaddr.s_addr; 9356059Samurai} 9366059Samurai 9376059Samuraistatic void 93846828SbrianIpcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, 93936285Sbrian struct fsm_decode *dec) 9406059Samurai{ 94136285Sbrian /* Deal with incoming PROTO_IPCP */ 94240561Sbrian struct iface *iface = fp->bundle->iface; 94336285Sbrian struct ipcp *ipcp = fsm2ipcp(fp); 94440561Sbrian int type, length, gotdns, gotdnsnak, n; 94536285Sbrian u_int32_t compproto; 9466059Samurai struct compreq *pcomp; 94736285Sbrian struct in_addr ipaddr, dstipaddr, have_ip, dns[2], dnsnak[2]; 94836285Sbrian char tbuff[100], tbuff2[100]; 9496059Samurai 95036285Sbrian gotdns = 0; 95136285Sbrian gotdnsnak = 0; 95236285Sbrian dnsnak[0].s_addr = dnsnak[1].s_addr = INADDR_ANY; 9536059Samurai 9546059Samurai while (plen >= sizeof(struct fsmconfig)) { 9556059Samurai type = *cp; 9566059Samurai length = cp[1]; 95736285Sbrian 95836285Sbrian if (length == 0) { 95936285Sbrian log_Printf(LogIPCP, "%s: IPCP size zero\n", fp->link->name); 96036285Sbrian break; 96136285Sbrian } 96236285Sbrian 96331171Sbrian if (type < NCFTYPES) 96431962Sbrian snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes[type], length); 96531171Sbrian else if (type > 128 && type < 128 + NCFTYPES128) 96631962Sbrian snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes128[type-128], length); 9676059Samurai else 96831962Sbrian snprintf(tbuff, sizeof tbuff, " <%d>[%d] ", type, length); 9696059Samurai 9706059Samurai switch (type) { 9716059Samurai case TY_IPADDR: /* RFC1332 */ 97238814Sbrian memcpy(&ipaddr.s_addr, cp + 2, 4); 97336285Sbrian log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 9746059Samurai 97531034Sbrian switch (mode_type) { 9766059Samurai case MODE_REQ: 97736285Sbrian if (iplist_isvalid(&ipcp->cfg.peer_list)) { 97831850Sbrian if (ipaddr.s_addr == INADDR_ANY || 97936285Sbrian iplist_ip2pos(&ipcp->cfg.peer_list, ipaddr) < 0 || 98036285Sbrian ipcp_SetIPaddress(fp->bundle, ipcp->cfg.my_range.ipaddr, 98136285Sbrian ipaddr, 1)) { 98236285Sbrian log_Printf(LogIPCP, "%s: Address invalid or already in use\n", 98331690Sbrian inet_ntoa(ipaddr)); 98440561Sbrian /* 98540561Sbrian * If we've already had a valid address configured for the peer, 98640561Sbrian * try NAKing with that so that we don't have to upset things 98740561Sbrian * too much. 98840561Sbrian */ 98940561Sbrian for (n = 0; n < iface->in_addrs; n++) 99040561Sbrian if (iplist_ip2pos(&ipcp->cfg.peer_list, iface->in_addr[n].brd) 99140561Sbrian >=0) { 99240561Sbrian ipcp->peer_ip = iface->in_addr[n].brd; 99340561Sbrian break; 99440561Sbrian } 99540561Sbrian 99640561Sbrian if (n == iface->in_addrs) 99736285Sbrian /* Just pick an IP number from our list */ 99836285Sbrian ipcp->peer_ip = ChooseHisAddr 99936285Sbrian (fp->bundle, ipcp->cfg.my_range.ipaddr); 100036285Sbrian 100136285Sbrian if (ipcp->peer_ip.s_addr == INADDR_ANY) { 100236285Sbrian memcpy(dec->rejend, cp, length); 100336285Sbrian dec->rejend += length; 100431690Sbrian } else { 100536285Sbrian memcpy(dec->nakend, cp, 2); 100640561Sbrian memcpy(dec->nakend + 2, &ipcp->peer_ip.s_addr, length - 2); 100736285Sbrian dec->nakend += length; 100831690Sbrian } 100931690Sbrian break; 101031690Sbrian } 101136285Sbrian } else if (!AcceptableAddr(&ipcp->cfg.peer_range, ipaddr)) { 101228679Sbrian /* 101336285Sbrian * If destination address is not acceptable, NAK with what we 101428679Sbrian * want to use. 101528679Sbrian */ 101636285Sbrian memcpy(dec->nakend, cp, 2); 101740561Sbrian for (n = 0; n < iface->in_addrs; n++) 101840561Sbrian if ((iface->in_addr[n].brd.s_addr & 101940561Sbrian ipcp->cfg.peer_range.mask.s_addr) 102040561Sbrian == (ipcp->cfg.peer_range.ipaddr.s_addr & 102140561Sbrian ipcp->cfg.peer_range.mask.s_addr)) { 102240561Sbrian /* We prefer the already-configured address */ 102340561Sbrian memcpy(dec->nakend + 2, &iface->in_addr[n].brd.s_addr, 102440561Sbrian length - 2); 102540561Sbrian break; 102640561Sbrian } 102740561Sbrian 102840561Sbrian if (n == iface->in_addrs) 102940561Sbrian memcpy(dec->nakend + 2, &ipcp->peer_ip.s_addr, length - 2); 103040561Sbrian 103136285Sbrian dec->nakend += length; 103228679Sbrian break; 10336059Samurai } 103436285Sbrian ipcp->peer_ip = ipaddr; 103536285Sbrian memcpy(dec->ackend, cp, length); 103636285Sbrian dec->ackend += length; 10376059Samurai break; 103840561Sbrian 10396059Samurai case MODE_NAK: 104036285Sbrian if (AcceptableAddr(&ipcp->cfg.my_range, ipaddr)) { 104131690Sbrian /* Use address suggested by peer */ 104231962Sbrian snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s ", tbuff, 104336285Sbrian inet_ntoa(ipcp->my_ip)); 104436285Sbrian log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 104536285Sbrian ipcp->my_ip = ipaddr; 104647648Sbrian bundle_AdjustFilters(fp->bundle, &ipcp->my_ip, NULL); 104731690Sbrian } else { 104836285Sbrian log_Printf(log_IsKept(LogIPCP) ? LogIPCP : LogPHASE, 104936285Sbrian "%s: Unacceptable address!\n", inet_ntoa(ipaddr)); 105036285Sbrian fsm_Close(&ipcp->fsm); 10516059Samurai } 10526059Samurai break; 105340561Sbrian 10546059Samurai case MODE_REJ: 105536285Sbrian ipcp->peer_reject |= (1 << type); 10566059Samurai break; 10576059Samurai } 10586059Samurai break; 105940561Sbrian 10606059Samurai case TY_COMPPROTO: 106143545Sbrian pcomp = (struct compreq *)(cp + 2); 106243545Sbrian compproto = (ntohs(pcomp->proto) << 16) + (pcomp->slots << 8) + 106343545Sbrian pcomp->compcid; 106436285Sbrian log_Printf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto)); 10656059Samurai 106631034Sbrian switch (mode_type) { 10676059Samurai case MODE_REQ: 106836285Sbrian if (!IsAccepted(ipcp->cfg.vj.neg)) { 106936285Sbrian memcpy(dec->rejend, cp, length); 107036285Sbrian dec->rejend += length; 10716059Samurai } else { 10726059Samurai switch (length) { 107328679Sbrian case 4: /* RFC1172 */ 10746059Samurai if (ntohs(pcomp->proto) == PROTO_VJCOMP) { 107543545Sbrian log_Printf(LogWARN, "Peer is speaking RFC1172 compression " 107643545Sbrian "protocol !\n"); 107736285Sbrian ipcp->heis1172 = 1; 107836285Sbrian ipcp->peer_compproto = compproto; 107936285Sbrian memcpy(dec->ackend, cp, length); 108036285Sbrian dec->ackend += length; 10816059Samurai } else { 108236285Sbrian memcpy(dec->nakend, cp, 2); 10836059Samurai pcomp->proto = htons(PROTO_VJCOMP); 108436285Sbrian memcpy(dec->nakend+2, &pcomp, 2); 108536285Sbrian dec->nakend += length; 10866059Samurai } 10876059Samurai break; 108828679Sbrian case 6: /* RFC1332 */ 108943545Sbrian if (ntohs(pcomp->proto) == PROTO_VJCOMP) { 109043545Sbrian if (pcomp->slots <= MAX_VJ_STATES 109143545Sbrian && pcomp->slots >= MIN_VJ_STATES) { 109243545Sbrian /* Ok, we can do that */ 109343545Sbrian ipcp->peer_compproto = compproto; 109443545Sbrian ipcp->heis1172 = 0; 109543545Sbrian memcpy(dec->ackend, cp, length); 109643545Sbrian dec->ackend += length; 109743545Sbrian } else { 109843545Sbrian /* Get as close as we can to what he wants */ 109943545Sbrian ipcp->heis1172 = 0; 110043545Sbrian memcpy(dec->nakend, cp, 2); 110143545Sbrian pcomp->slots = pcomp->slots < MIN_VJ_STATES ? 110243545Sbrian MIN_VJ_STATES : MAX_VJ_STATES; 110343545Sbrian memcpy(dec->nakend+2, &pcomp, sizeof pcomp); 110443545Sbrian dec->nakend += length; 110543545Sbrian } 11066059Samurai } else { 110743545Sbrian /* What we really want */ 110836285Sbrian memcpy(dec->nakend, cp, 2); 11096059Samurai pcomp->proto = htons(PROTO_VJCOMP); 111036285Sbrian pcomp->slots = DEF_VJ_STATES; 111143545Sbrian pcomp->compcid = 1; 111236285Sbrian memcpy(dec->nakend+2, &pcomp, sizeof pcomp); 111336285Sbrian dec->nakend += length; 11146059Samurai } 11156059Samurai break; 11166059Samurai default: 111736285Sbrian memcpy(dec->rejend, cp, length); 111836285Sbrian dec->rejend += length; 11196059Samurai break; 11206059Samurai } 11216059Samurai } 11226059Samurai break; 112340561Sbrian 11246059Samurai case MODE_NAK: 112543545Sbrian if (ntohs(pcomp->proto) == PROTO_VJCOMP) { 112643545Sbrian if (pcomp->slots > MAX_VJ_STATES) 112743545Sbrian pcomp->slots = MAX_VJ_STATES; 112843545Sbrian else if (pcomp->slots < MIN_VJ_STATES) 112943545Sbrian pcomp->slots = MIN_VJ_STATES; 113043545Sbrian compproto = (ntohs(pcomp->proto) << 16) + (pcomp->slots << 8) + 113143545Sbrian pcomp->compcid; 113243545Sbrian } else 113343545Sbrian compproto = 0; 113436285Sbrian log_Printf(LogIPCP, "%s changing compproto: %08x --> %08x\n", 113536285Sbrian tbuff, ipcp->my_compproto, compproto); 113643545Sbrian ipcp->my_compproto = compproto; 11376059Samurai break; 113840561Sbrian 11396059Samurai case MODE_REJ: 114036285Sbrian ipcp->peer_reject |= (1 << type); 11416059Samurai break; 11426059Samurai } 11436059Samurai break; 114440561Sbrian 114528679Sbrian case TY_IPADDRS: /* RFC1172 */ 114638814Sbrian memcpy(&ipaddr.s_addr, cp + 2, 4); 114738814Sbrian memcpy(&dstipaddr.s_addr, cp + 6, 4); 114831962Sbrian snprintf(tbuff2, sizeof tbuff2, "%s %s,", tbuff, inet_ntoa(ipaddr)); 114936285Sbrian log_Printf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr)); 11506059Samurai 115131034Sbrian switch (mode_type) { 11526059Samurai case MODE_REQ: 115346686Sbrian memcpy(dec->rejend, cp, length); 115446686Sbrian dec->rejend += length; 11556059Samurai break; 115640561Sbrian 11576059Samurai case MODE_NAK: 11586059Samurai case MODE_REJ: 11596059Samurai break; 11606059Samurai } 11616059Samurai break; 116218752Sjkh 116336285Sbrian case TY_PRIMARY_DNS: /* DNS negotiation (rfc1877) */ 116436285Sbrian case TY_SECONDARY_DNS: 116538814Sbrian memcpy(&ipaddr.s_addr, cp + 2, 4); 116636285Sbrian log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 116718752Sjkh 116831034Sbrian switch (mode_type) { 116918752Sjkh case MODE_REQ: 117036285Sbrian if (!IsAccepted(ipcp->cfg.ns.dns_neg)) { 117136285Sbrian ipcp->my_reject |= (1 << (type - TY_ADJUST_NS)); 117236285Sbrian memcpy(dec->rejend, cp, length); 117336285Sbrian dec->rejend += length; 117436285Sbrian break; 117536285Sbrian } 117636285Sbrian if (!gotdns) { 117736285Sbrian dns[0] = ipcp->cfg.ns.dns[0]; 117836285Sbrian dns[1] = ipcp->cfg.ns.dns[1]; 117936285Sbrian if (dns[0].s_addr == INADDR_ANY && dns[1].s_addr == INADDR_ANY) 118036285Sbrian getdns(ipcp, dns); 118136285Sbrian gotdns = 1; 118236285Sbrian } 118336285Sbrian have_ip = dns[type == TY_PRIMARY_DNS ? 0 : 1]; 118428679Sbrian 118536285Sbrian if (ipaddr.s_addr != have_ip.s_addr) { 118618752Sjkh /* 118736285Sbrian * The client has got the DNS stuff wrong (first request) so 118828974Sbrian * we'll tell 'em how it is 118928679Sbrian */ 119036285Sbrian memcpy(dec->nakend, cp, 2); /* copy first two (type/length) */ 119136285Sbrian memcpy(dec->nakend + 2, &have_ip.s_addr, length - 2); 119236285Sbrian dec->nakend += length; 119336285Sbrian } else { 119436285Sbrian /* 119536285Sbrian * Otherwise they have it right (this time) so we send a ack packet 119636285Sbrian * back confirming it... end of story 119736285Sbrian */ 119836285Sbrian memcpy(dec->ackend, cp, length); 119936285Sbrian dec->ackend += length; 120036285Sbrian } 120118752Sjkh break; 120240561Sbrian 120328679Sbrian case MODE_NAK: /* what does this mean?? */ 120436285Sbrian if (IsEnabled(ipcp->cfg.ns.dns_neg)) { 120536285Sbrian gotdnsnak = 1; 120638814Sbrian memcpy(&dnsnak[type == TY_PRIMARY_DNS ? 0 : 1].s_addr, cp + 2, 4); 120736285Sbrian } 120818752Sjkh break; 120940561Sbrian 121036285Sbrian case MODE_REJ: /* Can't do much, stop asking */ 121136285Sbrian ipcp->peer_reject |= (1 << (type - TY_ADJUST_NS)); 121218752Sjkh break; 121318752Sjkh } 121418752Sjkh break; 121518752Sjkh 121636285Sbrian case TY_PRIMARY_NBNS: /* M$ NetBIOS nameserver hack (rfc1877) */ 121718752Sjkh case TY_SECONDARY_NBNS: 121838814Sbrian memcpy(&ipaddr.s_addr, cp + 2, 4); 121936285Sbrian log_Printf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 122036285Sbrian 122131034Sbrian switch (mode_type) { 122218752Sjkh case MODE_REQ: 122336285Sbrian have_ip.s_addr = 122436285Sbrian ipcp->cfg.ns.nbns[type == TY_PRIMARY_NBNS ? 0 : 1].s_addr; 122536285Sbrian 122636285Sbrian if (have_ip.s_addr == INADDR_ANY) { 122736285Sbrian log_Printf(LogIPCP, "NBNS REQ - rejected - nbns not set\n"); 122836285Sbrian ipcp->my_reject |= (1 << (type - TY_ADJUST_NS)); 122936285Sbrian memcpy(dec->rejend, cp, length); 123036285Sbrian dec->rejend += length; 123118752Sjkh break; 123236285Sbrian } 123336285Sbrian 123436285Sbrian if (ipaddr.s_addr != have_ip.s_addr) { 123536285Sbrian memcpy(dec->nakend, cp, 2); 123636285Sbrian memcpy(dec->nakend+2, &have_ip.s_addr, length); 123736285Sbrian dec->nakend += length; 123836285Sbrian } else { 123936285Sbrian memcpy(dec->ackend, cp, length); 124036285Sbrian dec->ackend += length; 124136285Sbrian } 124218752Sjkh break; 124340561Sbrian 124418752Sjkh case MODE_NAK: 124536285Sbrian log_Printf(LogIPCP, "MS NBNS req %d - NAK??\n", type); 124618752Sjkh break; 124740561Sbrian 124818752Sjkh case MODE_REJ: 124936285Sbrian log_Printf(LogIPCP, "MS NBNS req %d - REJ??\n", type); 125018752Sjkh break; 125118752Sjkh } 125218752Sjkh break; 125318752Sjkh 12546059Samurai default: 125536285Sbrian if (mode_type != MODE_NOP) { 125636285Sbrian ipcp->my_reject |= (1 << type); 125736285Sbrian memcpy(dec->rejend, cp, length); 125836285Sbrian dec->rejend += length; 125936285Sbrian } 12606059Samurai break; 12616059Samurai } 12626059Samurai plen -= length; 12636059Samurai cp += length; 12646059Samurai } 126536285Sbrian 126636285Sbrian if (gotdnsnak) 126736285Sbrian if (!setdns(ipcp, dnsnak)) { 126836285Sbrian ipcp->peer_reject |= (1 << (TY_PRIMARY_DNS - TY_ADJUST_NS)); 126936285Sbrian ipcp->peer_reject |= (1 << (TY_SECONDARY_DNS - TY_ADJUST_NS)); 127036285Sbrian } 127136285Sbrian 127236285Sbrian if (mode_type != MODE_NOP) { 127336285Sbrian if (dec->rejend != dec->rej) { 127436285Sbrian /* rejects are preferred */ 127536285Sbrian dec->ackend = dec->ack; 127636285Sbrian dec->nakend = dec->nak; 127736285Sbrian } else if (dec->nakend != dec->nak) 127836285Sbrian /* then NAKs */ 127936285Sbrian dec->ackend = dec->ack; 128036285Sbrian } 12816059Samurai} 12826059Samurai 128346686Sbrianextern struct mbuf * 128446686Sbrianipcp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 12856059Samurai{ 128636285Sbrian /* Got PROTO_IPCP from link */ 128754912Sbrian m_settype(bp, MB_IPCPIN); 128836285Sbrian if (bundle_Phase(bundle) == PHASE_NETWORK) 128946686Sbrian fsm_Input(&bundle->ncp.ipcp.fsm, bp); 129036285Sbrian else { 129136285Sbrian if (bundle_Phase(bundle) < PHASE_NETWORK) 129236285Sbrian log_Printf(LogIPCP, "%s: Error: Unexpected IPCP in phase %s (ignored)\n", 129346686Sbrian l->name, bundle_PhaseName(bundle)); 129454912Sbrian m_freem(bp); 129536285Sbrian } 129646686Sbrian return NULL; 12976059Samurai} 129832267Sbrian 129932267Sbrianint 130043313Sbrianipcp_UseHisIPaddr(struct bundle *bundle, struct in_addr hisaddr) 130143313Sbrian{ 130243313Sbrian struct ipcp *ipcp = &bundle->ncp.ipcp; 130343313Sbrian 130443313Sbrian memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 130543313Sbrian iplist_reset(&ipcp->cfg.peer_list); 130643313Sbrian ipcp->peer_ip = ipcp->cfg.peer_range.ipaddr = hisaddr; 130743313Sbrian ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 130843313Sbrian ipcp->cfg.peer_range.width = 32; 130943313Sbrian 131043313Sbrian if (ipcp_SetIPaddress(bundle, ipcp->cfg.my_range.ipaddr, hisaddr, 0) < 0) 131143313Sbrian return 0; 131243313Sbrian 131343313Sbrian return 1; /* Ok */ 131443313Sbrian} 131543313Sbrian 131643313Sbrianint 131736285Sbrianipcp_UseHisaddr(struct bundle *bundle, const char *hisaddr, int setaddr) 131832267Sbrian{ 131936285Sbrian struct ipcp *ipcp = &bundle->ncp.ipcp; 132036285Sbrian 132136285Sbrian /* Use `hisaddr' for the peers address (set iface if `setaddr') */ 132236285Sbrian memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 132336285Sbrian iplist_reset(&ipcp->cfg.peer_list); 132432267Sbrian if (strpbrk(hisaddr, ",-")) { 132536285Sbrian iplist_setsrc(&ipcp->cfg.peer_list, hisaddr); 132636285Sbrian if (iplist_isvalid(&ipcp->cfg.peer_list)) { 132736285Sbrian iplist_setrandpos(&ipcp->cfg.peer_list); 132836285Sbrian ipcp->peer_ip = ChooseHisAddr(bundle, ipcp->my_ip); 132936285Sbrian if (ipcp->peer_ip.s_addr == INADDR_ANY) { 133036285Sbrian log_Printf(LogWARN, "%s: None available !\n", ipcp->cfg.peer_list.src); 133147648Sbrian return 0; 133232267Sbrian } 133336285Sbrian ipcp->cfg.peer_range.ipaddr.s_addr = ipcp->peer_ip.s_addr; 133436285Sbrian ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 133536285Sbrian ipcp->cfg.peer_range.width = 32; 133632267Sbrian } else { 133736285Sbrian log_Printf(LogWARN, "%s: Invalid range !\n", hisaddr); 133832267Sbrian return 0; 133932267Sbrian } 134043313Sbrian } else if (ParseAddr(ipcp, hisaddr, &ipcp->cfg.peer_range.ipaddr, 134136285Sbrian &ipcp->cfg.peer_range.mask, 134236285Sbrian &ipcp->cfg.peer_range.width) != 0) { 134336285Sbrian ipcp->peer_ip.s_addr = ipcp->cfg.peer_range.ipaddr.s_addr; 134432267Sbrian 134536285Sbrian if (setaddr && ipcp_SetIPaddress(bundle, ipcp->cfg.my_range.ipaddr, 134640561Sbrian ipcp->cfg.peer_range.ipaddr, 0) < 0) 134732267Sbrian return 0; 134832267Sbrian } else 134932267Sbrian return 0; 135032267Sbrian 135147648Sbrian bundle_AdjustFilters(bundle, NULL, &ipcp->peer_ip); 135247648Sbrian 135347648Sbrian return 1; /* Ok */ 135432267Sbrian} 135544455Sbrian 135644455Sbrianstruct in_addr 135744455Sbrianaddr2mask(struct in_addr addr) 135844455Sbrian{ 135944455Sbrian u_int32_t haddr = ntohl(addr.s_addr); 136044455Sbrian 136144455Sbrian haddr = IN_CLASSA(haddr) ? IN_CLASSA_NET : 136244455Sbrian IN_CLASSB(haddr) ? IN_CLASSB_NET : 136344455Sbrian IN_CLASSC_NET; 136444455Sbrian addr.s_addr = htonl(haddr); 136544455Sbrian 136644455Sbrian return addr; 136744455Sbrian} 1368