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 * 202f786681SBrian Somers * $Id: ipcp.c,v 1.50.2.25 1998/03/20 19:46:49 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 "slcompress.h" 54eaa4df37SBrian Somers #include "ipcp.h" 555ca5389aSBrian Somers #include "filter.h" 562f786681SBrian Somers #include "descriptor.h" 577a6f8720SBrian Somers #include "bundle.h" 581ae349f5Scvs2svn #include "loadalias.h" 591ae349f5Scvs2svn #include "vars.h" 601ae349f5Scvs2svn #include "vjcomp.h" 611ae349f5Scvs2svn #include "ip.h" 621ae349f5Scvs2svn #include "route.h" 63879ed6faSBrian Somers #include "lqr.h" 648c07a7b2SBrian Somers #include "hdlc.h" 656140ba11SBrian Somers #include "async.h" 668c07a7b2SBrian Somers #include "link.h" 6763b73463SBrian Somers #include "physical.h" 68455aabc3SBrian Somers #include "id.h" 69455aabc3SBrian Somers #include "arp.h" 70455aabc3SBrian Somers #include "systems.h" 7185b542cfSBrian Somers #include "prompt.h" 721ae349f5Scvs2svn 73503a7782SBrian Somers #undef REJECTED 74503a7782SBrian Somers #define REJECTED(p, x) ((p)->peer_reject & (1<<(x))) 75503a7782SBrian Somers 7629e275ceSBrian Somers struct compreq { 7729e275ceSBrian Somers u_short proto; 7829e275ceSBrian Somers u_char slots; 7929e275ceSBrian Somers u_char compcid; 8029e275ceSBrian Somers }; 811ae349f5Scvs2svn 821ae349f5Scvs2svn static void IpcpLayerUp(struct fsm *); 831ae349f5Scvs2svn static void IpcpLayerDown(struct fsm *); 847308ec68SBrian Somers static void IpcpLayerStart(struct fsm *); 857308ec68SBrian Somers static void IpcpLayerFinish(struct fsm *); 861ae349f5Scvs2svn static void IpcpInitRestartCounter(struct fsm *); 877308ec68SBrian Somers static void IpcpSendConfigReq(struct fsm *); 882267893fSBrian Somers static void IpcpSentTerminateReq(struct fsm *); 892267893fSBrian Somers static void IpcpSendTerminateAck(struct fsm *, u_char); 9030c2f2ffSBrian Somers static void IpcpDecodeConfig(struct fsm *, u_char *, int, int, 9130c2f2ffSBrian Somers struct fsm_decode *); 9283d1af55SBrian Somers 9383d1af55SBrian Somers static struct fsm_callbacks ipcp_Callbacks = { 9483d1af55SBrian Somers IpcpLayerUp, 9583d1af55SBrian Somers IpcpLayerDown, 9683d1af55SBrian Somers IpcpLayerStart, 976d666775SBrian Somers IpcpLayerFinish, 9883d1af55SBrian Somers IpcpInitRestartCounter, 9983d1af55SBrian Somers IpcpSendConfigReq, 1002267893fSBrian Somers IpcpSentTerminateReq, 10183d1af55SBrian Somers IpcpSendTerminateAck, 10283d1af55SBrian Somers IpcpDecodeConfig, 103503a7782SBrian Somers NullRecvResetReq, 104503a7782SBrian Somers NullRecvResetAck 10583d1af55SBrian Somers }; 1061ae349f5Scvs2svn 1071ae349f5Scvs2svn static const char *cftypes[] = { 1081ae349f5Scvs2svn /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */ 1091ae349f5Scvs2svn "???", 1101ae349f5Scvs2svn "IPADDRS", /* 1: IP-Addresses */ /* deprecated */ 1111ae349f5Scvs2svn "COMPPROTO", /* 2: IP-Compression-Protocol */ 1121ae349f5Scvs2svn "IPADDR", /* 3: IP-Address */ 1131ae349f5Scvs2svn }; 1141ae349f5Scvs2svn 1151ae349f5Scvs2svn #define NCFTYPES (sizeof cftypes/sizeof cftypes[0]) 1161ae349f5Scvs2svn 1171ae349f5Scvs2svn static const char *cftypes128[] = { 1181ae349f5Scvs2svn /* Check out the latest ``Assigned numbers'' rfc (rfc1700.txt) */ 1191ae349f5Scvs2svn "???", 1201ae349f5Scvs2svn "PRIDNS", /* 129: Primary DNS Server Address */ 1211ae349f5Scvs2svn "PRINBNS", /* 130: Primary NBNS Server Address */ 1221ae349f5Scvs2svn "SECDNS", /* 131: Secondary DNS Server Address */ 1231ae349f5Scvs2svn "SECNBNS", /* 132: Secondary NBNS Server Address */ 1241ae349f5Scvs2svn }; 1251ae349f5Scvs2svn 1261ae349f5Scvs2svn #define NCFTYPES128 (sizeof cftypes128/sizeof cftypes128[0]) 1271ae349f5Scvs2svn 1281ae349f5Scvs2svn void 1295828db6dSBrian Somers ipcp_AddInOctets(struct ipcp *ipcp, int n) 1301ae349f5Scvs2svn { 1315828db6dSBrian Somers throughput_addin(&ipcp->throughput, n); 1321ae349f5Scvs2svn } 1331ae349f5Scvs2svn 1341ae349f5Scvs2svn void 1355828db6dSBrian Somers ipcp_AddOutOctets(struct ipcp *ipcp, int n) 1361ae349f5Scvs2svn { 1375828db6dSBrian Somers throughput_addout(&ipcp->throughput, n); 1381ae349f5Scvs2svn } 1391ae349f5Scvs2svn 1401ae349f5Scvs2svn int 1411ae349f5Scvs2svn ReportIpcpStatus(struct cmdargs const *arg) 1421ae349f5Scvs2svn { 1435828db6dSBrian Somers prompt_Printf(&prompt, "%s [%s]\n", arg->bundle->ncp.ipcp.fsm.name, 1445828db6dSBrian Somers StateNames[arg->bundle->ncp.ipcp.fsm.state]); 1455828db6dSBrian Somers if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED) { 14685b542cfSBrian Somers prompt_Printf(&prompt, " His side: %s, %s\n", 1475828db6dSBrian Somers inet_ntoa(arg->bundle->ncp.ipcp.peer_ip), 1485828db6dSBrian Somers vj2asc(arg->bundle->ncp.ipcp.peer_compproto)); 14985b542cfSBrian Somers prompt_Printf(&prompt, " My side: %s, %s\n", 1505828db6dSBrian Somers inet_ntoa(arg->bundle->ncp.ipcp.my_ip), 1515828db6dSBrian Somers vj2asc(arg->bundle->ncp.ipcp.my_compproto)); 1521ae349f5Scvs2svn } 1531ae349f5Scvs2svn 15485b542cfSBrian Somers prompt_Printf(&prompt, "\nDefaults:\n"); 15585b542cfSBrian Somers prompt_Printf(&prompt, " My Address: %s/%d\n", 1565828db6dSBrian Somers inet_ntoa(arg->bundle->ncp.ipcp.cfg.my_range.ipaddr), 1575828db6dSBrian Somers arg->bundle->ncp.ipcp.cfg.my_range.width); 1585828db6dSBrian Somers if (iplist_isvalid(&arg->bundle->ncp.ipcp.cfg.peer_list)) 15985b542cfSBrian Somers prompt_Printf(&prompt, " His Address: %s\n", 1605828db6dSBrian Somers arg->bundle->ncp.ipcp.cfg.peer_list.src); 1611ae349f5Scvs2svn else 16285b542cfSBrian Somers prompt_Printf(&prompt, " His Address: %s/%d\n", 1635828db6dSBrian Somers inet_ntoa(arg->bundle->ncp.ipcp.cfg.peer_range.ipaddr), 1645828db6dSBrian Somers arg->bundle->ncp.ipcp.cfg.peer_range.width); 1655828db6dSBrian Somers if (arg->bundle->ncp.ipcp.cfg.HaveTriggerAddress) 16685b542cfSBrian Somers prompt_Printf(&prompt, " Negotiation(trigger): %s\n", 1675828db6dSBrian Somers inet_ntoa(arg->bundle->ncp.ipcp.cfg.TriggerAddress)); 1681ae349f5Scvs2svn else 16985b542cfSBrian Somers prompt_Printf(&prompt, " Negotiation(trigger): MYADDR\n"); 170503a7782SBrian Somers prompt_Printf(&prompt, " Initial VJ slots: %d\n", 1715828db6dSBrian Somers arg->bundle->ncp.ipcp.cfg.VJInitSlots); 17285b542cfSBrian Somers prompt_Printf(&prompt, " Initial VJ compression: %s\n", 1735828db6dSBrian Somers arg->bundle->ncp.ipcp.cfg.VJInitComp ? "on" : "off"); 1741ae349f5Scvs2svn 17585b542cfSBrian Somers prompt_Printf(&prompt, "\n"); 1765828db6dSBrian Somers throughput_disp(&arg->bundle->ncp.ipcp.throughput); 1771ae349f5Scvs2svn 1781ae349f5Scvs2svn return 0; 1791ae349f5Scvs2svn } 1801ae349f5Scvs2svn 1811ae349f5Scvs2svn int 1825828db6dSBrian Somers SetInitVJ(struct cmdargs const *arg) 1831ae349f5Scvs2svn { 1845828db6dSBrian Somers if (arg->argc != 2) 1851ae349f5Scvs2svn return -1; 1865828db6dSBrian Somers if (!strcasecmp(arg->argv[0], "slots")) { 1871ae349f5Scvs2svn int slots; 1881ae349f5Scvs2svn 1895828db6dSBrian Somers slots = atoi(arg->argv[1]); 1901ae349f5Scvs2svn if (slots < 4 || slots > 16) 1911ae349f5Scvs2svn return 1; 1925828db6dSBrian Somers arg->bundle->ncp.ipcp.cfg.VJInitSlots = slots; 1931ae349f5Scvs2svn return 0; 1945828db6dSBrian Somers } else if (!strcasecmp(arg->argv[0], "slotcomp")) { 1955828db6dSBrian Somers if (!strcasecmp(arg->argv[1], "on")) 1965828db6dSBrian Somers arg->bundle->ncp.ipcp.cfg.VJInitComp = 1; 1975828db6dSBrian Somers else if (!strcasecmp(arg->argv[1], "off")) 1985828db6dSBrian Somers arg->bundle->ncp.ipcp.cfg.VJInitComp = 0; 1991ae349f5Scvs2svn else 2001ae349f5Scvs2svn return 2; 2011ae349f5Scvs2svn return 0; 2021ae349f5Scvs2svn } 2031ae349f5Scvs2svn return -1; 2041ae349f5Scvs2svn } 2051ae349f5Scvs2svn 2061ae349f5Scvs2svn void 2076d666775SBrian Somers ipcp_Init(struct ipcp *ipcp, struct bundle *bundle, struct link *l, 2086d666775SBrian Somers const struct fsm_parent *parent) 2091ae349f5Scvs2svn { 210503a7782SBrian Somers struct hostent *hp; 211503a7782SBrian Somers char name[MAXHOSTNAMELEN]; 21229e275ceSBrian Somers 213503a7782SBrian Somers fsm_Init(&ipcp->fsm, "IPCP", PROTO_IPCP, IPCP_MAXCODE, 10, LogIPCP, 2146d666775SBrian Somers bundle, l, parent, &ipcp_Callbacks); 215503a7782SBrian Somers 216503a7782SBrian Somers ipcp->cfg.VJInitSlots = DEF_VJ_STATES; 217503a7782SBrian Somers ipcp->cfg.VJInitComp = 1; 218503a7782SBrian Somers memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range); 219503a7782SBrian Somers if (gethostname(name, sizeof name) == 0) { 220503a7782SBrian Somers hp = gethostbyname(name); 221503a7782SBrian Somers if (hp && hp->h_addrtype == AF_INET) { 222503a7782SBrian Somers memcpy(&ipcp->cfg.my_range.ipaddr.s_addr, hp->h_addr, hp->h_length); 223503a7782SBrian Somers ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 224503a7782SBrian Somers ipcp->cfg.peer_range.width = 32; 2251ae349f5Scvs2svn } 226503a7782SBrian Somers } 22730c2f2ffSBrian Somers ipcp->cfg.netmask.s_addr = INADDR_ANY; 228503a7782SBrian Somers memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 229503a7782SBrian Somers iplist_setsrc(&ipcp->cfg.peer_list, ""); 230503a7782SBrian Somers ipcp->cfg.HaveTriggerAddress = 0; 231503a7782SBrian Somers 232503a7782SBrian Somers ipcp->cfg.ns_entries[0].s_addr = INADDR_ANY; 233503a7782SBrian Somers ipcp->cfg.ns_entries[1].s_addr = INADDR_ANY; 234503a7782SBrian Somers ipcp->cfg.nbns_entries[0].s_addr = INADDR_ANY; 235503a7782SBrian Somers ipcp->cfg.nbns_entries[1].s_addr = INADDR_ANY; 236503a7782SBrian Somers 237eaa4df37SBrian Somers memset(&ipcp->vj, '\0', sizeof ipcp->vj); 238eaa4df37SBrian Somers 239503a7782SBrian Somers ipcp->my_ifip.s_addr = INADDR_ANY; 240503a7782SBrian Somers ipcp->peer_ifip.s_addr = INADDR_ANY; 241503a7782SBrian Somers 242503a7782SBrian Somers ipcp_Setup(ipcp); 243503a7782SBrian Somers } 244503a7782SBrian Somers 245503a7782SBrian Somers void 246503a7782SBrian Somers ipcp_Setup(struct ipcp *ipcp) 247503a7782SBrian Somers { 248503a7782SBrian Somers int pos; 249503a7782SBrian Somers 250503a7782SBrian Somers ipcp->fsm.open_mode = 0; 2515454ccd9SBrian Somers ipcp->fsm.maxconfig = 10; 252503a7782SBrian Somers 253503a7782SBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 254503a7782SBrian Somers if (ipcp->my_ifip.s_addr != INADDR_ANY && 255503a7782SBrian Somers (pos = iplist_ip2pos(&ipcp->cfg.peer_list, ipcp->my_ifip)) != -1) 256503a7782SBrian Somers ipcp->cfg.peer_range.ipaddr = iplist_setcurpos(&ipcp->cfg.peer_list, pos); 257503a7782SBrian Somers else 258503a7782SBrian Somers ipcp->cfg.peer_range.ipaddr = iplist_setrandpos(&ipcp->cfg.peer_list); 259503a7782SBrian Somers ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 260503a7782SBrian Somers ipcp->cfg.peer_range.width = 32; 261503a7782SBrian Somers } 262503a7782SBrian Somers 263503a7782SBrian Somers ipcp->heis1172 = 0; 264503a7782SBrian Somers 265503a7782SBrian Somers ipcp->peer_ip = ipcp->cfg.peer_range.ipaddr; 266503a7782SBrian Somers ipcp->peer_compproto = 0; 2671ae349f5Scvs2svn 2681ae349f5Scvs2svn /* 2691ae349f5Scvs2svn * Some implementations of PPP require that we send a 2701ae349f5Scvs2svn * *special* value as our address, even though the rfc specifies 2711ae349f5Scvs2svn * full negotiation (e.g. "0.0.0.0" or Not "0.0.0.0"). 2721ae349f5Scvs2svn */ 273503a7782SBrian Somers if (ipcp->cfg.HaveTriggerAddress) { 274503a7782SBrian Somers ipcp->my_ip = ipcp->cfg.TriggerAddress; 27529e275ceSBrian Somers LogPrintf(LogIPCP, "Using trigger address %s\n", 276503a7782SBrian Somers inet_ntoa(ipcp->cfg.TriggerAddress)); 277503a7782SBrian Somers } else 278503a7782SBrian Somers ipcp->my_ip = ipcp->cfg.my_range.ipaddr; 27929e275ceSBrian Somers 2801ae349f5Scvs2svn if (Enabled(ConfVjcomp)) 281503a7782SBrian Somers ipcp->my_compproto = (PROTO_VJCOMP << 16) + 282503a7782SBrian Somers ((ipcp->cfg.VJInitSlots - 1) << 8) + 283503a7782SBrian Somers ipcp->cfg.VJInitComp; 2841ae349f5Scvs2svn else 285503a7782SBrian Somers ipcp->my_compproto = 0; 286eaa4df37SBrian Somers sl_compress_init(&ipcp->vj.cslc, ipcp->cfg.VJInitSlots - 1); 28729e275ceSBrian Somers 288503a7782SBrian Somers ipcp->peer_reject = 0; 289503a7782SBrian Somers ipcp->my_reject = 0; 290503a7782SBrian Somers 291503a7782SBrian Somers throughput_init(&ipcp->throughput); 2921ae349f5Scvs2svn } 2931ae349f5Scvs2svn 294455aabc3SBrian Somers static int 29530c2f2ffSBrian Somers ipcp_SetIPaddress(struct bundle *bundle, struct in_addr myaddr, 29630c2f2ffSBrian Somers struct in_addr hisaddr, int silent) 297455aabc3SBrian Somers { 298455aabc3SBrian Somers struct sockaddr_in *sock_in; 299455aabc3SBrian Somers int s; 300455aabc3SBrian Somers u_long mask, addr; 301455aabc3SBrian Somers struct ifaliasreq ifra; 302455aabc3SBrian Somers 303455aabc3SBrian Somers /* If given addresses are alreay set, then ignore this request */ 30430c2f2ffSBrian Somers if (bundle->ncp.ipcp.my_ifip.s_addr == myaddr.s_addr && 30530c2f2ffSBrian Somers bundle->ncp.ipcp.peer_ifip.s_addr == hisaddr.s_addr) 306455aabc3SBrian Somers return 0; 307455aabc3SBrian Somers 30830c2f2ffSBrian Somers IpcpCleanInterface(&bundle->ncp.ipcp.fsm); 30968a0f0ccSBrian Somers 310455aabc3SBrian Somers s = ID0socket(AF_INET, SOCK_DGRAM, 0); 311455aabc3SBrian Somers if (s < 0) { 312455aabc3SBrian Somers LogPrintf(LogERROR, "SetIpDevice: socket(): %s\n", strerror(errno)); 313455aabc3SBrian Somers return (-1); 314455aabc3SBrian Somers } 315455aabc3SBrian Somers 316455aabc3SBrian Somers memset(&ifra, '\0', sizeof ifra); 317455aabc3SBrian Somers strncpy(ifra.ifra_name, bundle->ifname, sizeof ifra.ifra_name - 1); 318455aabc3SBrian Somers ifra.ifra_name[sizeof ifra.ifra_name - 1] = '\0'; 319455aabc3SBrian Somers 320455aabc3SBrian Somers /* Set interface address */ 321455aabc3SBrian Somers sock_in = (struct sockaddr_in *)&ifra.ifra_addr; 322455aabc3SBrian Somers sock_in->sin_family = AF_INET; 323455aabc3SBrian Somers sock_in->sin_addr = myaddr; 324455aabc3SBrian Somers sock_in->sin_len = sizeof *sock_in; 325455aabc3SBrian Somers 326455aabc3SBrian Somers /* Set destination address */ 327455aabc3SBrian Somers sock_in = (struct sockaddr_in *)&ifra.ifra_broadaddr; 328455aabc3SBrian Somers sock_in->sin_family = AF_INET; 329455aabc3SBrian Somers sock_in->sin_addr = hisaddr; 330455aabc3SBrian Somers sock_in->sin_len = sizeof *sock_in; 331455aabc3SBrian Somers 332455aabc3SBrian Somers addr = ntohl(myaddr.s_addr); 333455aabc3SBrian Somers if (IN_CLASSA(addr)) 334455aabc3SBrian Somers mask = IN_CLASSA_NET; 335455aabc3SBrian Somers else if (IN_CLASSB(addr)) 336455aabc3SBrian Somers mask = IN_CLASSB_NET; 337455aabc3SBrian Somers else 338455aabc3SBrian Somers mask = IN_CLASSC_NET; 339455aabc3SBrian Somers 340455aabc3SBrian Somers /* if subnet mask is given, use it instead of class mask */ 34130c2f2ffSBrian Somers if (bundle->ncp.ipcp.cfg.netmask.s_addr != INADDR_ANY && 34230c2f2ffSBrian Somers (ntohl(bundle->ncp.ipcp.cfg.netmask.s_addr) & mask) == mask) 34330c2f2ffSBrian Somers mask = ntohl(bundle->ncp.ipcp.cfg.netmask.s_addr); 344455aabc3SBrian Somers 345455aabc3SBrian Somers sock_in = (struct sockaddr_in *)&ifra.ifra_mask; 346455aabc3SBrian Somers sock_in->sin_family = AF_INET; 347455aabc3SBrian Somers sock_in->sin_addr.s_addr = htonl(mask); 348455aabc3SBrian Somers sock_in->sin_len = sizeof *sock_in; 349455aabc3SBrian Somers 350455aabc3SBrian Somers if (ID0ioctl(s, SIOCAIFADDR, &ifra) < 0) { 351455aabc3SBrian Somers if (!silent) 352455aabc3SBrian Somers LogPrintf(LogERROR, "SetIpDevice: ioctl(SIOCAIFADDR): %s\n", 353455aabc3SBrian Somers strerror(errno)); 354455aabc3SBrian Somers close(s); 355455aabc3SBrian Somers return (-1); 356455aabc3SBrian Somers } 357455aabc3SBrian Somers 35830c2f2ffSBrian Somers bundle->ncp.ipcp.peer_ifip.s_addr = hisaddr.s_addr; 35930c2f2ffSBrian Somers bundle->ncp.ipcp.my_ifip.s_addr = myaddr.s_addr; 360455aabc3SBrian Somers 361455aabc3SBrian Somers if (Enabled(ConfProxy)) 36230c2f2ffSBrian Somers sifproxyarp(bundle, bundle->ncp.ipcp.peer_ifip, s); 363455aabc3SBrian Somers 364455aabc3SBrian Somers close(s); 365455aabc3SBrian Somers return (0); 366455aabc3SBrian Somers } 367455aabc3SBrian Somers 368455aabc3SBrian Somers static struct in_addr 36930c2f2ffSBrian Somers ChooseHisAddr(struct bundle *bundle, const struct in_addr gw) 370455aabc3SBrian Somers { 371455aabc3SBrian Somers struct in_addr try; 372455aabc3SBrian Somers int f; 373455aabc3SBrian Somers 3745828db6dSBrian Somers for (f = 0; f < bundle->ncp.ipcp.cfg.peer_list.nItems; f++) { 3755828db6dSBrian Somers try = iplist_next(&bundle->ncp.ipcp.cfg.peer_list); 376455aabc3SBrian Somers LogPrintf(LogDEBUG, "ChooseHisAddr: Check item %d (%s)\n", 377455aabc3SBrian Somers f, inet_ntoa(try)); 37830c2f2ffSBrian Somers if (ipcp_SetIPaddress(bundle, gw, try, 1) == 0) { 379455aabc3SBrian Somers LogPrintf(LogIPCP, "ChooseHisAddr: Selected IP address %s\n", 380455aabc3SBrian Somers inet_ntoa(try)); 381455aabc3SBrian Somers break; 382455aabc3SBrian Somers } 383455aabc3SBrian Somers } 384455aabc3SBrian Somers 3855828db6dSBrian Somers if (f == bundle->ncp.ipcp.cfg.peer_list.nItems) { 386455aabc3SBrian Somers LogPrintf(LogDEBUG, "ChooseHisAddr: All addresses in use !\n"); 387455aabc3SBrian Somers try.s_addr = INADDR_ANY; 388455aabc3SBrian Somers } 389455aabc3SBrian Somers 390455aabc3SBrian Somers return try; 391455aabc3SBrian Somers } 392455aabc3SBrian Somers 3931ae349f5Scvs2svn static void 3941ae349f5Scvs2svn IpcpInitRestartCounter(struct fsm * fp) 3951ae349f5Scvs2svn { 3967308ec68SBrian Somers /* Set fsm timer load */ 3971ae349f5Scvs2svn fp->FsmTimer.load = VarRetryTimeout * SECTICKS; 3981ae349f5Scvs2svn fp->restart = 5; 3991ae349f5Scvs2svn } 4001ae349f5Scvs2svn 4011ae349f5Scvs2svn static void 4021ae349f5Scvs2svn IpcpSendConfigReq(struct fsm *fp) 4031ae349f5Scvs2svn { 4047308ec68SBrian Somers /* Send config REQ please */ 4058c07a7b2SBrian Somers struct physical *p = link2physical(fp->link); 406aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 4072267893fSBrian Somers u_char buff[12]; 4082267893fSBrian Somers struct lcp_opt *o; 4091ae349f5Scvs2svn 4102267893fSBrian Somers o = (struct lcp_opt *)buff; 41130c2f2ffSBrian Somers 41283d1af55SBrian Somers if ((p && !Physical_IsSync(p)) || !REJECTED(ipcp, TY_IPADDR)) { 4132267893fSBrian Somers *(u_int32_t *)o->data = ipcp->my_ip.s_addr; 4142267893fSBrian Somers INC_LCP_OPT(TY_IPADDR, 6, o); 4151ae349f5Scvs2svn } 4161ae349f5Scvs2svn 4172267893fSBrian Somers if (ipcp->my_compproto && !REJECTED(ipcp, TY_COMPPROTO)) 41883d1af55SBrian Somers if (ipcp->heis1172) { 4192267893fSBrian Somers *(u_short *)o->data = htons(PROTO_VJCOMP); 4202267893fSBrian Somers INC_LCP_OPT(TY_COMPPROTO, 4, o); 4211ae349f5Scvs2svn } else { 4222267893fSBrian Somers *(u_long *)o->data = htonl(ipcp->my_compproto); 4232267893fSBrian Somers INC_LCP_OPT(TY_COMPPROTO, 6, o); 4241ae349f5Scvs2svn } 4252267893fSBrian Somers 4262267893fSBrian Somers FsmOutput(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff); 4271ae349f5Scvs2svn } 4281ae349f5Scvs2svn 4291ae349f5Scvs2svn static void 4302267893fSBrian Somers IpcpSentTerminateReq(struct fsm * fp) 4311ae349f5Scvs2svn { 4327308ec68SBrian Somers /* Term REQ just sent by FSM */ 4331ae349f5Scvs2svn } 4341ae349f5Scvs2svn 4351ae349f5Scvs2svn static void 4362267893fSBrian Somers IpcpSendTerminateAck(struct fsm *fp, u_char id) 4371ae349f5Scvs2svn { 4387308ec68SBrian Somers /* Send Term ACK please */ 4392267893fSBrian Somers FsmOutput(fp, CODE_TERMACK, id, NULL, 0); 4401ae349f5Scvs2svn } 4411ae349f5Scvs2svn 4421ae349f5Scvs2svn static void 4431ae349f5Scvs2svn IpcpLayerStart(struct fsm * fp) 4441ae349f5Scvs2svn { 4457308ec68SBrian Somers /* We're about to start up ! */ 4461ae349f5Scvs2svn LogPrintf(LogIPCP, "IpcpLayerStart.\n"); 447455aabc3SBrian Somers 448455aabc3SBrian Somers /* This is where we should be setting up the interface in AUTO mode */ 4491ae349f5Scvs2svn } 4501ae349f5Scvs2svn 4511ae349f5Scvs2svn static void 4521ae349f5Scvs2svn IpcpLayerFinish(struct fsm *fp) 4531ae349f5Scvs2svn { 4547308ec68SBrian Somers /* We're now down */ 4551ae349f5Scvs2svn LogPrintf(LogIPCP, "IpcpLayerFinish.\n"); 4561ae349f5Scvs2svn } 4571ae349f5Scvs2svn 45868a0f0ccSBrian Somers void 45968a0f0ccSBrian Somers IpcpCleanInterface(struct fsm *fp) 46068a0f0ccSBrian Somers { 46168a0f0ccSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 46268a0f0ccSBrian Somers struct ifaliasreq ifra; 46368a0f0ccSBrian Somers struct sockaddr_in *me, *peer; 46468a0f0ccSBrian Somers int s; 46568a0f0ccSBrian Somers 46668a0f0ccSBrian Somers s = ID0socket(AF_INET, SOCK_DGRAM, 0); 46768a0f0ccSBrian Somers if (s < 0) { 46868a0f0ccSBrian Somers LogPrintf(LogERROR, "IpcpCleanInterface: socket: %s\n", strerror(errno)); 46968a0f0ccSBrian Somers return; 47068a0f0ccSBrian Somers } 47168a0f0ccSBrian Somers 47268a0f0ccSBrian Somers if (Enabled(ConfProxy)) 473503a7782SBrian Somers cifproxyarp(fp->bundle, ipcp->peer_ifip, s); 47468a0f0ccSBrian Somers 475503a7782SBrian Somers if (ipcp->my_ifip.s_addr != INADDR_ANY || 476503a7782SBrian Somers ipcp->peer_ifip.s_addr != INADDR_ANY) { 47768a0f0ccSBrian Somers memset(&ifra, '\0', sizeof ifra); 47868a0f0ccSBrian Somers strncpy(ifra.ifra_name, fp->bundle->ifname, sizeof ifra.ifra_name - 1); 47968a0f0ccSBrian Somers ifra.ifra_name[sizeof ifra.ifra_name - 1] = '\0'; 48068a0f0ccSBrian Somers me = (struct sockaddr_in *)&ifra.ifra_addr; 48168a0f0ccSBrian Somers peer = (struct sockaddr_in *)&ifra.ifra_broadaddr; 48268a0f0ccSBrian Somers me->sin_family = peer->sin_family = AF_INET; 48368a0f0ccSBrian Somers me->sin_len = peer->sin_len = sizeof(struct sockaddr_in); 484503a7782SBrian Somers me->sin_addr = ipcp->my_ifip; 485503a7782SBrian Somers peer->sin_addr = ipcp->peer_ifip; 48668a0f0ccSBrian Somers if (ID0ioctl(s, SIOCDIFADDR, &ifra) < 0) { 48768a0f0ccSBrian Somers LogPrintf(LogERROR, "IpcpCleanInterface: ioctl(SIOCDIFADDR): %s\n", 48868a0f0ccSBrian Somers strerror(errno)); 48968a0f0ccSBrian Somers close(s); 49068a0f0ccSBrian Somers } 491503a7782SBrian Somers ipcp->my_ifip.s_addr = ipcp->peer_ifip.s_addr = INADDR_ANY; 49268a0f0ccSBrian Somers } 49368a0f0ccSBrian Somers 49468a0f0ccSBrian Somers close(s); 49568a0f0ccSBrian Somers } 49668a0f0ccSBrian Somers 4971ae349f5Scvs2svn static void 4981ae349f5Scvs2svn IpcpLayerDown(struct fsm *fp) 4991ae349f5Scvs2svn { 5007308ec68SBrian Somers /* About to come down */ 501aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 502455aabc3SBrian Somers const char *s; 503455aabc3SBrian Somers 504503a7782SBrian Somers s = inet_ntoa(ipcp->peer_ifip); 505455aabc3SBrian Somers LogPrintf(LogIsKept(LogLINK) ? LogLINK : LogIPCP, "IpcpLayerDown: %s\n", s); 506455aabc3SBrian Somers 50783d1af55SBrian Somers throughput_stop(&ipcp->throughput); 50883d1af55SBrian Somers throughput_log(&ipcp->throughput, LogIPCP, NULL); 509455aabc3SBrian Somers /* 510455aabc3SBrian Somers * XXX this stuff should really live in the FSM. Our config should 511455aabc3SBrian Somers * associate executable sections in files with events. 512455aabc3SBrian Somers */ 513455aabc3SBrian Somers if (SelectSystem(fp->bundle, s, LINKDOWNFILE) < 0) 514455aabc3SBrian Somers if (GetLabel()) { 515455aabc3SBrian Somers if (SelectSystem(fp->bundle, GetLabel(), LINKDOWNFILE) < 0) 516455aabc3SBrian Somers SelectSystem(fp->bundle, "MYADDR", LINKDOWNFILE); 517455aabc3SBrian Somers } else 518455aabc3SBrian Somers SelectSystem(fp->bundle, "MYADDR", LINKDOWNFILE); 519455aabc3SBrian Somers 52068a0f0ccSBrian Somers if (!(mode & MODE_AUTO)) 52168a0f0ccSBrian Somers IpcpCleanInterface(fp); 5221ae349f5Scvs2svn } 5231ae349f5Scvs2svn 5241ae349f5Scvs2svn static void 5251ae349f5Scvs2svn IpcpLayerUp(struct fsm *fp) 5261ae349f5Scvs2svn { 5277308ec68SBrian Somers /* We're now up */ 528aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 5291ae349f5Scvs2svn char tbuff[100]; 5301ae349f5Scvs2svn 5312267893fSBrian Somers LogPrintf(LogIPCP, "IpcpLayerUp.\n"); 532503a7782SBrian Somers snprintf(tbuff, sizeof tbuff, "myaddr = %s ", inet_ntoa(ipcp->my_ip)); 533455aabc3SBrian Somers LogPrintf(LogIsKept(LogIPCP) ? LogIPCP : LogLINK, " %s hisaddr = %s\n", 534503a7782SBrian Somers tbuff, inet_ntoa(ipcp->peer_ip)); 5351ae349f5Scvs2svn 536503a7782SBrian Somers if (ipcp->peer_compproto >> 16 == PROTO_VJCOMP) 537eaa4df37SBrian Somers sl_compress_init(&ipcp->vj.cslc, (ipcp->peer_compproto >> 8) & 255); 5381ae349f5Scvs2svn 53930c2f2ffSBrian Somers if (ipcp_SetIPaddress(fp->bundle, ipcp->my_ip, 54030c2f2ffSBrian Somers ipcp->peer_ip, 0) < 0) { 5411ae349f5Scvs2svn LogPrintf(LogERROR, "IpcpLayerUp: unable to set ip address\n"); 5421ae349f5Scvs2svn return; 5431ae349f5Scvs2svn } 544455aabc3SBrian Somers 5451ae349f5Scvs2svn #ifndef NOALIAS 5461ae349f5Scvs2svn if (mode & MODE_ALIAS) 547503a7782SBrian Somers VarPacketAliasSetAddress(ipcp->my_ip); 5481ae349f5Scvs2svn #endif 549455aabc3SBrian Somers 550455aabc3SBrian Somers LogPrintf(LogIsKept(LogLINK) ? LogLINK : LogIPCP, "IpcpLayerUp: %s\n", 551503a7782SBrian Somers inet_ntoa(ipcp->peer_ifip)); 552455aabc3SBrian Somers 553455aabc3SBrian Somers /* 554455aabc3SBrian Somers * XXX this stuff should really live in the FSM. Our config should 555455aabc3SBrian Somers * associate executable sections in files with events. 556455aabc3SBrian Somers */ 557503a7782SBrian Somers if (SelectSystem(fp->bundle, inet_ntoa(ipcp->my_ifip), LINKUPFILE) < 0) 558455aabc3SBrian Somers if (GetLabel()) { 559455aabc3SBrian Somers if (SelectSystem(fp->bundle, GetLabel(), LINKUPFILE) < 0) 560455aabc3SBrian Somers SelectSystem(fp->bundle, "MYADDR", LINKUPFILE); 561455aabc3SBrian Somers } else 562455aabc3SBrian Somers SelectSystem(fp->bundle, "MYADDR", LINKUPFILE); 563455aabc3SBrian Somers 56483d1af55SBrian Somers throughput_start(&ipcp->throughput); 56585b542cfSBrian Somers prompt_Display(&prompt, fp->bundle); 5661ae349f5Scvs2svn } 5671ae349f5Scvs2svn 5681ae349f5Scvs2svn static int 5691ae349f5Scvs2svn AcceptableAddr(struct in_range *prange, struct in_addr ipaddr) 5701ae349f5Scvs2svn { 5717308ec68SBrian Somers /* Is the given IP in the given range ? */ 5721ae349f5Scvs2svn LogPrintf(LogDEBUG, "requested = %x\n", htonl(ipaddr.s_addr)); 5731ae349f5Scvs2svn LogPrintf(LogDEBUG, "range = %x\n", htonl(prange->ipaddr.s_addr)); 5741ae349f5Scvs2svn LogPrintf(LogDEBUG, "/%x\n", htonl(prange->mask.s_addr)); 5751ae349f5Scvs2svn LogPrintf(LogDEBUG, "%x, %x\n", htonl(prange->ipaddr.s_addr & prange-> 5761ae349f5Scvs2svn mask.s_addr), htonl(ipaddr.s_addr & prange->mask.s_addr)); 5771ae349f5Scvs2svn return (prange->ipaddr.s_addr & prange->mask.s_addr) == 5781ae349f5Scvs2svn (ipaddr.s_addr & prange->mask.s_addr) && ipaddr.s_addr; 5791ae349f5Scvs2svn } 5801ae349f5Scvs2svn 5811ae349f5Scvs2svn static void 58230c2f2ffSBrian Somers IpcpDecodeConfig(struct fsm *fp, u_char * cp, int plen, int mode_type, 58330c2f2ffSBrian Somers struct fsm_decode *dec) 5841ae349f5Scvs2svn { 5857308ec68SBrian Somers /* Deal with incoming PROTO_IPCP */ 586aad81d1eSBrian Somers struct ipcp *ipcp = fsm2ipcp(fp); 5871ae349f5Scvs2svn int type, length; 5881ae349f5Scvs2svn u_long *lp, compproto; 5891ae349f5Scvs2svn struct compreq *pcomp; 5901ae349f5Scvs2svn struct in_addr ipaddr, dstipaddr, dnsstuff, ms_info_req; 59130c2f2ffSBrian Somers char tbuff[100], tbuff2[100]; 5921ae349f5Scvs2svn 5931ae349f5Scvs2svn while (plen >= sizeof(struct fsmconfig)) { 5941ae349f5Scvs2svn type = *cp; 5951ae349f5Scvs2svn length = cp[1]; 5961ae349f5Scvs2svn if (type < NCFTYPES) 5971ae349f5Scvs2svn snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes[type], length); 5981ae349f5Scvs2svn else if (type > 128 && type < 128 + NCFTYPES128) 5991ae349f5Scvs2svn snprintf(tbuff, sizeof tbuff, " %s[%d] ", cftypes128[type-128], length); 6001ae349f5Scvs2svn else 6011ae349f5Scvs2svn snprintf(tbuff, sizeof tbuff, " <%d>[%d] ", type, length); 6021ae349f5Scvs2svn 6031ae349f5Scvs2svn switch (type) { 6041ae349f5Scvs2svn case TY_IPADDR: /* RFC1332 */ 6051ae349f5Scvs2svn lp = (u_long *) (cp + 2); 6061ae349f5Scvs2svn ipaddr.s_addr = *lp; 6071ae349f5Scvs2svn LogPrintf(LogIPCP, "%s %s\n", tbuff, inet_ntoa(ipaddr)); 6081ae349f5Scvs2svn 6091ae349f5Scvs2svn switch (mode_type) { 6101ae349f5Scvs2svn case MODE_REQ: 611503a7782SBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 6121ae349f5Scvs2svn if (ipaddr.s_addr == INADDR_ANY || 613503a7782SBrian Somers iplist_ip2pos(&ipcp->cfg.peer_list, ipaddr) < 0 || 61430c2f2ffSBrian Somers ipcp_SetIPaddress(fp->bundle, ipcp->cfg.my_range.ipaddr, 61530c2f2ffSBrian Somers ipaddr, 1)) { 6161ae349f5Scvs2svn LogPrintf(LogIPCP, "%s: Address invalid or already in use\n", 6171ae349f5Scvs2svn inet_ntoa(ipaddr)); 618503a7782SBrian Somers ipcp->peer_ip = ChooseHisAddr 61930c2f2ffSBrian Somers (fp->bundle, ipcp->cfg.my_range.ipaddr); 620503a7782SBrian Somers if (ipcp->peer_ip.s_addr == INADDR_ANY) { 62130c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 62230c2f2ffSBrian Somers dec->rejend += length; 6231ae349f5Scvs2svn } else { 62430c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 62530c2f2ffSBrian Somers memcpy(dec->nakend+2, &ipcp->peer_ip.s_addr, length - 2); 62630c2f2ffSBrian Somers dec->nakend += length; 6271ae349f5Scvs2svn } 6281ae349f5Scvs2svn break; 6291ae349f5Scvs2svn } 630503a7782SBrian Somers } else if (!AcceptableAddr(&ipcp->cfg.peer_range, ipaddr)) { 6311ae349f5Scvs2svn /* 6321ae349f5Scvs2svn * If destination address is not acceptable, insist to use what we 6331ae349f5Scvs2svn * want to use. 6341ae349f5Scvs2svn */ 63530c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 63630c2f2ffSBrian Somers memcpy(dec->nakend+2, &ipcp->peer_ip.s_addr, length - 2); 63730c2f2ffSBrian Somers dec->nakend += length; 6381ae349f5Scvs2svn break; 6391ae349f5Scvs2svn } 640503a7782SBrian Somers ipcp->peer_ip = ipaddr; 64130c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 64230c2f2ffSBrian Somers dec->ackend += length; 6431ae349f5Scvs2svn break; 6441ae349f5Scvs2svn case MODE_NAK: 645503a7782SBrian Somers if (AcceptableAddr(&ipcp->cfg.my_range, ipaddr)) { 6461ae349f5Scvs2svn /* Use address suggested by peer */ 6471ae349f5Scvs2svn snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s ", tbuff, 648503a7782SBrian Somers inet_ntoa(ipcp->my_ip)); 6491ae349f5Scvs2svn LogPrintf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 650503a7782SBrian Somers ipcp->my_ip = ipaddr; 6511ae349f5Scvs2svn } else { 6521ae349f5Scvs2svn LogPrintf(LogIPCP, "%s: Unacceptable address!\n", inet_ntoa(ipaddr)); 65383d1af55SBrian Somers FsmClose(&ipcp->fsm); 6541ae349f5Scvs2svn } 6551ae349f5Scvs2svn break; 6561ae349f5Scvs2svn case MODE_REJ: 657503a7782SBrian Somers ipcp->peer_reject |= (1 << type); 6581ae349f5Scvs2svn break; 6591ae349f5Scvs2svn } 6601ae349f5Scvs2svn break; 6611ae349f5Scvs2svn case TY_COMPPROTO: 6621ae349f5Scvs2svn lp = (u_long *) (cp + 2); 6631ae349f5Scvs2svn compproto = htonl(*lp); 6641ae349f5Scvs2svn LogPrintf(LogIPCP, "%s %s\n", tbuff, vj2asc(compproto)); 6651ae349f5Scvs2svn 6661ae349f5Scvs2svn switch (mode_type) { 6671ae349f5Scvs2svn case MODE_REQ: 6681ae349f5Scvs2svn if (!Acceptable(ConfVjcomp)) { 66930c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 67030c2f2ffSBrian Somers dec->rejend += length; 6711ae349f5Scvs2svn } else { 6721ae349f5Scvs2svn pcomp = (struct compreq *) (cp + 2); 6731ae349f5Scvs2svn switch (length) { 6741ae349f5Scvs2svn case 4: /* RFC1172 */ 6751ae349f5Scvs2svn if (ntohs(pcomp->proto) == PROTO_VJCOMP) { 6761ae349f5Scvs2svn LogPrintf(LogWARN, "Peer is speaking RFC1172 compression protocol !\n"); 67783d1af55SBrian Somers ipcp->heis1172 = 1; 678503a7782SBrian Somers ipcp->peer_compproto = compproto; 67930c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 68030c2f2ffSBrian Somers dec->ackend += length; 6811ae349f5Scvs2svn } else { 68230c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 6831ae349f5Scvs2svn pcomp->proto = htons(PROTO_VJCOMP); 68430c2f2ffSBrian Somers memcpy(dec->nakend+2, &pcomp, 2); 68530c2f2ffSBrian Somers dec->nakend += length; 6861ae349f5Scvs2svn } 6871ae349f5Scvs2svn break; 6881ae349f5Scvs2svn case 6: /* RFC1332 */ 6891ae349f5Scvs2svn if (ntohs(pcomp->proto) == PROTO_VJCOMP 690503a7782SBrian Somers && pcomp->slots <= MAX_VJ_STATES 691503a7782SBrian Somers && pcomp->slots >= MIN_VJ_STATES) { 692503a7782SBrian Somers ipcp->peer_compproto = compproto; 69383d1af55SBrian Somers ipcp->heis1172 = 0; 69430c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 69530c2f2ffSBrian Somers dec->ackend += length; 6961ae349f5Scvs2svn } else { 69730c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 6981ae349f5Scvs2svn pcomp->proto = htons(PROTO_VJCOMP); 699503a7782SBrian Somers pcomp->slots = DEF_VJ_STATES; 7001ae349f5Scvs2svn pcomp->compcid = 0; 70130c2f2ffSBrian Somers memcpy(dec->nakend+2, &pcomp, sizeof pcomp); 70230c2f2ffSBrian Somers dec->nakend += length; 7031ae349f5Scvs2svn } 7041ae349f5Scvs2svn break; 7051ae349f5Scvs2svn default: 70630c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 70730c2f2ffSBrian Somers dec->rejend += length; 7081ae349f5Scvs2svn break; 7091ae349f5Scvs2svn } 7101ae349f5Scvs2svn } 7111ae349f5Scvs2svn break; 7121ae349f5Scvs2svn case MODE_NAK: 7131ae349f5Scvs2svn LogPrintf(LogIPCP, "%s changing compproto: %08x --> %08x\n", 714503a7782SBrian Somers tbuff, ipcp->my_compproto, compproto); 715503a7782SBrian Somers ipcp->my_compproto = compproto; 7161ae349f5Scvs2svn break; 7171ae349f5Scvs2svn case MODE_REJ: 718503a7782SBrian Somers ipcp->peer_reject |= (1 << type); 7191ae349f5Scvs2svn break; 7201ae349f5Scvs2svn } 7211ae349f5Scvs2svn break; 7221ae349f5Scvs2svn case TY_IPADDRS: /* RFC1172 */ 7231ae349f5Scvs2svn lp = (u_long *) (cp + 2); 7241ae349f5Scvs2svn ipaddr.s_addr = *lp; 7251ae349f5Scvs2svn lp = (u_long *) (cp + 6); 7261ae349f5Scvs2svn dstipaddr.s_addr = *lp; 7271ae349f5Scvs2svn snprintf(tbuff2, sizeof tbuff2, "%s %s,", tbuff, inet_ntoa(ipaddr)); 7281ae349f5Scvs2svn LogPrintf(LogIPCP, "%s %s\n", tbuff2, inet_ntoa(dstipaddr)); 7291ae349f5Scvs2svn 7301ae349f5Scvs2svn switch (mode_type) { 7311ae349f5Scvs2svn case MODE_REQ: 732503a7782SBrian Somers ipcp->peer_ip = ipaddr; 733503a7782SBrian Somers ipcp->my_ip = dstipaddr; 73430c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 73530c2f2ffSBrian Somers dec->ackend += length; 7361ae349f5Scvs2svn break; 7371ae349f5Scvs2svn case MODE_NAK: 7381ae349f5Scvs2svn snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s", tbuff, 739503a7782SBrian Somers inet_ntoa(ipcp->my_ip)); 7401ae349f5Scvs2svn LogPrintf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr)); 741503a7782SBrian Somers ipcp->my_ip = ipaddr; 742503a7782SBrian Somers ipcp->peer_ip = dstipaddr; 7431ae349f5Scvs2svn break; 7441ae349f5Scvs2svn case MODE_REJ: 745503a7782SBrian Somers ipcp->peer_reject |= (1 << type); 7461ae349f5Scvs2svn break; 7471ae349f5Scvs2svn } 7481ae349f5Scvs2svn break; 7491ae349f5Scvs2svn 7501ae349f5Scvs2svn /* 7511ae349f5Scvs2svn * MS extensions for MS's PPP 7521ae349f5Scvs2svn */ 7531ae349f5Scvs2svn 7541ae349f5Scvs2svn #ifndef NOMSEXT 7551ae349f5Scvs2svn case TY_PRIMARY_DNS: /* MS PPP DNS negotiation hack */ 7561ae349f5Scvs2svn case TY_SECONDARY_DNS: 75730c2f2ffSBrian Somers switch (mode_type) { 75830c2f2ffSBrian Somers case MODE_REQ: 7591ae349f5Scvs2svn if (!Enabled(ConfMSExt)) { 7601ae349f5Scvs2svn LogPrintf(LogIPCP, "MS NS req - rejected - msext disabled\n"); 76183d1af55SBrian Somers ipcp->my_reject |= (1 << type); 76230c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 76330c2f2ffSBrian Somers dec->rejend += length; 7641ae349f5Scvs2svn break; 7651ae349f5Scvs2svn } 7661ae349f5Scvs2svn lp = (u_long *) (cp + 2); 7671ae349f5Scvs2svn dnsstuff.s_addr = *lp; 768503a7782SBrian Somers ms_info_req.s_addr = ipcp->cfg.ns_entries 76929e275ceSBrian Somers [(type - TY_PRIMARY_DNS) ? 1 : 0].s_addr; 7701ae349f5Scvs2svn if (dnsstuff.s_addr != ms_info_req.s_addr) { 7711ae349f5Scvs2svn 7721ae349f5Scvs2svn /* 7731ae349f5Scvs2svn * So the client has got the DNS stuff wrong (first request) so 7741ae349f5Scvs2svn * we'll tell 'em how it is 7751ae349f5Scvs2svn */ 77630c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); /* copy first two (type/length) */ 7771ae349f5Scvs2svn LogPrintf(LogIPCP, "MS NS req %d:%s->%s - nak\n", 7782267893fSBrian Somers type, inet_ntoa(dnsstuff), inet_ntoa(ms_info_req)); 77930c2f2ffSBrian Somers memcpy(dec->nakend+2, &ms_info_req, length); 78030c2f2ffSBrian Somers dec->nakend += length; 7811ae349f5Scvs2svn break; 7821ae349f5Scvs2svn } 7831ae349f5Scvs2svn 7841ae349f5Scvs2svn /* 7851ae349f5Scvs2svn * Otherwise they have it right (this time) so we send a ack packet 7861ae349f5Scvs2svn * back confirming it... end of story 7871ae349f5Scvs2svn */ 7881ae349f5Scvs2svn LogPrintf(LogIPCP, "MS NS req %d:%s ok - ack\n", 7892267893fSBrian Somers type, inet_ntoa(ms_info_req)); 79030c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 79130c2f2ffSBrian Somers dec->ackend += length; 7921ae349f5Scvs2svn break; 7931ae349f5Scvs2svn case MODE_NAK: /* what does this mean?? */ 7941ae349f5Scvs2svn LogPrintf(LogIPCP, "MS NS req %d - NAK??\n", type); 7951ae349f5Scvs2svn break; 7961ae349f5Scvs2svn case MODE_REJ: /* confused?? me to :) */ 7971ae349f5Scvs2svn LogPrintf(LogIPCP, "MS NS req %d - REJ??\n", type); 7981ae349f5Scvs2svn break; 7991ae349f5Scvs2svn } 8001ae349f5Scvs2svn break; 8011ae349f5Scvs2svn 8021ae349f5Scvs2svn case TY_PRIMARY_NBNS: /* MS PPP NetBIOS nameserver hack */ 8031ae349f5Scvs2svn case TY_SECONDARY_NBNS: 80430c2f2ffSBrian Somers switch (mode_type) { 80530c2f2ffSBrian Somers case MODE_REQ: 8061ae349f5Scvs2svn if (!Enabled(ConfMSExt)) { 8071ae349f5Scvs2svn LogPrintf(LogIPCP, "MS NBNS req - rejected - msext disabled\n"); 80883d1af55SBrian Somers ipcp->my_reject |= (1 << type); 80930c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 81030c2f2ffSBrian Somers dec->rejend += length; 8111ae349f5Scvs2svn break; 8121ae349f5Scvs2svn } 8131ae349f5Scvs2svn lp = (u_long *) (cp + 2); 8141ae349f5Scvs2svn dnsstuff.s_addr = *lp; 815503a7782SBrian Somers ms_info_req.s_addr = ipcp->cfg.nbns_entries 81629e275ceSBrian Somers [(type - TY_PRIMARY_NBNS) ? 1 : 0].s_addr; 8171ae349f5Scvs2svn if (dnsstuff.s_addr != ms_info_req.s_addr) { 81830c2f2ffSBrian Somers memcpy(dec->nakend, cp, 2); 81930c2f2ffSBrian Somers memcpy(dec->nakend+2, &ms_info_req.s_addr, length); 8201ae349f5Scvs2svn LogPrintf(LogIPCP, "MS NBNS req %d:%s->%s - nak\n", 8212267893fSBrian Somers type, inet_ntoa(dnsstuff), inet_ntoa(ms_info_req)); 82230c2f2ffSBrian Somers dec->nakend += length; 8231ae349f5Scvs2svn break; 8241ae349f5Scvs2svn } 8251ae349f5Scvs2svn LogPrintf(LogIPCP, "MS NBNS req %d:%s ok - ack\n", 8262267893fSBrian Somers type, inet_ntoa(ms_info_req)); 82730c2f2ffSBrian Somers memcpy(dec->ackend, cp, length); 82830c2f2ffSBrian Somers dec->ackend += length; 8291ae349f5Scvs2svn break; 8301ae349f5Scvs2svn case MODE_NAK: 8311ae349f5Scvs2svn LogPrintf(LogIPCP, "MS NBNS req %d - NAK??\n", type); 8321ae349f5Scvs2svn break; 8331ae349f5Scvs2svn case MODE_REJ: 8341ae349f5Scvs2svn LogPrintf(LogIPCP, "MS NBNS req %d - REJ??\n", type); 8351ae349f5Scvs2svn break; 8361ae349f5Scvs2svn } 8371ae349f5Scvs2svn break; 8381ae349f5Scvs2svn 8391ae349f5Scvs2svn #endif 8401ae349f5Scvs2svn 8411ae349f5Scvs2svn default: 84230c2f2ffSBrian Somers if (mode_type != MODE_NOP) { 84383d1af55SBrian Somers ipcp->my_reject |= (1 << type); 84430c2f2ffSBrian Somers memcpy(dec->rejend, cp, length); 84530c2f2ffSBrian Somers dec->rejend += length; 84630c2f2ffSBrian Somers } 8471ae349f5Scvs2svn break; 8481ae349f5Scvs2svn } 8491ae349f5Scvs2svn plen -= length; 8501ae349f5Scvs2svn cp += length; 8511ae349f5Scvs2svn } 8521ae349f5Scvs2svn } 8531ae349f5Scvs2svn 8541ae349f5Scvs2svn void 8555828db6dSBrian Somers IpcpInput(struct ipcp *ipcp, struct mbuf * bp) 8561ae349f5Scvs2svn { 8577308ec68SBrian Somers /* Got PROTO_IPCP from link */ 8585828db6dSBrian Somers FsmInput(&ipcp->fsm, bp); 8591ae349f5Scvs2svn } 8601ae349f5Scvs2svn 8611ae349f5Scvs2svn int 8627a6f8720SBrian Somers UseHisaddr(struct bundle *bundle, const char *hisaddr, int setaddr) 8631ae349f5Scvs2svn { 8645828db6dSBrian Somers struct ipcp *ipcp = &bundle->ncp.ipcp; 8655828db6dSBrian Somers 8667308ec68SBrian Somers /* Use `hisaddr' for the peers address (set iface if `setaddr') */ 8675828db6dSBrian Somers memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range); 8685828db6dSBrian Somers iplist_reset(&ipcp->cfg.peer_list); 8691ae349f5Scvs2svn if (strpbrk(hisaddr, ",-")) { 8705828db6dSBrian Somers iplist_setsrc(&ipcp->cfg.peer_list, hisaddr); 8715828db6dSBrian Somers if (iplist_isvalid(&ipcp->cfg.peer_list)) { 8725828db6dSBrian Somers iplist_setrandpos(&ipcp->cfg.peer_list); 87330c2f2ffSBrian Somers ipcp->peer_ip = ChooseHisAddr(bundle, ipcp->my_ip); 8745828db6dSBrian Somers if (ipcp->peer_ip.s_addr == INADDR_ANY) { 8755828db6dSBrian Somers LogPrintf(LogWARN, "%s: None available !\n", 8765828db6dSBrian Somers ipcp->cfg.peer_list.src); 8771ae349f5Scvs2svn return(0); 8781ae349f5Scvs2svn } 8795828db6dSBrian Somers ipcp->cfg.peer_range.ipaddr.s_addr = ipcp->peer_ip.s_addr; 8805828db6dSBrian Somers ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST; 8815828db6dSBrian Somers ipcp->cfg.peer_range.width = 32; 8821ae349f5Scvs2svn } else { 8831ae349f5Scvs2svn LogPrintf(LogWARN, "%s: Invalid range !\n", hisaddr); 8841ae349f5Scvs2svn return 0; 8851ae349f5Scvs2svn } 8865828db6dSBrian Somers } else if (ParseAddr(ipcp, 1, &hisaddr, &ipcp->cfg.peer_range.ipaddr, 8875828db6dSBrian Somers &ipcp->cfg.peer_range.mask, 8885828db6dSBrian Somers &ipcp->cfg.peer_range.width) != 0) { 8895828db6dSBrian Somers ipcp->peer_ip.s_addr = ipcp->cfg.peer_range.ipaddr.s_addr; 8901ae349f5Scvs2svn 89130c2f2ffSBrian Somers if (setaddr && ipcp_SetIPaddress(bundle, ipcp->cfg.my_range.ipaddr, 89230c2f2ffSBrian Somers ipcp->cfg.peer_range.ipaddr, 0) < 0) { 8935828db6dSBrian Somers ipcp->cfg.my_range.ipaddr.s_addr = INADDR_ANY; 8945828db6dSBrian Somers ipcp->cfg.peer_range.ipaddr.s_addr = INADDR_ANY; 8951ae349f5Scvs2svn return 0; 8961ae349f5Scvs2svn } 8971ae349f5Scvs2svn } else 8981ae349f5Scvs2svn return 0; 8991ae349f5Scvs2svn 9001ae349f5Scvs2svn return 1; 9011ae349f5Scvs2svn } 902