11ae349f5Scvs2svn /* 21ae349f5Scvs2svn * PPP IP Control Protocol (IPCP) Module 31ae349f5Scvs2svn * 41ae349f5Scvs2svn * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 51ae349f5Scvs2svn * 61ae349f5Scvs2svn * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 71ae349f5Scvs2svn * 81ae349f5Scvs2svn * Redistribution and use in source and binary forms are permitted 91ae349f5Scvs2svn * provided that the above copyright notice and this paragraph are 101ae349f5Scvs2svn * duplicated in all such forms and that any documentation, 111ae349f5Scvs2svn * advertising materials, and other materials related to such 121ae349f5Scvs2svn * distribution and use acknowledge that the software was developed 131ae349f5Scvs2svn * by the Internet Initiative Japan, Inc. The name of the 141ae349f5Scvs2svn * IIJ may not be used to endorse or promote products derived 151ae349f5Scvs2svn * from this software without specific prior written permission. 161ae349f5Scvs2svn * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 171ae349f5Scvs2svn * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 181ae349f5Scvs2svn * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 191ae349f5Scvs2svn * 20455aabc3SBrian Somers * $Id: ipcp.c,v 1.50.2.8 1998/02/06 02:24:19 brian Exp $ 211ae349f5Scvs2svn * 221ae349f5Scvs2svn * TODO: 231ae349f5Scvs2svn * o More RFC1772 backwoard compatibility 241ae349f5Scvs2svn */ 251ae349f5Scvs2svn #include <sys/param.h> 261ae349f5Scvs2svn #include <netinet/in_systm.h> 271ae349f5Scvs2svn #include <netinet/in.h> 281ae349f5Scvs2svn #include <netinet/ip.h> 291ae349f5Scvs2svn #include <arpa/inet.h> 301ae349f5Scvs2svn #include <sys/socket.h> 311ae349f5Scvs2svn #include <netdb.h> 32455aabc3SBrian Somers #include <sys/time.h> 33455aabc3SBrian Somers #include <net/if.h> 34455aabc3SBrian Somers #include <sys/sockio.h> 351ae349f5Scvs2svn 361ae349f5Scvs2svn #include <stdio.h> 371ae349f5Scvs2svn #include <stdlib.h> 381ae349f5Scvs2svn #include <string.h> 39455aabc3SBrian Somers #include <sys/errno.h> 406140ba11SBrian Somers #include <termios.h> 411ae349f5Scvs2svn #include <unistd.h> 421ae349f5Scvs2svn 431ae349f5Scvs2svn #include "command.h" 441ae349f5Scvs2svn #include "mbuf.h" 451ae349f5Scvs2svn #include "log.h" 461ae349f5Scvs2svn #include "defs.h" 471ae349f5Scvs2svn #include "timer.h" 481ae349f5Scvs2svn #include "fsm.h" 491ae349f5Scvs2svn #include "lcpproto.h" 501ae349f5Scvs2svn #include "lcp.h" 511ae349f5Scvs2svn #include "iplist.h" 5229e275ceSBrian Somers #include "throughput.h" 531ae349f5Scvs2svn #include "ipcp.h" 541ae349f5Scvs2svn #include "slcompress.h" 557a6f8720SBrian Somers #include "bundle.h" 561ae349f5Scvs2svn #include "loadalias.h" 571ae349f5Scvs2svn #include "vars.h" 581ae349f5Scvs2svn #include "vjcomp.h" 591ae349f5Scvs2svn #include "ip.h" 601ae349f5Scvs2svn #include "route.h" 611ae349f5Scvs2svn #include "filter.h" 628c07a7b2SBrian Somers #include "hdlc.h" 636140ba11SBrian Somers #include "async.h" 648c07a7b2SBrian Somers #include "link.h" 6563b73463SBrian Somers #include "physical.h" 66455aabc3SBrian Somers #include "id.h" 67455aabc3SBrian Somers #include "arp.h" 68455aabc3SBrian Somers #include "systems.h" 691ae349f5Scvs2svn 7029e275ceSBrian Somers struct compreq { 7129e275ceSBrian Somers u_short proto; 7229e275ceSBrian Somers u_char slots; 7329e275ceSBrian Somers u_char compcid; 7429e275ceSBrian Somers }; 751ae349f5Scvs2svn 761ae349f5Scvs2svn static void IpcpLayerUp(struct fsm *); 771ae349f5Scvs2svn static void IpcpLayerDown(struct fsm *); 787308ec68SBrian Somers static void IpcpLayerStart(struct fsm *); 797308ec68SBrian Somers static void IpcpLayerFinish(struct fsm *); 801ae349f5Scvs2svn static void IpcpInitRestartCounter(struct fsm *); 817308ec68SBrian Somers static void IpcpSendConfigReq(struct fsm *); 827308ec68SBrian Somers static void IpcpSendTerminateReq(struct fsm *); 837308ec68SBrian Somers static void IpcpSendTerminateAck(struct fsm *); 8483d1af55SBrian Somers static void IpcpDecodeConfig(struct fsm *, u_char *, int, int); 8583d1af55SBrian Somers 8683d1af55SBrian Somers static struct fsm_callbacks ipcp_Callbacks = { 8783d1af55SBrian Somers IpcpLayerUp, 8883d1af55SBrian Somers IpcpLayerDown, 8983d1af55SBrian Somers IpcpLayerStart, 9083d1af55SBrian Somers IpcpLayerFinish, 9183d1af55SBrian Somers IpcpInitRestartCounter, 9283d1af55SBrian Somers IpcpSendConfigReq, 9383d1af55SBrian Somers IpcpSendTerminateReq, 9483d1af55SBrian Somers IpcpSendTerminateAck, 9583d1af55SBrian Somers IpcpDecodeConfig, 9683d1af55SBrian Somers }; 971ae349f5Scvs2svn 987308ec68SBrian Somers struct ipcpstate IpcpInfo = { 997308ec68SBrian Somers { 1001ae349f5Scvs2svn "IPCP", 1011ae349f5Scvs2svn PROTO_IPCP, 1021ae349f5Scvs2svn IPCP_MAXCODE, 1031ae349f5Scvs2svn 0, 1041ae349f5Scvs2svn ST_INITIAL, 1051ae349f5Scvs2svn 0, 0, 0, 1061ae349f5Scvs2svn {0, 0, 0, NULL, NULL, NULL}, /* FSM timer */ 1071ae349f5Scvs2svn {0, 0, 0, NULL, NULL, NULL}, /* Open timer */ 1081ae349f5Scvs2svn {0, 0, 0, NULL, NULL, NULL}, /* Stopped timer */ 1091ae349f5Scvs2svn LogIPCP, 1107a6f8720SBrian Somers NULL, /* link */ 1117a6f8720SBrian Somers NULL, /* bundle */ 11283d1af55SBrian Somers &ipcp_Callbacks, 1137308ec68SBrian Somers }, 1147308ec68SBrian Somers MAX_VJ_STATES, 1157308ec68SBrian Somers 1 1161ae349f5Scvs2svn }; 1171ae349f5Scvs2svn 1181ae349f5Scvs2svn static const char *cftypes[] = { 1191ae349f5Scvs2svn /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */ 1201ae349f5Scvs2svn "???", 1211ae349f5Scvs2svn "IPADDRS", /* 1: IP-Addresses */ /* deprecated */ 1221ae349f5Scvs2svn "COMPPROTO", /* 2: IP-Compression-Protocol */ 1231ae349f5Scvs2svn "IPADDR", /* 3: IP-Address */ 1241ae349f5Scvs2svn }; 1251ae349f5Scvs2svn 1261ae349f5Scvs2svn #define NCFTYPES (sizeof cftypes/sizeof cftypes[0]) 1271ae349f5Scvs2svn 1281ae349f5Scvs2svn static const char *cftypes128[] = { 1291ae349f5Scvs2svn /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */ 1301ae349f5Scvs2svn "???", 1311ae349f5Scvs2svn "PRIDNS", /* 129: Primary DNS Server Address */ 1321ae349f5Scvs2svn "PRINBNS", /* 130: Primary NBNS Server Address */ 1331ae349f5Scvs2svn "SECDNS", /* 131: Secondary DNS Server Address */ 1341ae349f5Scvs2svn "SECNBNS", /* 132: Secondary NBNS Server Address */ 1351ae349f5Scvs2svn }; 1361ae349f5Scvs2svn 1371ae349f5Scvs2svn #define NCFTYPES128 (sizeof cftypes128/sizeof cftypes128[0]) 1381ae349f5Scvs2svn 1391ae349f5Scvs2svn void 1401ae349f5Scvs2svn IpcpAddInOctets(int n) 1411ae349f5Scvs2svn { 14229e275ceSBrian Somers throughput_addin(&IpcpInfo.throughput, n); 1431ae349f5Scvs2svn } 1441ae349f5Scvs2svn 1451ae349f5Scvs2svn void 1461ae349f5Scvs2svn IpcpAddOutOctets(int n) 1471ae349f5Scvs2svn { 14829e275ceSBrian Somers throughput_addout(&IpcpInfo.throughput, n); 1491ae349f5Scvs2svn } 1501ae349f5Scvs2svn 1511ae349f5Scvs2svn int 1521ae349f5Scvs2svn ReportIpcpStatus(struct cmdargs const *arg) 1531ae349f5Scvs2svn { 1541ae349f5Scvs2svn if (!VarTerm) 1551ae349f5Scvs2svn return 1; 1567308ec68SBrian Somers fprintf(VarTerm, "%s [%s]\n", IpcpInfo.fsm.name, 1577308ec68SBrian Somers StateNames[IpcpInfo.fsm.state]); 1587308ec68SBrian Somers if (IpcpInfo.fsm.state == ST_OPENED) { 15942e91bc7SBrian Somers fprintf(VarTerm, " His side: %s, %s\n", 1601ae349f5Scvs2svn inet_ntoa(IpcpInfo.his_ipaddr), vj2asc(IpcpInfo.his_compproto)); 16142e91bc7SBrian Somers fprintf(VarTerm, " My side: %s, %s\n", 1621ae349f5Scvs2svn inet_ntoa(IpcpInfo.want_ipaddr), vj2asc(IpcpInfo.want_compproto)); 1631ae349f5Scvs2svn } 1641ae349f5Scvs2svn 16542e91bc7SBrian Somers fprintf(VarTerm, "\nDefaults:\n"); 1661ae349f5Scvs2svn fprintf(VarTerm, " My Address: %s/%d\n", 16729e275ceSBrian Somers inet_ntoa(IpcpInfo.DefMyAddress.ipaddr), IpcpInfo.DefMyAddress.width); 16829e275ceSBrian Somers if (iplist_isvalid(&IpcpInfo.DefHisChoice)) 16942e91bc7SBrian Somers fprintf(VarTerm, " His Address: %s\n", 17042e91bc7SBrian Somers IpcpInfo.DefHisChoice.src); 1711ae349f5Scvs2svn else 1721ae349f5Scvs2svn fprintf(VarTerm, " His Address: %s/%d\n", 17329e275ceSBrian Somers inet_ntoa(IpcpInfo.DefHisAddress.ipaddr), 17429e275ceSBrian Somers IpcpInfo.DefHisAddress.width); 17529e275ceSBrian Somers if (IpcpInfo.HaveTriggerAddress) 17629e275ceSBrian Somers fprintf(VarTerm, " Negotiation(trigger): %s\n", 17729e275ceSBrian Somers inet_ntoa(IpcpInfo.TriggerAddress)); 1781ae349f5Scvs2svn else 1791ae349f5Scvs2svn fprintf(VarTerm, " Negotiation(trigger): MYADDR\n"); 18042e91bc7SBrian Somers fprintf(VarTerm, " Initial VJ slots: %d\n", IpcpInfo.VJInitSlots); 18142e91bc7SBrian Somers fprintf(VarTerm, " Initial VJ compression: %s\n", 18242e91bc7SBrian Somers IpcpInfo.VJInitComp ? "on" : "off"); 1831ae349f5Scvs2svn 1841ae349f5Scvs2svn fprintf(VarTerm, "\n"); 18529e275ceSBrian Somers throughput_disp(&IpcpInfo.throughput, VarTerm); 1861ae349f5Scvs2svn 1871ae349f5Scvs2svn return 0; 1881ae349f5Scvs2svn } 1891ae349f5Scvs2svn 1901ae349f5Scvs2svn void 1911ae349f5Scvs2svn IpcpDefAddress() 1921ae349f5Scvs2svn { 1937308ec68SBrian Somers /* Setup default IP addresses (`hostname` -> 0.0.0.0) */ 1941ae349f5Scvs2svn struct hostent *hp; 1951ae349f5Scvs2svn char name[200]; 1961ae349f5Scvs2svn 19729e275ceSBrian Somers memset(&IpcpInfo.DefMyAddress, '\0', sizeof IpcpInfo.DefMyAddress); 19829e275ceSBrian Somers memset(&IpcpInfo.DefHisAddress, '\0', sizeof IpcpInfo.DefHisAddress); 19929e275ceSBrian Somers IpcpInfo.HaveTriggerAddress = 0; 2001ae349f5Scvs2svn if (gethostname(name, sizeof name) == 0) { 2011ae349f5Scvs2svn hp = gethostbyname(name); 20229e275ceSBrian Somers if (hp && hp->h_addrtype == AF_INET) 20329e275ceSBrian Somers memcpy(&IpcpInfo.DefMyAddress.ipaddr.s_addr, hp->h_addr, hp->h_length); 2041ae349f5Scvs2svn } 2051ae349f5Scvs2svn } 2061ae349f5Scvs2svn 2071ae349f5Scvs2svn int 2081ae349f5Scvs2svn SetInitVJ(struct cmdargs const *args) 2091ae349f5Scvs2svn { 2101ae349f5Scvs2svn if (args->argc != 2) 2111ae349f5Scvs2svn return -1; 2121ae349f5Scvs2svn if (!strcasecmp(args->argv[0], "slots")) { 2131ae349f5Scvs2svn int slots; 2141ae349f5Scvs2svn 2151ae349f5Scvs2svn slots = atoi(args->argv[1]); 2161ae349f5Scvs2svn if (slots < 4 || slots > 16) 2171ae349f5Scvs2svn return 1; 21829e275ceSBrian Somers IpcpInfo.VJInitSlots = slots; 2191ae349f5Scvs2svn return 0; 2201ae349f5Scvs2svn } else if (!strcasecmp(args->argv[0], "slotcomp")) { 2211ae349f5Scvs2svn if (!strcasecmp(args->argv[1], "on")) 22229e275ceSBrian Somers IpcpInfo.VJInitComp = 1; 2231ae349f5Scvs2svn else if (!strcasecmp(args->argv[1], "off")) 22429e275ceSBrian Somers IpcpInfo.VJInitComp = 0; 2251ae349f5Scvs2svn else 2261ae349f5Scvs2svn return 2; 2271ae349f5Scvs2svn return 0; 2281ae349f5Scvs2svn } 2291ae349f5Scvs2svn return -1; 2301ae349f5Scvs2svn } 2311ae349f5Scvs2svn 2321ae349f5Scvs2svn void 2337a6f8720SBrian Somers IpcpInit(struct bundle *bundle, struct link *l) 2341ae349f5Scvs2svn { 2357308ec68SBrian Somers /* Initialise ourselves */ 2367a6f8720SBrian Somers FsmInit(&IpcpInfo.fsm, bundle, l); 23729e275ceSBrian Somers if (iplist_isvalid(&IpcpInfo.DefHisChoice)) 23829e275ceSBrian Somers iplist_setrandpos(&IpcpInfo.DefHisChoice); 23929e275ceSBrian Somers IpcpInfo.his_compproto = 0; 24029e275ceSBrian Somers IpcpInfo.his_reject = IpcpInfo.my_reject = 0; 24129e275ceSBrian Somers 2421ae349f5Scvs2svn if ((mode & MODE_DEDICATED) && !GetLabel()) { 24329e275ceSBrian Somers IpcpInfo.want_ipaddr.s_addr = IpcpInfo.his_ipaddr.s_addr = INADDR_ANY; 24429e275ceSBrian Somers IpcpInfo.his_ipaddr.s_addr = INADDR_ANY; 2451ae349f5Scvs2svn } else { 24629e275ceSBrian Somers IpcpInfo.want_ipaddr.s_addr = IpcpInfo.DefMyAddress.ipaddr.s_addr; 24729e275ceSBrian Somers IpcpInfo.his_ipaddr.s_addr = IpcpInfo.DefHisAddress.ipaddr.s_addr; 2481ae349f5Scvs2svn } 2491ae349f5Scvs2svn 2501ae349f5Scvs2svn /* 2511ae349f5Scvs2svn * Some implementations of PPP require that we send a 2521ae349f5Scvs2svn * *special* value as our address, even though the rfc specifies 2531ae349f5Scvs2svn * full negotiation (e.g. "0.0.0.0" or Not "0.0.0.0"). 2541ae349f5Scvs2svn */ 25529e275ceSBrian Somers if (IpcpInfo.HaveTriggerAddress) { 25629e275ceSBrian Somers IpcpInfo.want_ipaddr.s_addr = IpcpInfo.TriggerAddress.s_addr; 25729e275ceSBrian Somers LogPrintf(LogIPCP, "Using trigger address %s\n", 25829e275ceSBrian Somers inet_ntoa(IpcpInfo.TriggerAddress)); 2591ae349f5Scvs2svn } 260455aabc3SBrian Somers IpcpInfo.if_mine.s_addr = IpcpInfo.if_peer.s_addr = INADDR_ANY; 26129e275ceSBrian Somers 2621ae349f5Scvs2svn if (Enabled(ConfVjcomp)) 26329e275ceSBrian Somers IpcpInfo.want_compproto = (PROTO_VJCOMP << 16) + 26429e275ceSBrian Somers ((IpcpInfo.VJInitSlots - 1) << 8) + 26529e275ceSBrian Somers IpcpInfo.VJInitComp; 2661ae349f5Scvs2svn else 2671ae349f5Scvs2svn IpcpInfo.want_compproto = 0; 2686140ba11SBrian Somers VjInit(IpcpInfo.VJInitSlots - 1); 26929e275ceSBrian Somers 2701ae349f5Scvs2svn IpcpInfo.heis1172 = 0; 2717308ec68SBrian Somers IpcpInfo.fsm.maxconfig = 10; 27229e275ceSBrian Somers throughput_init(&IpcpInfo.throughput); 2731ae349f5Scvs2svn } 2741ae349f5Scvs2svn 275455aabc3SBrian Somers static int 276455aabc3SBrian Somers ipcp_SetIPaddress(struct bundle *bundle, struct ipcpstate *ipcp, 277455aabc3SBrian Somers struct in_addr myaddr, struct in_addr hisaddr, 278455aabc3SBrian Somers struct in_addr netmask, int silent) 279455aabc3SBrian Somers { 280455aabc3SBrian Somers struct sockaddr_in *sock_in; 281455aabc3SBrian Somers int s; 282455aabc3SBrian Somers u_long mask, addr; 283455aabc3SBrian Somers struct ifaliasreq ifra; 284455aabc3SBrian Somers 285455aabc3SBrian Somers /* If given addresses are alreay set, then ignore this request */ 286455aabc3SBrian Somers if (ipcp->if_mine.s_addr == myaddr.s_addr && 287455aabc3SBrian Somers ipcp->if_peer.s_addr == hisaddr.s_addr) 288455aabc3SBrian Somers return 0; 289455aabc3SBrian Somers 290455aabc3SBrian Somers s = ID0socket(AF_INET, SOCK_DGRAM, 0); 291455aabc3SBrian Somers if (s < 0) { 292455aabc3SBrian Somers LogPrintf(LogERROR, "SetIpDevice: socket(): %s\n", strerror(errno)); 293455aabc3SBrian Somers return (-1); 294455aabc3SBrian Somers } 295455aabc3SBrian Somers 296455aabc3SBrian Somers memset(&ifra, '\0', sizeof ifra); 297455aabc3SBrian Somers strncpy(ifra.ifra_name, bundle->ifname, sizeof ifra.ifra_name - 1); 298455aabc3SBrian Somers ifra.ifra_name[sizeof ifra.ifra_name - 1] = '\0'; 299455aabc3SBrian Somers 300455aabc3SBrian Somers /* If different address has been set, then delete it first */ 301455aabc3SBrian Somers if (ipcp->if_mine.s_addr != INADDR_ANY || 302455aabc3SBrian Somers ipcp->if_peer.s_addr != INADDR_ANY) 303455aabc3SBrian Somers if (ID0ioctl(s, SIOCDIFADDR, &ifra) < 0) { 304455aabc3SBrian Somers LogPrintf(LogERROR, "SetIpDevice: ioctl(SIOCDIFADDR): %s\n", 305455aabc3SBrian Somers strerror(errno)); 306455aabc3SBrian Somers close(s); 307455aabc3SBrian Somers return (-1); 308455aabc3SBrian Somers } 309455aabc3SBrian Somers 310455aabc3SBrian Somers /* Set interface address */ 311455aabc3SBrian Somers sock_in = (struct sockaddr_in *)&ifra.ifra_addr; 312455aabc3SBrian Somers sock_in->sin_family = AF_INET; 313455aabc3SBrian Somers sock_in->sin_addr = myaddr; 314455aabc3SBrian Somers sock_in->sin_len = sizeof *sock_in; 315455aabc3SBrian Somers 316455aabc3SBrian Somers /* Set destination address */ 317455aabc3SBrian Somers sock_in = (struct sockaddr_in *)&ifra.ifra_broadaddr; 318455aabc3SBrian Somers sock_in->sin_family = AF_INET; 319455aabc3SBrian Somers sock_in->sin_addr = hisaddr; 320455aabc3SBrian Somers sock_in->sin_len = sizeof *sock_in; 321455aabc3SBrian Somers 322455aabc3SBrian Somers addr = ntohl(myaddr.s_addr); 323455aabc3SBrian Somers if (IN_CLASSA(addr)) 324455aabc3SBrian Somers mask = IN_CLASSA_NET; 325455aabc3SBrian Somers else if (IN_CLASSB(addr)) 326455aabc3SBrian Somers mask = IN_CLASSB_NET; 327455aabc3SBrian Somers else 328455aabc3SBrian Somers mask = IN_CLASSC_NET; 329455aabc3SBrian Somers 330455aabc3SBrian Somers /* if subnet mask is given, use it instead of class mask */ 331455aabc3SBrian Somers if (netmask.s_addr != INADDR_ANY && (ntohl(netmask.s_addr) & mask) == mask) 332455aabc3SBrian Somers mask = ntohl(netmask.s_addr); 333455aabc3SBrian Somers 334455aabc3SBrian Somers sock_in = (struct sockaddr_in *)&ifra.ifra_mask; 335455aabc3SBrian Somers sock_in->sin_family = AF_INET; 336455aabc3SBrian Somers sock_in->sin_addr.s_addr = htonl(mask); 337455aabc3SBrian Somers sock_in->sin_len = sizeof *sock_in; 338455aabc3SBrian Somers 339455aabc3SBrian Somers if (ID0ioctl(s, SIOCAIFADDR, &ifra) < 0) { 340455aabc3SBrian Somers if (!silent) 341455aabc3SBrian Somers LogPrintf(LogERROR, "SetIpDevice: ioctl(SIOCAIFADDR): %s\n", 342455aabc3SBrian Somers strerror(errno)); 343455aabc3SBrian Somers close(s); 344455aabc3SBrian Somers return (-1); 345455aabc3SBrian Somers } 346455aabc3SBrian Somers 347455aabc3SBrian Somers ipcp->if_peer.s_addr = hisaddr.s_addr; 348455aabc3SBrian Somers ipcp->if_mine.s_addr = myaddr.s_addr; 349455aabc3SBrian Somers 350455aabc3SBrian Somers if (Enabled(ConfProxy)) 351455aabc3SBrian Somers sifproxyarp(bundle, ipcp, s); 352455aabc3SBrian Somers 353455aabc3SBrian Somers close(s); 354455aabc3SBrian Somers return (0); 355455aabc3SBrian Somers } 356455aabc3SBrian Somers 357455aabc3SBrian Somers static struct in_addr 358455aabc3SBrian Somers ChooseHisAddr(struct bundle *bundle, struct ipcpstate *ipcp, 359455aabc3SBrian Somers const struct in_addr gw) 360455aabc3SBrian Somers { 361455aabc3SBrian Somers struct in_addr try; 362455aabc3SBrian Somers int f; 363455aabc3SBrian Somers 364455aabc3SBrian Somers for (f = 0; f < IpcpInfo.DefHisChoice.nItems; f++) { 365455aabc3SBrian Somers try = iplist_next(&IpcpInfo.DefHisChoice); 366455aabc3SBrian Somers LogPrintf(LogDEBUG, "ChooseHisAddr: Check item %d (%s)\n", 367455aabc3SBrian Somers f, inet_ntoa(try)); 368455aabc3SBrian Somers if (ipcp_SetIPaddress(bundle, ipcp, gw, try, ifnetmask, 1) == 0) { 369455aabc3SBrian Somers LogPrintf(LogIPCP, "ChooseHisAddr: Selected IP address %s\n", 370455aabc3SBrian Somers inet_ntoa(try)); 371455aabc3SBrian Somers break; 372455aabc3SBrian Somers } 373455aabc3SBrian Somers } 374455aabc3SBrian Somers 375455aabc3SBrian Somers if (f == IpcpInfo.DefHisChoice.nItems) { 376455aabc3SBrian Somers LogPrintf(LogDEBUG, "ChooseHisAddr: All addresses in use !\n"); 377455aabc3SBrian Somers try.s_addr = INADDR_ANY; 378455aabc3SBrian Somers } 379455aabc3SBrian Somers 380455aabc3SBrian Somers return try; 381455aabc3SBrian Somers } 382455aabc3SBrian Somers 3831ae349f5Scvs2svn static void 3841ae349f5Scvs2svn IpcpInitRestartCounter(struct fsm * fp) 3851ae349f5Scvs2svn { 3867308ec68SBrian Somers /* Set fsm timer load */ 3871ae349f5Scvs2svn fp->FsmTimer.load = VarRetryTimeout * SECTICKS; 3881ae349f5Scvs2svn fp->restart = 5; 3891ae349f5Scvs2svn } 3901ae349f5Scvs2svn 3911ae349f5Scvs2svn static void 3921ae349f5Scvs2svn IpcpSendConfigReq(struct fsm *fp) 3931ae349f5Scvs2svn { 3947308ec68SBrian Somers /* Send config REQ please */ 3958c07a7b2SBrian Somers struct physical *p = link2physical(fp->link); 39683d1af55SBrian Somers struct ipcpstate *ipcp = fsm2ipcp(fp); 3971ae349f5Scvs2svn u_char *cp; 3981ae349f5Scvs2svn struct lcp_opt o; 3991ae349f5Scvs2svn 4001ae349f5Scvs2svn cp = ReqBuff; 4011ae349f5Scvs2svn LogPrintf(LogIPCP, "IpcpSendConfigReq\n"); 40283d1af55SBrian Somers if ((p && !Physical_IsSync(p)) || !REJECTED(ipcp, TY_IPADDR)) { 4031ae349f5Scvs2svn o.id = TY_IPADDR; 4041ae349f5Scvs2svn o.len = 6; 40583d1af55SBrian Somers *(u_long *)o.data = ipcp->want_ipaddr.s_addr; 4061ae349f5Scvs2svn cp += LcpPutConf(LogIPCP, cp, &o, cftypes[o.id], 40783d1af55SBrian Somers inet_ntoa(ipcp->want_ipaddr)); 4081ae349f5Scvs2svn } 4091ae349f5Scvs2svn 41083d1af55SBrian Somers if (ipcp->want_compproto && !REJECTED(ipcp, TY_COMPPROTO)) { 4111ae349f5Scvs2svn const char *args; 4121ae349f5Scvs2svn o.id = TY_COMPPROTO; 41383d1af55SBrian Somers if (ipcp->heis1172) { 4141ae349f5Scvs2svn o.len = 4; 4151ae349f5Scvs2svn *(u_short *)o.data = htons(PROTO_VJCOMP); 4161ae349f5Scvs2svn args = ""; 4171ae349f5Scvs2svn } else { 4181ae349f5Scvs2svn o.len = 6; 41983d1af55SBrian Somers *(u_long *)o.data = htonl(ipcp->want_compproto); 42083d1af55SBrian Somers args = vj2asc(ipcp->want_compproto); 4211ae349f5Scvs2svn } 4221ae349f5Scvs2svn cp += LcpPutConf(LogIPCP, cp, &o, cftypes[o.id], args); 4231ae349f5Scvs2svn } 4241ae349f5Scvs2svn FsmOutput(fp, CODE_CONFIGREQ, fp->reqid++, ReqBuff, cp - ReqBuff); 4251ae349f5Scvs2svn } 4261ae349f5Scvs2svn 4271ae349f5Scvs2svn static void 4281ae349f5Scvs2svn IpcpSendTerminateReq(struct fsm * fp) 4291ae349f5Scvs2svn { 4307308ec68SBrian Somers /* Term REQ just sent by FSM */ 4311ae349f5Scvs2svn } 4321ae349f5Scvs2svn 4331ae349f5Scvs2svn static void 4341ae349f5Scvs2svn IpcpSendTerminateAck(struct fsm * fp) 4351ae349f5Scvs2svn { 4367308ec68SBrian Somers /* Send Term ACK please */ 4371ae349f5Scvs2svn LogPrintf(LogIPCP, "IpcpSendTerminateAck\n"); 4381ae349f5Scvs2svn FsmOutput(fp, CODE_TERMACK, fp->reqid++, NULL, 0); 4391ae349f5Scvs2svn } 4401ae349f5Scvs2svn 4411ae349f5Scvs2svn static void 4421ae349f5Scvs2svn IpcpLayerStart(struct fsm * fp) 4431ae349f5Scvs2svn { 4447308ec68SBrian Somers /* We're about to start up ! */ 4451ae349f5Scvs2svn LogPrintf(LogIPCP, "IpcpLayerStart.\n"); 446455aabc3SBrian Somers 447455aabc3SBrian Somers /* This is where we should be setting up the interface in AUTO mode */ 4481ae349f5Scvs2svn } 4491ae349f5Scvs2svn 4501ae349f5Scvs2svn static void 4511ae349f5Scvs2svn IpcpLayerFinish(struct fsm *fp) 4521ae349f5Scvs2svn { 4537308ec68SBrian Somers /* We're now down */ 4541ae349f5Scvs2svn LogPrintf(LogIPCP, "IpcpLayerFinish.\n"); 4551ae349f5Scvs2svn } 4561ae349f5Scvs2svn 4571ae349f5Scvs2svn static void 4581ae349f5Scvs2svn IpcpLayerDown(struct fsm *fp) 4591ae349f5Scvs2svn { 4607308ec68SBrian Somers /* About to come down */ 46183d1af55SBrian Somers struct ipcpstate *ipcp = fsm2ipcp(fp); 462455aabc3SBrian Somers const char *s; 463455aabc3SBrian Somers 464455aabc3SBrian Somers s = inet_ntoa(ipcp->if_peer); 465455aabc3SBrian Somers LogPrintf(LogIsKept(LogLINK) ? LogLINK : LogIPCP, "IpcpLayerDown: %s\n", s); 466455aabc3SBrian Somers 46783d1af55SBrian Somers throughput_stop(&ipcp->throughput); 46883d1af55SBrian Somers throughput_log(&ipcp->throughput, LogIPCP, NULL); 469455aabc3SBrian Somers 470455aabc3SBrian Somers /* 471455aabc3SBrian Somers * XXX this stuff should really live in the FSM. Our config should 472455aabc3SBrian Somers * associate executable sections in files with events. 473455aabc3SBrian Somers */ 474455aabc3SBrian Somers if (SelectSystem(fp->bundle, s, LINKDOWNFILE) < 0) 475455aabc3SBrian Somers if (GetLabel()) { 476455aabc3SBrian Somers if (SelectSystem(fp->bundle, GetLabel(), LINKDOWNFILE) < 0) 477455aabc3SBrian Somers SelectSystem(fp->bundle, "MYADDR", LINKDOWNFILE); 478455aabc3SBrian Somers } else 479455aabc3SBrian Somers SelectSystem(fp->bundle, "MYADDR", LINKDOWNFILE); 480455aabc3SBrian Somers 481455aabc3SBrian Somers if (!(mode & MODE_AUTO)) { 482455aabc3SBrian Somers struct ifaliasreq ifra; 483455aabc3SBrian Somers int s; 484455aabc3SBrian Somers 485455aabc3SBrian Somers s = ID0socket(AF_INET, SOCK_DGRAM, 0); 486455aabc3SBrian Somers if (s < 0) { 487455aabc3SBrian Somers LogPrintf(LogERROR, "IpcpLayerDown: socket: %s\n", strerror(errno)); 488455aabc3SBrian Somers return; 489455aabc3SBrian Somers } 490455aabc3SBrian Somers 491455aabc3SBrian Somers if (Enabled(ConfProxy)) 492455aabc3SBrian Somers cifproxyarp(fp->bundle, ipcp, s); 493455aabc3SBrian Somers 494455aabc3SBrian Somers if (ipcp->if_mine.s_addr != INADDR_ANY || 495455aabc3SBrian Somers ipcp->if_peer.s_addr != INADDR_ANY) { 496455aabc3SBrian Somers memset(&ifra, '\0', sizeof ifra); 497455aabc3SBrian Somers strncpy(ifra.ifra_name, fp->bundle->ifname, sizeof ifra.ifra_name - 1); 498455aabc3SBrian Somers ifra.ifra_name[sizeof ifra.ifra_name - 1] = '\0'; 499455aabc3SBrian Somers /* XXX don't delete things belonging to other NCPs */ 500455aabc3SBrian Somers if (ID0ioctl(s, SIOCDIFADDR, &ifra) < 0) { 501455aabc3SBrian Somers LogPrintf(LogERROR, "IpcpLayerDown: ioctl(SIOCDIFADDR): %s\n", 502455aabc3SBrian Somers strerror(errno)); 503455aabc3SBrian Somers close(s); 504455aabc3SBrian Somers return; 505455aabc3SBrian Somers } 506455aabc3SBrian Somers ipcp->if_mine.s_addr = ipcp->if_peer.s_addr = INADDR_ANY; 507455aabc3SBrian Somers } 508455aabc3SBrian Somers 509455aabc3SBrian Somers close(s); 510455aabc3SBrian Somers return; 511455aabc3SBrian Somers } 5121ae349f5Scvs2svn } 5131ae349f5Scvs2svn 5141ae349f5Scvs2svn static void 5151ae349f5Scvs2svn IpcpLayerUp(struct fsm *fp) 5161ae349f5Scvs2svn { 5177308ec68SBrian Somers /* We're now up */ 51883d1af55SBrian Somers struct ipcpstate *ipcp = fsm2ipcp(fp); 5191ae349f5Scvs2svn char tbuff[100]; 5201ae349f5Scvs2svn 5211ae349f5Scvs2svn LogPrintf(LogIPCP, "IpcpLayerUp(%d).\n", fp->state); 52283d1af55SBrian Somers snprintf(tbuff, sizeof tbuff, "myaddr = %s ", inet_ntoa(ipcp->want_ipaddr)); 523455aabc3SBrian Somers LogPrintf(LogIsKept(LogIPCP) ? LogIPCP : LogLINK, " %s hisaddr = %s\n", 524455aabc3SBrian Somers tbuff, inet_ntoa(ipcp->his_ipaddr)); 5251ae349f5Scvs2svn 52683d1af55SBrian Somers if (ipcp->his_compproto >> 16 == PROTO_VJCOMP) 52783d1af55SBrian Somers VjInit((ipcp->his_compproto >> 8) & 255); 5281ae349f5Scvs2svn 529455aabc3SBrian Somers if (ipcp_SetIPaddress(fp->bundle, ipcp, ipcp->want_ipaddr, 530455aabc3SBrian Somers ipcp->his_ipaddr, ifnetmask, 0) < 0) { 5311ae349f5Scvs2svn if (VarTerm) 5321ae349f5Scvs2svn LogPrintf(LogERROR, "IpcpLayerUp: unable to set ip address\n"); 5331ae349f5Scvs2svn return; 5341ae349f5Scvs2svn } 535455aabc3SBrian Somers 5361ae349f5Scvs2svn #ifndef NOALIAS 5371ae349f5Scvs2svn if (mode & MODE_ALIAS) 53883d1af55SBrian Somers VarPacketAliasSetAddress(ipcp->want_ipaddr); 5391ae349f5Scvs2svn #endif 540455aabc3SBrian Somers 541455aabc3SBrian Somers LogPrintf(LogIsKept(LogLINK) ? LogLINK : LogIPCP, "IpcpLayerUp: %s\n", 542455aabc3SBrian Somers inet_ntoa(ipcp->if_peer)); 543455aabc3SBrian Somers 544455aabc3SBrian Somers /* 545455aabc3SBrian Somers * XXX this stuff should really live in the FSM. Our config should 546455aabc3SBrian Somers * associate executable sections in files with events. 547455aabc3SBrian Somers */ 548455aabc3SBrian Somers if (SelectSystem(fp->bundle, inet_ntoa(ipcp->if_mine), LINKUPFILE) < 0) 549455aabc3SBrian Somers if (GetLabel()) { 550455aabc3SBrian Somers if (SelectSystem(fp->bundle, GetLabel(), LINKUPFILE) < 0) 551455aabc3SBrian Somers SelectSystem(fp->bundle, "MYADDR", LINKUPFILE); 552455aabc3SBrian Somers } else 553455aabc3SBrian Somers SelectSystem(fp->bundle, "MYADDR", LINKUPFILE); 554455aabc3SBrian Somers 55583d1af55SBrian Somers throughput_start(&ipcp->throughput); 5561ae349f5Scvs2svn StartIdleTimer(); 557455aabc3SBrian Somers Prompt(fp->bundle); 5581ae349f5Scvs2svn } 5591ae349f5Scvs2svn 5601ae349f5Scvs2svn void 5611ae349f5Scvs2svn IpcpUp() 5621ae349f5Scvs2svn { 5637308ec68SBrian Somers /* Lower layers are ready.... go */ 5647308ec68SBrian Somers FsmUp(&IpcpInfo.fsm); 5651ae349f5Scvs2svn LogPrintf(LogIPCP, "IPCP Up event!!\n"); 5661ae349f5Scvs2svn } 5671ae349f5Scvs2svn 5681ae349f5Scvs2svn void 5691ae349f5Scvs2svn IpcpOpen() 5701ae349f5Scvs2svn { 5717308ec68SBrian Somers /* Start IPCP please */ 5727308ec68SBrian Somers FsmOpen(&IpcpInfo.fsm); 5731ae349f5Scvs2svn } 5741ae349f5Scvs2svn 5751ae349f5Scvs2svn static int 5761ae349f5Scvs2svn AcceptableAddr(struct in_range *prange, struct in_addr ipaddr) 5771ae349f5Scvs2svn { 5787308ec68SBrian Somers /* Is the given IP in the given range ? */ 5791ae349f5Scvs2svn LogPrintf(LogDEBUG, "requested = %x\n", htonl(ipaddr.s_addr)); 5801ae349f5Scvs2svn LogPrintf(LogDEBUG, "range = %x\n", htonl(prange->ipaddr.s_addr)); 5811ae349f5Scvs2svn LogPrintf(LogDEBUG, "/%x\n", htonl(prange->mask.s_addr)); 5821ae349f5Scvs2svn LogPrintf(LogDEBUG, "%x, %x\n", htonl(prange->ipaddr.s_addr & prange-> 5831ae349f5Scvs2svn mask.s_addr), htonl(ipaddr.s_addr & prange->mask.s_addr)); 5841ae349f5Scvs2svn return (prange->ipaddr.s_addr & prange->mask.s_addr) == 5851ae349f5Scvs2svn (ipaddr.s_addr & prange->mask.s_addr) && ipaddr.s_addr; 5861ae349f5Scvs2svn } 5871ae349f5Scvs2svn 5881ae349f5Scvs2svn static void 58983d1af55SBrian Somers IpcpDecodeConfig(struct fsm *fp, u_char * cp, int plen, int mode_type) 5901ae349f5Scvs2svn { 5917308ec68SBrian Somers /* Deal with incoming PROTO_IPCP */ 59283d1af55SBrian Somers struct ipcpstate *ipcp = fsm2ipcp(fp); 5931ae349f5Scvs2svn int type, length; 5941ae349f5Scvs2svn u_long *lp, compproto; 5951ae349f5Scvs2svn struct compreq *pcomp; 5961ae349f5Scvs2svn struct in_addr ipaddr, dstipaddr, dnsstuff, ms_info_req; 5971ae349f5Scvs2svn char tbuff[100]; 5981ae349f5Scvs2svn char tbuff2[100]; 5991ae349f5Scvs2svn 6001ae349f5Scvs2svn ackp = AckBuff; 6011ae349f5Scvs2svn nakp = NakBuff; 6021ae349f5Scvs2svn rejp = RejBuff; 6031ae349f5Scvs2svn 6041ae349f5Scvs2svn while (plen >= sizeof(struct fsmconfig)) { 6051ae349f5Scvs2svn type = *cp; 6061ae349f5Scvs2svn length = cp[1]; 6071ae349f5Scvs2svn if (type < NCFTYPES) 6081ae349f5Scvs2svn snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes[type], length); 6091ae349f5Scvs2svn else if (type > 128 && type < 128 + NCFTYPES128) 6101ae349f5Scvs2svn snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes128[type-128], length); 6111ae349f5Scvs2svn else 6121ae349f5Scvs2svn snprintf(tbuff, sizeof tbuff, " <%d>[%d] ", type, length); 6131ae349f5Scvs2svn 6141ae349f5Scvs2svn switch (type) { 6151ae349f5Scvs2svn case TY_IPADDR: /* RFC1332 */ 6161ae349f5Scvs2svn lp = (u_long *) (cp + 2); 6171ae349f5Scvs2svn ipaddr.s_addr = *lp; 6181ae349f5Scvs2svn LogPrintf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 6191ae349f5Scvs2svn 6201ae349f5Scvs2svn switch (mode_type) { 6211ae349f5Scvs2svn case MODE_REQ: 62283d1af55SBrian Somers if (iplist_isvalid(&ipcp->DefHisChoice)) { 6231ae349f5Scvs2svn if (ipaddr.s_addr == INADDR_ANY || 62483d1af55SBrian Somers iplist_ip2pos(&ipcp->DefHisChoice, ipaddr) < 0 || 625455aabc3SBrian Somers ipcp_SetIPaddress(fp->bundle, ipcp, ipcp->DefMyAddress.ipaddr, 626455aabc3SBrian Somers ipaddr, ifnetmask, 1)) { 6271ae349f5Scvs2svn LogPrintf(LogIPCP, "%s: Address invalid or already in use\n", 6281ae349f5Scvs2svn inet_ntoa(ipaddr)); 62983d1af55SBrian Somers ipcp->his_ipaddr = ChooseHisAddr 630455aabc3SBrian Somers (fp->bundle, ipcp, ipcp->DefMyAddress.ipaddr); 63183d1af55SBrian Somers if (ipcp->his_ipaddr.s_addr == INADDR_ANY) { 6321ae349f5Scvs2svn memcpy(rejp, cp, length); 6331ae349f5Scvs2svn rejp += length; 6341ae349f5Scvs2svn } else { 6351ae349f5Scvs2svn memcpy(nakp, cp, 2); 63683d1af55SBrian Somers memcpy(nakp+2, &ipcp->his_ipaddr.s_addr, length - 2); 6371ae349f5Scvs2svn nakp += length; 6381ae349f5Scvs2svn } 6391ae349f5Scvs2svn break; 6401ae349f5Scvs2svn } 64183d1af55SBrian Somers } else if (!AcceptableAddr(&ipcp->DefHisAddress, ipaddr)) { 6421ae349f5Scvs2svn /* 6431ae349f5Scvs2svn * If destination address is not acceptable, insist to use what we 6441ae349f5Scvs2svn * want to use. 6451ae349f5Scvs2svn */ 6461ae349f5Scvs2svn memcpy(nakp, cp, 2); 64783d1af55SBrian Somers memcpy(nakp+2, &ipcp->his_ipaddr.s_addr, length - 2); 6481ae349f5Scvs2svn nakp += length; 6491ae349f5Scvs2svn break; 6501ae349f5Scvs2svn } 65183d1af55SBrian Somers ipcp->his_ipaddr = ipaddr; 6521ae349f5Scvs2svn memcpy(ackp, cp, length); 6531ae349f5Scvs2svn ackp += length; 6541ae349f5Scvs2svn break; 6551ae349f5Scvs2svn case MODE_NAK: 65683d1af55SBrian Somers if (AcceptableAddr(&ipcp->DefMyAddress, ipaddr)) { 6571ae349f5Scvs2svn /* Use address suggested by peer */ 6581ae349f5Scvs2svn snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s ", tbuff, 65983d1af55SBrian Somers inet_ntoa(ipcp->want_ipaddr)); 6601ae349f5Scvs2svn LogPrintf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 66183d1af55SBrian Somers ipcp->want_ipaddr = ipaddr; 6621ae349f5Scvs2svn } else { 6631ae349f5Scvs2svn LogPrintf(LogIPCP, "%s: Unacceptable address!\n", inet_ntoa(ipaddr)); 66483d1af55SBrian Somers FsmClose(&ipcp->fsm); 6651ae349f5Scvs2svn } 6661ae349f5Scvs2svn break; 6671ae349f5Scvs2svn case MODE_REJ: 66883d1af55SBrian Somers ipcp->his_reject |= (1 << type); 6691ae349f5Scvs2svn break; 6701ae349f5Scvs2svn } 6711ae349f5Scvs2svn break; 6721ae349f5Scvs2svn case TY_COMPPROTO: 6731ae349f5Scvs2svn lp = (u_long *) (cp + 2); 6741ae349f5Scvs2svn compproto = htonl(*lp); 6751ae349f5Scvs2svn LogPrintf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto)); 6761ae349f5Scvs2svn 6771ae349f5Scvs2svn switch (mode_type) { 6781ae349f5Scvs2svn case MODE_REQ: 6791ae349f5Scvs2svn if (!Acceptable(ConfVjcomp)) { 6801ae349f5Scvs2svn memcpy(rejp, cp, length); 6811ae349f5Scvs2svn rejp += length; 6821ae349f5Scvs2svn } else { 6831ae349f5Scvs2svn pcomp = (struct compreq *) (cp + 2); 6841ae349f5Scvs2svn switch (length) { 6851ae349f5Scvs2svn case 4: /* RFC1172 */ 6861ae349f5Scvs2svn if (ntohs(pcomp->proto) == PROTO_VJCOMP) { 6871ae349f5Scvs2svn LogPrintf(LogWARN, "Peer is speaking RFC1172 compression protocol !\n"); 68883d1af55SBrian Somers ipcp->heis1172 = 1; 68983d1af55SBrian Somers ipcp->his_compproto = compproto; 6901ae349f5Scvs2svn memcpy(ackp, cp, length); 6911ae349f5Scvs2svn ackp += length; 6921ae349f5Scvs2svn } else { 6931ae349f5Scvs2svn memcpy(nakp, cp, 2); 6941ae349f5Scvs2svn pcomp->proto = htons(PROTO_VJCOMP); 6951ae349f5Scvs2svn memcpy(nakp+2, &pcomp, 2); 6961ae349f5Scvs2svn nakp += length; 6971ae349f5Scvs2svn } 6981ae349f5Scvs2svn break; 6991ae349f5Scvs2svn case 6: /* RFC1332 */ 7001ae349f5Scvs2svn if (ntohs(pcomp->proto) == PROTO_VJCOMP 70129e275ceSBrian Somers && pcomp->slots < MAX_VJ_STATES && pcomp->slots > 2) { 70283d1af55SBrian Somers ipcp->his_compproto = compproto; 70383d1af55SBrian Somers ipcp->heis1172 = 0; 7041ae349f5Scvs2svn memcpy(ackp, cp, length); 7051ae349f5Scvs2svn ackp += length; 7061ae349f5Scvs2svn } else { 7071ae349f5Scvs2svn memcpy(nakp, cp, 2); 7081ae349f5Scvs2svn pcomp->proto = htons(PROTO_VJCOMP); 70929e275ceSBrian Somers pcomp->slots = MAX_VJ_STATES - 1; 7101ae349f5Scvs2svn pcomp->compcid = 0; 7111ae349f5Scvs2svn memcpy(nakp+2, &pcomp, sizeof pcomp); 7121ae349f5Scvs2svn nakp += length; 7131ae349f5Scvs2svn } 7141ae349f5Scvs2svn break; 7151ae349f5Scvs2svn default: 7161ae349f5Scvs2svn memcpy(rejp, cp, length); 7171ae349f5Scvs2svn rejp += length; 7181ae349f5Scvs2svn break; 7191ae349f5Scvs2svn } 7201ae349f5Scvs2svn } 7211ae349f5Scvs2svn break; 7221ae349f5Scvs2svn case MODE_NAK: 7231ae349f5Scvs2svn LogPrintf(LogIPCP, "%s changing compproto: %08x --> %08x\n", 72483d1af55SBrian Somers tbuff, ipcp->want_compproto, compproto); 72583d1af55SBrian Somers ipcp->want_compproto = compproto; 7261ae349f5Scvs2svn break; 7271ae349f5Scvs2svn case MODE_REJ: 72883d1af55SBrian Somers ipcp->his_reject |= (1 << type); 7291ae349f5Scvs2svn break; 7301ae349f5Scvs2svn } 7311ae349f5Scvs2svn break; 7321ae349f5Scvs2svn case TY_IPADDRS: /* RFC1172 */ 7331ae349f5Scvs2svn lp = (u_long *) (cp + 2); 7341ae349f5Scvs2svn ipaddr.s_addr = *lp; 7351ae349f5Scvs2svn lp = (u_long *) (cp + 6); 7361ae349f5Scvs2svn dstipaddr.s_addr = *lp; 7371ae349f5Scvs2svn snprintf(tbuff2, sizeof tbuff2, "%s %s,", tbuff, inet_ntoa(ipaddr)); 7381ae349f5Scvs2svn LogPrintf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr)); 7391ae349f5Scvs2svn 7401ae349f5Scvs2svn switch (mode_type) { 7411ae349f5Scvs2svn case MODE_REQ: 74283d1af55SBrian Somers ipcp->his_ipaddr = ipaddr; 74383d1af55SBrian Somers ipcp->want_ipaddr = dstipaddr; 7441ae349f5Scvs2svn memcpy(ackp, cp, length); 7451ae349f5Scvs2svn ackp += length; 7461ae349f5Scvs2svn break; 7471ae349f5Scvs2svn case MODE_NAK: 7481ae349f5Scvs2svn snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s", tbuff, 74983d1af55SBrian Somers inet_ntoa(ipcp->want_ipaddr)); 7501ae349f5Scvs2svn LogPrintf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 75183d1af55SBrian Somers ipcp->want_ipaddr = ipaddr; 75283d1af55SBrian Somers ipcp->his_ipaddr = dstipaddr; 7531ae349f5Scvs2svn break; 7541ae349f5Scvs2svn case MODE_REJ: 75583d1af55SBrian Somers ipcp->his_reject |= (1 << type); 7561ae349f5Scvs2svn break; 7571ae349f5Scvs2svn } 7581ae349f5Scvs2svn break; 7591ae349f5Scvs2svn 7601ae349f5Scvs2svn /* 7611ae349f5Scvs2svn * MS extensions for MS's PPP 7621ae349f5Scvs2svn */ 7631ae349f5Scvs2svn 7641ae349f5Scvs2svn #ifndef NOMSEXT 7651ae349f5Scvs2svn case TY_PRIMARY_DNS: /* MS PPP DNS negotiation hack */ 7661ae349f5Scvs2svn case TY_SECONDARY_DNS: 7671ae349f5Scvs2svn if (!Enabled(ConfMSExt)) { 7681ae349f5Scvs2svn LogPrintf(LogIPCP, "MS NS req - rejected - msext disabled\n"); 76983d1af55SBrian Somers ipcp->my_reject |= (1 << type); 7701ae349f5Scvs2svn memcpy(rejp, cp, length); 7711ae349f5Scvs2svn rejp += length; 7721ae349f5Scvs2svn break; 7731ae349f5Scvs2svn } 7741ae349f5Scvs2svn switch (mode_type) { 7751ae349f5Scvs2svn case MODE_REQ: 7761ae349f5Scvs2svn lp = (u_long *) (cp + 2); 7771ae349f5Scvs2svn dnsstuff.s_addr = *lp; 77883d1af55SBrian Somers ms_info_req.s_addr = ipcp->ns_entries 77929e275ceSBrian Somers [(type - TY_PRIMARY_DNS) ? 1 : 0].s_addr; 7801ae349f5Scvs2svn if (dnsstuff.s_addr != ms_info_req.s_addr) { 7811ae349f5Scvs2svn 7821ae349f5Scvs2svn /* 7831ae349f5Scvs2svn * So the client has got the DNS stuff wrong (first request) so 7841ae349f5Scvs2svn * we'll tell 'em how it is 7851ae349f5Scvs2svn */ 7861ae349f5Scvs2svn memcpy(nakp, cp, 2); /* copy first two (type/length) */ 7871ae349f5Scvs2svn LogPrintf(LogIPCP, "MS NS req %d:%s->%s - nak\n", 7881ae349f5Scvs2svn type, 7891ae349f5Scvs2svn inet_ntoa(dnsstuff), 7901ae349f5Scvs2svn inet_ntoa(ms_info_req)); 7911ae349f5Scvs2svn memcpy(nakp+2, &ms_info_req, length); 7921ae349f5Scvs2svn nakp += length; 7931ae349f5Scvs2svn break; 7941ae349f5Scvs2svn } 7951ae349f5Scvs2svn 7961ae349f5Scvs2svn /* 7971ae349f5Scvs2svn * Otherwise they have it right (this time) so we send a ack packet 7981ae349f5Scvs2svn * back confirming it... end of story 7991ae349f5Scvs2svn */ 8001ae349f5Scvs2svn LogPrintf(LogIPCP, "MS NS req %d:%s ok - ack\n", 8011ae349f5Scvs2svn type, 8021ae349f5Scvs2svn inet_ntoa(ms_info_req)); 8031ae349f5Scvs2svn memcpy(ackp, cp, length); 8041ae349f5Scvs2svn ackp += length; 8051ae349f5Scvs2svn break; 8061ae349f5Scvs2svn case MODE_NAK: /* what does this mean?? */ 8071ae349f5Scvs2svn LogPrintf(LogIPCP, "MS NS req %d - NAK??\n", type); 8081ae349f5Scvs2svn break; 8091ae349f5Scvs2svn case MODE_REJ: /* confused?? me to :) */ 8101ae349f5Scvs2svn LogPrintf(LogIPCP, "MS NS req %d - REJ??\n", type); 8111ae349f5Scvs2svn break; 8121ae349f5Scvs2svn } 8131ae349f5Scvs2svn break; 8141ae349f5Scvs2svn 8151ae349f5Scvs2svn case TY_PRIMARY_NBNS: /* MS PPP NetBIOS nameserver hack */ 8161ae349f5Scvs2svn case TY_SECONDARY_NBNS: 8171ae349f5Scvs2svn if (!Enabled(ConfMSExt)) { 8181ae349f5Scvs2svn LogPrintf(LogIPCP, "MS NBNS req - rejected - msext disabled\n"); 81983d1af55SBrian Somers ipcp->my_reject |= (1 << type); 8201ae349f5Scvs2svn memcpy(rejp, cp, length); 8211ae349f5Scvs2svn rejp += length; 8221ae349f5Scvs2svn break; 8231ae349f5Scvs2svn } 8241ae349f5Scvs2svn switch (mode_type) { 8251ae349f5Scvs2svn case MODE_REQ: 8261ae349f5Scvs2svn lp = (u_long *) (cp + 2); 8271ae349f5Scvs2svn dnsstuff.s_addr = *lp; 82883d1af55SBrian Somers ms_info_req.s_addr = ipcp->nbns_entries 82929e275ceSBrian Somers [(type - TY_PRIMARY_NBNS) ? 1 : 0].s_addr; 8301ae349f5Scvs2svn if (dnsstuff.s_addr != ms_info_req.s_addr) { 8311ae349f5Scvs2svn memcpy(nakp, cp, 2); 8321ae349f5Scvs2svn memcpy(nakp+2, &ms_info_req.s_addr, length); 8331ae349f5Scvs2svn LogPrintf(LogIPCP, "MS NBNS req %d:%s->%s - nak\n", 8341ae349f5Scvs2svn type, 8351ae349f5Scvs2svn inet_ntoa(dnsstuff), 8361ae349f5Scvs2svn inet_ntoa(ms_info_req)); 8371ae349f5Scvs2svn nakp += length; 8381ae349f5Scvs2svn break; 8391ae349f5Scvs2svn } 8401ae349f5Scvs2svn LogPrintf(LogIPCP, "MS NBNS req %d:%s ok - ack\n", 8411ae349f5Scvs2svn type, 8421ae349f5Scvs2svn inet_ntoa(ms_info_req)); 8431ae349f5Scvs2svn memcpy(ackp, cp, length); 8441ae349f5Scvs2svn ackp += length; 8451ae349f5Scvs2svn break; 8461ae349f5Scvs2svn case MODE_NAK: 8471ae349f5Scvs2svn LogPrintf(LogIPCP, "MS NBNS req %d - NAK??\n", type); 8481ae349f5Scvs2svn break; 8491ae349f5Scvs2svn case MODE_REJ: 8501ae349f5Scvs2svn LogPrintf(LogIPCP, "MS NBNS req %d - REJ??\n", type); 8511ae349f5Scvs2svn break; 8521ae349f5Scvs2svn } 8531ae349f5Scvs2svn break; 8541ae349f5Scvs2svn 8551ae349f5Scvs2svn #endif 8561ae349f5Scvs2svn 8571ae349f5Scvs2svn default: 85883d1af55SBrian Somers ipcp->my_reject |= (1 << type); 8591ae349f5Scvs2svn memcpy(rejp, cp, length); 8601ae349f5Scvs2svn rejp += length; 8611ae349f5Scvs2svn break; 8621ae349f5Scvs2svn } 8631ae349f5Scvs2svn plen -= length; 8641ae349f5Scvs2svn cp += length; 8651ae349f5Scvs2svn } 8661ae349f5Scvs2svn } 8671ae349f5Scvs2svn 8681ae349f5Scvs2svn void 8691ae349f5Scvs2svn IpcpInput(struct mbuf * bp) 8701ae349f5Scvs2svn { 8717308ec68SBrian Somers /* Got PROTO_IPCP from link */ 8727308ec68SBrian Somers FsmInput(&IpcpInfo.fsm, bp); 8731ae349f5Scvs2svn } 8741ae349f5Scvs2svn 8751ae349f5Scvs2svn int 8767a6f8720SBrian Somers UseHisaddr(struct bundle *bundle, const char *hisaddr, int setaddr) 8771ae349f5Scvs2svn { 8787308ec68SBrian Somers /* Use `hisaddr' for the peers address (set iface if `setaddr') */ 87929e275ceSBrian Somers memset(&IpcpInfo.DefHisAddress, '\0', sizeof IpcpInfo.DefHisAddress); 88029e275ceSBrian Somers iplist_reset(&IpcpInfo.DefHisChoice); 8811ae349f5Scvs2svn if (strpbrk(hisaddr, ",-")) { 88229e275ceSBrian Somers iplist_setsrc(&IpcpInfo.DefHisChoice, hisaddr); 88329e275ceSBrian Somers if (iplist_isvalid(&IpcpInfo.DefHisChoice)) { 88429e275ceSBrian Somers iplist_setrandpos(&IpcpInfo.DefHisChoice); 885455aabc3SBrian Somers IpcpInfo.his_ipaddr = ChooseHisAddr 886455aabc3SBrian Somers (bundle, &IpcpInfo, IpcpInfo.want_ipaddr); 8871ae349f5Scvs2svn if (IpcpInfo.his_ipaddr.s_addr == INADDR_ANY) { 88829e275ceSBrian Somers LogPrintf(LogWARN, "%s: None available !\n", IpcpInfo.DefHisChoice.src); 8891ae349f5Scvs2svn return(0); 8901ae349f5Scvs2svn } 89129e275ceSBrian Somers IpcpInfo.DefHisAddress.ipaddr.s_addr = IpcpInfo.his_ipaddr.s_addr; 89229e275ceSBrian Somers IpcpInfo.DefHisAddress.mask.s_addr = INADDR_BROADCAST; 89329e275ceSBrian Somers IpcpInfo.DefHisAddress.width = 32; 8941ae349f5Scvs2svn } else { 8951ae349f5Scvs2svn LogPrintf(LogWARN, "%s: Invalid range !\n", hisaddr); 8961ae349f5Scvs2svn return 0; 8971ae349f5Scvs2svn } 89829e275ceSBrian Somers } else if (ParseAddr(1, &hisaddr, &IpcpInfo.DefHisAddress.ipaddr, 89929e275ceSBrian Somers &IpcpInfo.DefHisAddress.mask, 90029e275ceSBrian Somers &IpcpInfo.DefHisAddress.width) != 0) { 90129e275ceSBrian Somers IpcpInfo.his_ipaddr.s_addr = IpcpInfo.DefHisAddress.ipaddr.s_addr; 9021ae349f5Scvs2svn 903455aabc3SBrian Somers if (setaddr && ipcp_SetIPaddress(bundle, &IpcpInfo, 904455aabc3SBrian Somers IpcpInfo.DefMyAddress.ipaddr, 905455aabc3SBrian Somers IpcpInfo.DefHisAddress.ipaddr, ifnetmask, 906455aabc3SBrian Somers 0) < 0) { 90729e275ceSBrian Somers IpcpInfo.DefMyAddress.ipaddr.s_addr = INADDR_ANY; 90829e275ceSBrian Somers IpcpInfo.DefHisAddress.ipaddr.s_addr = INADDR_ANY; 9091ae349f5Scvs2svn return 0; 9101ae349f5Scvs2svn } 9111ae349f5Scvs2svn } else 9121ae349f5Scvs2svn return 0; 9131ae349f5Scvs2svn 9141ae349f5Scvs2svn return 1; 9151ae349f5Scvs2svn } 916