summaryrefslogtreecommitdiffstats
path: root/usr.sbin/ppp/ipcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/ppp/ipcp.c')
-rw-r--r--usr.sbin/ppp/ipcp.c601
1 files changed, 276 insertions, 325 deletions
diff --git a/usr.sbin/ppp/ipcp.c b/usr.sbin/ppp/ipcp.c
index 031b9b0..bbed046 100644
--- a/usr.sbin/ppp/ipcp.c
+++ b/usr.sbin/ppp/ipcp.c
@@ -71,6 +71,8 @@
#include "lqr.h"
#include "hdlc.h"
#include "lcp.h"
+#include "ncpaddr.h"
+#include "ip.h"
#include "ipcp.h"
#include "filter.h"
#include "descriptor.h"
@@ -83,6 +85,8 @@
#ifndef NORADIUS
#include "radius.h"
#endif
+#include "ipv6cp.h"
+#include "ncp.h"
#include "bundle.h"
#include "id.h"
#include "arp.h"
@@ -90,101 +94,12 @@
#include "prompt.h"
#include "route.h"
#include "iface.h"
-#include "ip.h"
#undef REJECTED
#define REJECTED(p, x) ((p)->peer_reject & (1<<(x)))
#define issep(ch) ((ch) == ' ' || (ch) == '\t')
#define isip(ch) (((ch) >= '0' && (ch) <= '9') || (ch) == '.')
-static u_short default_urgent_tcp_ports[] = {
- 21, /* ftp */
- 22, /* ssh */
- 23, /* telnet */
- 513, /* login */
- 514, /* shell */
- 543, /* klogin */
- 544 /* kshell */
-};
-
-static u_short default_urgent_udp_ports[] = { };
-
-#define NDEFTCPPORTS \
- (sizeof default_urgent_tcp_ports / sizeof default_urgent_tcp_ports[0])
-#define NDEFUDPPORTS \
- (sizeof default_urgent_udp_ports / sizeof default_urgent_udp_ports[0])
-
-int
-ipcp_IsUrgentPort(struct port_range *range, u_short src, u_short dst)
-{
- int f;
-
- for (f = 0; f < range->nports; f++)
- if (range->port[f] == src || range->port[f] == dst)
- return 1;
-
- return 0;
-}
-
-void
-ipcp_AddUrgentPort(struct port_range *range, u_short port)
-{
- u_short *newport;
- int p;
-
- if (range->nports == range->maxports) {
- range->maxports += 10;
- newport = (u_short *)realloc(range->port,
- range->maxports * sizeof(u_short));
- if (newport == NULL) {
- log_Printf(LogERROR, "ipcp_AddUrgentPort: realloc: %s\n",
- strerror(errno));
- range->maxports -= 10;
- return;
- }
- range->port = newport;
- }
-
- for (p = 0; p < range->nports; p++)
- if (range->port[p] == port) {
- log_Printf(LogWARN, "%u: Port already set to urgent\n", port);
- break;
- } else if (range->port[p] > port) {
- memmove(range->port + p + 1, range->port + p,
- (range->nports - p) * sizeof(u_short));
- range->port[p] = port;
- range->nports++;
- break;
- }
-
- if (p == range->nports)
- range->port[range->nports++] = port;
-}
-
-void
-ipcp_RemoveUrgentPort(struct port_range *range, u_short port)
-{
- int p;
-
- for (p = 0; p < range->nports; p++)
- if (range->port[p] == port) {
- if (p != range->nports - 1)
- memmove(range->port + p, range->port + p + 1,
- (range->nports - p - 1) * sizeof(u_short));
- range->nports--;
- return;
- }
-
- if (p == range->nports)
- log_Printf(LogWARN, "%u: Port not set to urgent\n", port);
-}
-
-void
-ipcp_ClearUrgentPorts(struct port_range *range)
-{
- range->nports = 0;
-}
-
struct compreq {
u_short proto;
u_char slots;
@@ -327,7 +242,7 @@ ipcp_LoadDNS(struct ipcp *ipcp)
ch = *ncp;
*ncp = '\0';
- if (n < 2 && inet_aton(cp, ipcp->ns.dns + n))
+ if (n < 2 && inet_aton(cp, ipcp->ns.dns))
n++;
*ncp = ch;
@@ -344,7 +259,7 @@ ipcp_LoadDNS(struct ipcp *ipcp)
ipcp->ns.dns[0].s_addr = ipcp->ns.dns[1].s_addr;
ipcp->ns.dns[1].s_addr = INADDR_ANY;
}
- bundle_AdjustDNS(ipcp->fsm.bundle, ipcp->ns.dns);
+ bundle_AdjustDNS(ipcp->fsm.bundle);
}
} else
log_Printf(LogERROR, "Failed to stat opened %s: %s\n",
@@ -431,7 +346,6 @@ int
ipcp_Show(struct cmdargs const *arg)
{
struct ipcp *ipcp = &arg->bundle->ncp.ipcp;
- int p;
prompt_Printf(arg->prompt, "%s [%s]\n", ipcp->fsm.name,
State2Nam(ipcp->fsm.state));
@@ -441,12 +355,7 @@ ipcp_Show(struct cmdargs const *arg)
prompt_Printf(arg->prompt, " My side: %s, %s\n",
inet_ntoa(ipcp->my_ip), vj2asc(ipcp->my_compproto));
prompt_Printf(arg->prompt, " Queued packets: %lu\n",
- (unsigned long)ip_QueueLen(ipcp));
- }
-
- if (ipcp->route) {
- prompt_Printf(arg->prompt, "\n");
- route_ShowSticky(arg->prompt, ipcp->route, "Sticky routes", 1);
+ (unsigned long)ipcp_QueueLen(ipcp));
}
prompt_Printf(arg->prompt, "\nDefaults:\n");
@@ -454,9 +363,8 @@ ipcp_Show(struct cmdargs const *arg)
" REQ%s, %u Term REQ%s\n", ipcp->cfg.fsm.timeout,
ipcp->cfg.fsm.maxreq, ipcp->cfg.fsm.maxreq == 1 ? "" : "s",
ipcp->cfg.fsm.maxtrm, ipcp->cfg.fsm.maxtrm == 1 ? "" : "s");
- prompt_Printf(arg->prompt, " My Address: %s/%d",
- inet_ntoa(ipcp->cfg.my_range.ipaddr), ipcp->cfg.my_range.width);
- prompt_Printf(arg->prompt, ", netmask %s\n", inet_ntoa(ipcp->cfg.netmask));
+ prompt_Printf(arg->prompt, " My Address: %s\n",
+ ncprange_ntoa(&ipcp->cfg.my_range));
if (ipcp->cfg.HaveTriggerAddress)
prompt_Printf(arg->prompt, " Trigger address: %s\n",
inet_ntoa(ipcp->cfg.TriggerAddress));
@@ -469,15 +377,15 @@ ipcp_Show(struct cmdargs const *arg)
prompt_Printf(arg->prompt, " His Address: %s\n",
ipcp->cfg.peer_list.src);
else
- prompt_Printf(arg->prompt, " His Address: %s/%d\n",
- inet_ntoa(ipcp->cfg.peer_range.ipaddr),
- ipcp->cfg.peer_range.width);
+ prompt_Printf(arg->prompt, " His Address: %s\n",
+ ncprange_ntoa(&ipcp->cfg.peer_range));
prompt_Printf(arg->prompt, " DNS: %s",
ipcp->cfg.ns.dns[0].s_addr == INADDR_NONE ?
"none" : inet_ntoa(ipcp->cfg.ns.dns[0]));
if (ipcp->cfg.ns.dns[1].s_addr != INADDR_NONE)
- prompt_Printf(arg->prompt, ", %s", inet_ntoa(ipcp->cfg.ns.dns[1]));
+ prompt_Printf(arg->prompt, ", %s",
+ inet_ntoa(ipcp->cfg.ns.dns[1]));
prompt_Printf(arg->prompt, ", %s\n",
command_ShowNegval(ipcp->cfg.ns.dns_neg));
prompt_Printf(arg->prompt, " Resolver DNS: %s",
@@ -485,32 +393,12 @@ ipcp_Show(struct cmdargs const *arg)
"none" : inet_ntoa(ipcp->ns.dns[0]));
if (ipcp->ns.dns[1].s_addr != INADDR_NONE &&
ipcp->ns.dns[1].s_addr != ipcp->ns.dns[0].s_addr)
- prompt_Printf(arg->prompt, ", %s", inet_ntoa(ipcp->ns.dns[1]));
+ prompt_Printf(arg->prompt, ", %s",
+ inet_ntoa(ipcp->ns.dns[1]));
prompt_Printf(arg->prompt, "\n NetBIOS NS: %s, ",
inet_ntoa(ipcp->cfg.ns.nbns[0]));
- prompt_Printf(arg->prompt, "%s\n", inet_ntoa(ipcp->cfg.ns.nbns[1]));
-
- prompt_Printf(arg->prompt, " Urgent ports\n");
- prompt_Printf(arg->prompt, " TCP: ");
- if (ipcp->cfg.urgent.tcp.nports == 0)
- prompt_Printf(arg->prompt, "none");
- else
- for (p = 0; p < ipcp->cfg.urgent.tcp.nports; p++) {
- if (p)
- prompt_Printf(arg->prompt, ", ");
- prompt_Printf(arg->prompt, "%u", ipcp->cfg.urgent.tcp.port[p]);
- }
- prompt_Printf(arg->prompt, "\n UDP: ");
- if (ipcp->cfg.urgent.udp.nports == 0)
- prompt_Printf(arg->prompt, "none");
- else
- for (p = 0; p < ipcp->cfg.urgent.udp.nports; p++) {
- if (p)
- prompt_Printf(arg->prompt, ", ");
- prompt_Printf(arg->prompt, "%u", ipcp->cfg.urgent.udp.port[p]);
- }
- prompt_Printf(arg->prompt, "\n TOS: %s\n\n",
- ipcp->cfg.urgent.tos ? "yes" : "no");
+ prompt_Printf(arg->prompt, "%s\n",
+ inet_ntoa(ipcp->cfg.ns.nbns[1]));
throughput_disp(&ipcp->throughput, arg->prompt);
@@ -547,6 +435,7 @@ ipcp_Init(struct ipcp *ipcp, struct bundle *bundle, struct link *l,
const struct fsm_parent *parent)
{
struct hostent *hp;
+ struct in_addr host;
char name[MAXHOSTNAMELEN];
static const char * const timer_names[] =
{"IPCP restart", "IPCP openmode", "IPCP stopped"};
@@ -554,17 +443,20 @@ ipcp_Init(struct ipcp *ipcp, struct bundle *bundle, struct link *l,
fsm_Init(&ipcp->fsm, "IPCP", PROTO_IPCP, 1, IPCP_MAXCODE, LogIPCP,
bundle, l, parent, &ipcp_Callbacks, timer_names);
- ipcp->route = NULL;
ipcp->cfg.vj.slots = DEF_VJ_STATES;
ipcp->cfg.vj.slotcomp = 1;
memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range);
+
+ host.s_addr = htonl(INADDR_LOOPBACK);
+ ipcp->cfg.netmask.s_addr = INADDR_ANY;
if (gethostname(name, sizeof name) == 0) {
hp = gethostbyname(name);
- if (hp && hp->h_addrtype == AF_INET)
- memcpy(&ipcp->cfg.my_range.ipaddr.s_addr, hp->h_addr, hp->h_length);
+ if (hp && hp->h_addrtype == AF_INET && hp->h_length == sizeof host.s_addr)
+ memcpy(&host.s_addr, hp->h_addr, sizeof host.s_addr);
}
- ipcp->cfg.netmask.s_addr = INADDR_ANY;
- memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range);
+ ncprange_setip4(&ipcp->cfg.my_range, host, ipcp->cfg.netmask);
+ ncprange_setip4(&ipcp->cfg.peer_range, ipcp->cfg.netmask, ipcp->cfg.netmask);
+
iplist_setsrc(&ipcp->cfg.peer_list, "");
ipcp->cfg.HaveTriggerAddress = 0;
@@ -574,17 +466,6 @@ ipcp_Init(struct ipcp *ipcp, struct bundle *bundle, struct link *l,
ipcp->cfg.ns.nbns[0].s_addr = INADDR_ANY;
ipcp->cfg.ns.nbns[1].s_addr = INADDR_ANY;
- ipcp->cfg.urgent.tcp.nports = ipcp->cfg.urgent.tcp.maxports = NDEFTCPPORTS;
- ipcp->cfg.urgent.tcp.port = (u_short *)malloc(NDEFTCPPORTS * sizeof(u_short));
- memcpy(ipcp->cfg.urgent.tcp.port, default_urgent_tcp_ports,
- NDEFTCPPORTS * sizeof(u_short));
- ipcp->cfg.urgent.tos = 1;
-
- ipcp->cfg.urgent.udp.nports = ipcp->cfg.urgent.udp.maxports = NDEFUDPPORTS;
- ipcp->cfg.urgent.udp.port = (u_short *)malloc(NDEFUDPPORTS * sizeof(u_short));
- memcpy(ipcp->cfg.urgent.udp.port, default_urgent_udp_ports,
- NDEFUDPPORTS * sizeof(u_short));
-
ipcp->cfg.fsm.timeout = DEF_FSMRETRY;
ipcp->cfg.fsm.maxreq = DEF_FSMTRIES;
ipcp->cfg.fsm.maxtrm = DEF_FSMTRIES;
@@ -605,16 +486,8 @@ ipcp_Init(struct ipcp *ipcp, struct bundle *bundle, struct link *l,
void
ipcp_Destroy(struct ipcp *ipcp)
{
- if (ipcp->cfg.urgent.tcp.maxports) {
- ipcp->cfg.urgent.tcp.nports = ipcp->cfg.urgent.tcp.maxports = 0;
- free(ipcp->cfg.urgent.tcp.port);
- ipcp->cfg.urgent.tcp.port = NULL;
- }
- if (ipcp->cfg.urgent.udp.maxports) {
- ipcp->cfg.urgent.udp.nports = ipcp->cfg.urgent.udp.maxports = 0;
- free(ipcp->cfg.urgent.udp.port);
- ipcp->cfg.urgent.udp.port = NULL;
- }
+ throughput_destroy(&ipcp->throughput);
+
if (ipcp->ns.resolv != NULL) {
free(ipcp->ns.resolv);
ipcp->ns.resolv = NULL;
@@ -635,6 +508,8 @@ void
ipcp_Setup(struct ipcp *ipcp, u_int32_t mask)
{
struct iface *iface = ipcp->fsm.bundle->iface;
+ struct ncpaddr ipaddr;
+ struct in_addr peer;
int pos, n;
ipcp->fsm.open_mode = 0;
@@ -642,25 +517,24 @@ ipcp_Setup(struct ipcp *ipcp, u_int32_t mask)
if (iplist_isvalid(&ipcp->cfg.peer_list)) {
/* Try to give the peer a previously configured IP address */
- for (n = 0; n < iface->in_addrs; n++) {
- pos = iplist_ip2pos(&ipcp->cfg.peer_list, iface->in_addr[n].brd);
- if (pos != -1) {
- ipcp->cfg.peer_range.ipaddr =
- iplist_setcurpos(&ipcp->cfg.peer_list, pos);
+ for (n = 0; n < iface->addrs; n++) {
+ if (!ncpaddr_getip4(&iface->addr[n].peer, &peer))
+ continue;
+ if ((pos = iplist_ip2pos(&ipcp->cfg.peer_list, peer)) != -1) {
+ ncpaddr_setip4(&ipaddr, iplist_setcurpos(&ipcp->cfg.peer_list, pos));
break;
}
}
- if (n == iface->in_addrs)
+ if (n == iface->addrs)
/* Ok, so none of 'em fit.... pick a random one */
- ipcp->cfg.peer_range.ipaddr = iplist_setrandpos(&ipcp->cfg.peer_list);
+ ncpaddr_setip4(&ipaddr, iplist_setrandpos(&ipcp->cfg.peer_list));
- ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST;
- ipcp->cfg.peer_range.width = 32;
+ ncprange_sethost(&ipcp->cfg.peer_range, &ipaddr);
}
ipcp->heis1172 = 0;
ipcp->peer_req = 0;
- ipcp->peer_ip = ipcp->cfg.peer_range.ipaddr;
+ ncprange_getip4addr(&ipcp->cfg.peer_range, &ipcp->peer_ip);
ipcp->peer_compproto = 0;
if (ipcp->cfg.HaveTriggerAddress) {
@@ -677,17 +551,17 @@ ipcp_Setup(struct ipcp *ipcp, u_int32_t mask)
* Otherwise, if we've used an IP number before and it's still within
* the network specified on the ``set ifaddr'' line, we really
* want to keep that IP number so that we can keep any existing
- * connections that are bound to that IP (assuming we're not
- * ``iface-alias''ing).
+ * connections that are bound to that IP.
*/
- for (n = 0; n < iface->in_addrs; n++)
- if ((iface->in_addr[n].ifa.s_addr & ipcp->cfg.my_range.mask.s_addr) ==
- (ipcp->cfg.my_range.ipaddr.s_addr & ipcp->cfg.my_range.mask.s_addr)) {
- ipcp->my_ip = iface->in_addr[n].ifa;
+ for (n = 0; n < iface->addrs; n++) {
+ ncprange_getaddr(&iface->addr[n].ifa, &ipaddr);
+ if (ncprange_contains(&ipcp->cfg.my_range, &ipaddr)) {
+ ncpaddr_getip4(&ipaddr, &ipcp->my_ip);
break;
}
- if (n == iface->in_addrs)
- ipcp->my_ip = ipcp->cfg.my_range.ipaddr;
+ }
+ if (n == iface->addrs)
+ ncprange_getip4addr(&ipcp->cfg.my_range, &ipcp->my_ip);
}
if (IsEnabled(ipcp->cfg.vj.neg)
@@ -705,98 +579,121 @@ ipcp_Setup(struct ipcp *ipcp, u_int32_t mask)
ipcp->peer_reject = 0;
ipcp->my_reject = 0;
- /* Copy startup values into ipcp->dns? */
+ /* Copy startup values into ipcp->ns.dns */
if (ipcp->cfg.ns.dns[0].s_addr != INADDR_NONE)
- memcpy(ipcp->dns, ipcp->cfg.ns.dns, sizeof ipcp->dns);
- else if (ipcp->ns.dns[0].s_addr != INADDR_NONE)
- memcpy(ipcp->dns, ipcp->ns.dns, sizeof ipcp->dns);
- else
- ipcp->dns[0].s_addr = ipcp->dns[1].s_addr = INADDR_ANY;
+ memcpy(ipcp->ns.dns, ipcp->cfg.ns.dns, sizeof ipcp->ns.dns);
+}
+
+static int
+numaddresses(struct in_addr mask)
+{
+ u_int32_t bit, haddr;
+ int n;
+
+ haddr = ntohl(mask.s_addr);
+ bit = 1;
+ n = 1;
- if (ipcp->dns[1].s_addr == INADDR_NONE)
- ipcp->dns[1] = ipcp->dns[0];
+ do {
+ if (!(haddr & bit))
+ n <<= 1;
+ } while (bit <<= 1);
+
+ return n;
}
static int
-ipcp_doproxyall(struct bundle *bundle,
- int (*proxyfun)(struct bundle *, struct in_addr, int), int s)
+ipcp_proxyarp(struct ipcp *ipcp,
+ int (*proxyfun)(struct bundle *, struct in_addr, int),
+ const struct iface_addr *addr)
{
- int n, ret;
- struct sticky_route *rp;
- struct in_addr addr;
- struct ipcp *ipcp;
-
- ipcp = &bundle->ncp.ipcp;
- for (rp = ipcp->route; rp != NULL; rp = rp->next) {
- if (rp->mask.s_addr == INADDR_BROADCAST)
- continue;
- n = ntohl(INADDR_BROADCAST) - ntohl(rp->mask.s_addr) - 1;
- if (n > 0 && n <= 254 && rp->dst.s_addr != INADDR_ANY) {
- addr = rp->dst;
- while (n--) {
- addr.s_addr = htonl(ntohl(addr.s_addr) + 1);
- log_Printf(LogDEBUG, "ipcp_doproxyall: %s\n", inet_ntoa(addr));
- ret = (*proxyfun)(bundle, addr, s);
- if (!ret)
- return ret;
+ struct bundle *bundle = ipcp->fsm.bundle;
+ struct in_addr peer, mask, ip;
+ int n, ret, s;
+
+ if (!ncpaddr_getip4(&addr->peer, &peer)) {
+ log_Printf(LogERROR, "Oops, ipcp_proxyarp() called with unexpected addr\n");
+ return 0;
+ }
+
+ if ((s = ID0socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
+ log_Printf(LogERROR, "ipcp_proxyarp: socket: %s\n",
+ strerror(errno));
+ return 0;
+ }
+
+ ret = 0;
+
+ if (Enabled(bundle, OPT_PROXYALL)) {
+ ncprange_getip4mask(&addr->ifa, &mask);
+ if ((n = numaddresses(mask)) > 256) {
+ log_Printf(LogWARN, "%s: Too many addresses for proxyall\n",
+ ncprange_ntoa(&addr->ifa));
+ return 0;
+ }
+ ip.s_addr = peer.s_addr & mask.s_addr;
+ if (n >= 4) {
+ ip.s_addr = htonl(ntohl(ip.s_addr) + 1);
+ n -= 2;
+ }
+ while (n) {
+ if (!((ip.s_addr ^ peer.s_addr) & mask.s_addr)) {
+ if (!(ret = (*proxyfun)(bundle, ip, s)))
+ break;
+ n--;
}
+ ip.s_addr = htonl(ntohl(ip.s_addr) + 1);
}
- }
+ ret = !n;
+ } else if (Enabled(bundle, OPT_PROXY))
+ ret = (*proxyfun)(bundle, peer, s);
- return 0;
+ close(s);
+
+ return ret;
}
static int
-ipcp_SetIPaddress(struct bundle *bundle, struct in_addr myaddr,
- struct in_addr hisaddr, int silent)
+ipcp_SetIPaddress(struct ipcp *ipcp, struct in_addr myaddr,
+ struct in_addr hisaddr)
{
- struct in_addr mask, oaddr;
+ struct bundle *bundle = ipcp->fsm.bundle;
+ struct ncpaddr myncpaddr, hisncpaddr;
+ struct ncprange myrange, dst;
+ struct in_addr mask;
+
+ ncpaddr_setip4(&hisncpaddr, hisaddr);
+ ncpaddr_setip4(&myncpaddr, myaddr);
+ ncprange_sethost(&myrange, &myncpaddr);
mask = addr2mask(myaddr);
- if (bundle->ncp.ipcp.ifmask.s_addr != INADDR_ANY &&
- (bundle->ncp.ipcp.ifmask.s_addr & mask.s_addr) == mask.s_addr)
- mask.s_addr = bundle->ncp.ipcp.ifmask.s_addr;
+ if (ipcp->ifmask.s_addr != INADDR_ANY &&
+ (ipcp->ifmask.s_addr & mask.s_addr) == mask.s_addr)
+ ncprange_setip4mask(&myrange, ipcp->ifmask);
- oaddr.s_addr = bundle->iface->in_addrs ?
- bundle->iface->in_addr[0].ifa.s_addr : INADDR_ANY;
- if (!iface_inAdd(bundle->iface, myaddr, mask, hisaddr,
- IFACE_ADD_FIRST|IFACE_FORCE_ADD))
- return -1;
+ if (!iface_Add(bundle->iface, &bundle->ncp, &myrange, &hisncpaddr,
+ IFACE_ADD_FIRST|IFACE_FORCE_ADD|IFACE_SYSTEM))
+ return 0;
- if (!Enabled(bundle, OPT_IFACEALIAS) && bundle->iface->in_addrs > 1
- && myaddr.s_addr != oaddr.s_addr)
- /* Nuke the old one */
- iface_inDelete(bundle->iface, oaddr);
+ if (!Enabled(bundle, OPT_IFACEALIAS))
+ iface_Clear(bundle->iface, &bundle->ncp, AF_INET,
+ IFACE_CLEAR_ALIASES|IFACE_SYSTEM);
- if (bundle->ncp.ipcp.cfg.sendpipe > 0 || bundle->ncp.ipcp.cfg.recvpipe > 0)
- rt_Update(bundle, hisaddr, myaddr);
+ if (bundle->ncp.cfg.sendpipe > 0 || bundle->ncp.cfg.recvpipe > 0) {
+ ncprange_sethost(&dst, &hisncpaddr);
+ rt_Update(bundle, &dst);
+ }
if (Enabled(bundle, OPT_SROUTES))
- route_Change(bundle, bundle->ncp.ipcp.route, myaddr, hisaddr,
- bundle->ncp.ipcp.ns.dns);
+ route_Change(bundle, bundle->ncp.route, &myncpaddr, &hisncpaddr);
#ifndef NORADIUS
if (bundle->radius.valid)
- route_Change(bundle, bundle->radius.routes, myaddr, hisaddr,
- bundle->ncp.ipcp.ns.dns);
+ route_Change(bundle, bundle->radius.routes, &myncpaddr, &hisncpaddr);
#endif
- if (Enabled(bundle, OPT_PROXY) || Enabled(bundle, OPT_PROXYALL)) {
- int s = ID0socket(AF_INET, SOCK_DGRAM, 0);
- if (s < 0)
- log_Printf(LogERROR, "ipcp_SetIPaddress: socket(): %s\n",
- strerror(errno));
- else {
- if (Enabled(bundle, OPT_PROXYALL))
- ipcp_doproxyall(bundle, arp_SetProxy, s);
- else if (Enabled(bundle, OPT_PROXY))
- arp_SetProxy(bundle, hisaddr, s);
- close(s);
- }
- }
-
- return 0;
+ return 1; /* Ok */
}
static struct in_addr
@@ -809,7 +706,7 @@ ChooseHisAddr(struct bundle *bundle, struct in_addr gw)
try = iplist_next(&bundle->ncp.ipcp.cfg.peer_list);
log_Printf(LogDEBUG, "ChooseHisAddr: Check item %ld (%s)\n",
f, inet_ntoa(try));
- if (ipcp_SetIPaddress(bundle, gw, try, 1) == 0) {
+ if (ipcp_SetIPaddress(&bundle->ncp.ipcp, gw, try)) {
log_Printf(LogIPCP, "Selected IP address %s\n", inet_ntoa(try));
break;
}
@@ -876,16 +773,16 @@ IpcpSendConfigReq(struct fsm *fp)
}
}
- if (IsEnabled(ipcp->cfg.ns.dns_neg) &&
- !REJECTED(ipcp, TY_PRIMARY_DNS - TY_ADJUST_NS)) {
- memcpy(o->data, &ipcp->dns[0].s_addr, 4);
- INC_LCP_OPT(TY_PRIMARY_DNS, 6, o);
- }
+ if (IsEnabled(ipcp->cfg.ns.dns_neg)) {
+ if (!REJECTED(ipcp, TY_PRIMARY_DNS - TY_ADJUST_NS)) {
+ memcpy(o->data, &ipcp->ns.dns[0].s_addr, 4);
+ INC_LCP_OPT(TY_PRIMARY_DNS, 6, o);
+ }
- if (IsEnabled(ipcp->cfg.ns.dns_neg) &&
- !REJECTED(ipcp, TY_SECONDARY_DNS - TY_ADJUST_NS)) {
- memcpy(o->data, &ipcp->dns[1].s_addr, 4);
- INC_LCP_OPT(TY_SECONDARY_DNS, 6, o);
+ if (!REJECTED(ipcp, TY_SECONDARY_DNS - TY_ADJUST_NS)) {
+ memcpy(o->data, &ipcp->ns.dns[1].s_addr, 4);
+ INC_LCP_OPT(TY_SECONDARY_DNS, 6, o);
+ }
}
fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff,
@@ -929,43 +826,41 @@ IpcpLayerFinish(struct fsm *fp)
throughput_log(&ipcp->throughput, LogIPCP, NULL);
}
+/*
+ * Called from iface_Add() via ncp_IfaceAddrAdded()
+ */
void
-ipcp_CleanInterface(struct ipcp *ipcp)
+ipcp_IfaceAddrAdded(struct ipcp *ipcp, const struct iface_addr *addr)
{
- struct iface *iface = ipcp->fsm.bundle->iface;
+ struct bundle *bundle = ipcp->fsm.bundle;
- if (iface->in_addrs && (Enabled(ipcp->fsm.bundle, OPT_PROXY) ||
- Enabled(ipcp->fsm.bundle, OPT_PROXYALL))) {
- int s = ID0socket(AF_INET, SOCK_DGRAM, 0);
- if (s < 0)
- log_Printf(LogERROR, "ipcp_CleanInterface: socket: %s\n",
- strerror(errno));
- else {
- if (Enabled(ipcp->fsm.bundle, OPT_PROXYALL))
- ipcp_doproxyall(ipcp->fsm.bundle, arp_ClearProxy, s);
- else if (Enabled(ipcp->fsm.bundle, OPT_PROXY))
- arp_ClearProxy(ipcp->fsm.bundle, iface->in_addr[0].brd, s);
- close(s);
- }
- }
+ if (Enabled(bundle, OPT_PROXY) || Enabled(bundle, OPT_PROXYALL))
+ ipcp_proxyarp(ipcp, arp_SetProxy, addr);
+}
- iface_inClear(ipcp->fsm.bundle->iface, IFACE_CLEAR_ALL);
+/*
+ * Called from iface_Clear() and iface_Delete() via ncp_IfaceAddrDeleted()
+ */
+void
+ipcp_IfaceAddrDeleted(struct ipcp *ipcp, const struct iface_addr *addr)
+{
+ struct bundle *bundle = ipcp->fsm.bundle;
+
+ if (Enabled(bundle, OPT_PROXY) || Enabled(bundle, OPT_PROXYALL))
+ ipcp_proxyarp(ipcp, arp_ClearProxy, addr);
}
static void
IpcpLayerDown(struct fsm *fp)
{
/* About to come down */
- static int recursing;
struct ipcp *ipcp = fsm2ipcp(fp);
- const char *s;
+ static int recursing;
+ char addr[16];
if (!recursing++) {
- if (ipcp->fsm.bundle->iface->in_addrs)
- s = inet_ntoa(ipcp->fsm.bundle->iface->in_addr[0].ifa);
- else
- s = "Interface configuration error !";
- log_Printf(LogIPCP, "%s: LayerDown: %s\n", fp->link->name, s);
+ snprintf(addr, sizeof addr, "%s", inet_ntoa(ipcp->my_ip));
+ log_Printf(LogIPCP, "%s: LayerDown: %s\n", fp->link->name, addr);
#ifndef NORADIUS
radius_Account(&fp->bundle->radius, &fp->bundle->radacct,
@@ -977,7 +872,7 @@ IpcpLayerDown(struct fsm *fp)
* XXX this stuff should really live in the FSM. Our config should
* associate executable sections in files with events.
*/
- if (system_Select(fp->bundle, s, LINKDOWNFILE, NULL, NULL) < 0) {
+ if (system_Select(fp->bundle, addr, LINKDOWNFILE, NULL, NULL) < 0) {
if (bundle_GetLabel(fp->bundle)) {
if (system_Select(fp->bundle, bundle_GetLabel(fp->bundle),
LINKDOWNFILE, NULL, NULL) < 0)
@@ -994,7 +889,7 @@ IpcpLayerDown(struct fsm *fp)
int
ipcp_InterfaceUp(struct ipcp *ipcp)
{
- if (ipcp_SetIPaddress(ipcp->fsm.bundle, ipcp->my_ip, ipcp->peer_ip, 0) < 0) {
+ if (!ipcp_SetIPaddress(ipcp, ipcp->my_ip, ipcp->peer_ip)) {
log_Printf(LogERROR, "ipcp_InterfaceUp: unable to set ip address\n");
return 0;
}
@@ -1055,25 +950,19 @@ IpcpLayerUp(struct fsm *fp)
return 1;
}
-static int
-AcceptableAddr(const struct in_range *prange, struct in_addr ipaddr)
-{
- /* Is the given IP in the given range ? */
- return (prange->ipaddr.s_addr & prange->mask.s_addr) ==
- (ipaddr.s_addr & prange->mask.s_addr) && ipaddr.s_addr;
-}
-
static void
ipcp_ValidateReq(struct ipcp *ipcp, struct in_addr ip, struct fsm_decode *dec)
{
struct bundle *bundle = ipcp->fsm.bundle;
struct iface *iface = bundle->iface;
+ struct in_addr myaddr, peer;
int n;
if (iplist_isvalid(&ipcp->cfg.peer_list)) {
+ ncprange_getip4addr(&ipcp->cfg.my_range, &myaddr);
if (ip.s_addr == INADDR_ANY ||
iplist_ip2pos(&ipcp->cfg.peer_list, ip) < 0 ||
- ipcp_SetIPaddress(bundle, ipcp->cfg.my_range.ipaddr, ip, 1)) {
+ !ipcp_SetIPaddress(ipcp, myaddr, ip)) {
log_Printf(LogIPCP, "%s: Address invalid or already in use\n",
inet_ntoa(ip));
/*
@@ -1081,15 +970,19 @@ ipcp_ValidateReq(struct ipcp *ipcp, struct in_addr ip, struct fsm_decode *dec)
* try NAKing with that so that we don't have to upset things
* too much.
*/
- for (n = 0; n < iface->in_addrs; n++)
- if (iplist_ip2pos(&ipcp->cfg.peer_list, iface->in_addr[n].brd) >= 0) {
- ipcp->peer_ip = iface->in_addr[n].brd;
+ for (n = 0; n < iface->addrs; n++) {
+ if (!ncpaddr_getip4(&iface->addr[n].peer, &peer))
+ continue;
+ if (iplist_ip2pos(&ipcp->cfg.peer_list, peer) >= 0) {
+ ipcp->peer_ip = peer;
break;
}
+ }
- if (n == iface->in_addrs)
+ if (n == iface->addrs) {
/* Just pick an IP number from our list */
- ipcp->peer_ip = ChooseHisAddr(bundle, ipcp->cfg.my_range.ipaddr);
+ ipcp->peer_ip = ChooseHisAddr(bundle, myaddr);
+ }
if (ipcp->peer_ip.s_addr == INADDR_ANY) {
*dec->rejend++ = TY_IPADDR;
@@ -1104,23 +997,21 @@ ipcp_ValidateReq(struct ipcp *ipcp, struct in_addr ip, struct fsm_decode *dec)
}
return;
}
- } else if (!AcceptableAddr(&ipcp->cfg.peer_range, ip)) {
+ } else if (!ncprange_containsip4(&ipcp->cfg.peer_range, ip)) {
/*
* If the destination address is not acceptable, NAK with what we
* want to use.
*/
*dec->nakend++ = TY_IPADDR;
*dec->nakend++ = 6;
- for (n = 0; n < iface->in_addrs; n++)
- if ((iface->in_addr[n].brd.s_addr & ipcp->cfg.peer_range.mask.s_addr)
- == (ipcp->cfg.peer_range.ipaddr.s_addr &
- ipcp->cfg.peer_range.mask.s_addr)) {
+ for (n = 0; n < iface->addrs; n++)
+ if (ncprange_contains(&ipcp->cfg.peer_range, &iface->addr[n].peer)) {
/* We prefer the already-configured address */
- memcpy(dec->nakend, &iface->in_addr[n].brd.s_addr, 4);
+ ncpaddr_getip4addr(&iface->addr[n].peer, (u_int32_t *)dec->nakend);
break;
}
- if (n == iface->in_addrs)
+ if (n == iface->addrs)
memcpy(dec->nakend, &ipcp->peer_ip.s_addr, 4);
dec->nakend += 4;
@@ -1139,6 +1030,7 @@ IpcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type,
struct fsm_decode *dec)
{
/* Deal with incoming PROTO_IPCP */
+ struct ncpaddr ncpaddr;
struct ipcp *ipcp = fsm2ipcp(fp);
int type, length, gotdnsnak;
u_int32_t compproto;
@@ -1171,13 +1063,14 @@ IpcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type,
break;
case MODE_NAK:
- if (AcceptableAddr(&ipcp->cfg.my_range, ipaddr)) {
+ if (ncprange_containsip4(&ipcp->cfg.my_range, ipaddr)) {
/* Use address suggested by peer */
snprintf(tbuff2, sizeof tbuff2, "%s changing address: %s ", tbuff,
inet_ntoa(ipcp->my_ip));
log_Printf(LogIPCP, "%s --> %s\n", tbuff2, inet_ntoa(ipaddr));
ipcp->my_ip = ipaddr;
- bundle_AdjustFilters(fp->bundle, &ipcp->my_ip, NULL);
+ ncpaddr_setip4(&ncpaddr, ipcp->my_ip);
+ bundle_AdjustFilters(fp->bundle, &ncpaddr, NULL);
} else {
log_Printf(log_IsKept(LogIPCP) ? LogIPCP : LogPHASE,
"%s: Unacceptable address!\n", inet_ntoa(ipaddr));
@@ -1307,14 +1200,14 @@ IpcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type,
dec->rejend += length;
break;
}
- have_ip = ipcp->dns[type == TY_PRIMARY_DNS ? 0 : 1];
+ have_ip = ipcp->ns.dns[type == TY_PRIMARY_DNS ? 0 : 1];
if (type == TY_PRIMARY_DNS && ipaddr.s_addr != have_ip.s_addr &&
- ipaddr.s_addr == ipcp->dns[1].s_addr) {
+ ipaddr.s_addr == ipcp->ns.dns[1].s_addr) {
/* Swap 'em 'round */
- ipcp->dns[0] = ipcp->dns[1];
- ipcp->dns[1] = have_ip;
- have_ip = ipcp->dns[0];
+ ipcp->ns.dns[0] = ipcp->ns.dns[1];
+ ipcp->ns.dns[1] = have_ip;
+ have_ip = ipcp->ns.dns[0];
}
if (ipaddr.s_addr != have_ip.s_addr) {
@@ -1338,7 +1231,8 @@ IpcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type,
case MODE_NAK:
if (IsEnabled(ipcp->cfg.ns.dns_neg)) {
gotdnsnak = 1;
- memcpy(&ipcp->dns[type == TY_PRIMARY_DNS ? 0 : 1].s_addr, cp + 2, 4);
+ memcpy(&ipcp->ns.dns[type == TY_PRIMARY_DNS ? 0 : 1].s_addr,
+ cp + 2, 4);
}
break;
@@ -1399,17 +1293,16 @@ IpcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type,
}
if (gotdnsnak) {
- memcpy(ipcp->ns.dns, ipcp->dns, sizeof ipcp->ns.dns);
if (ipcp->ns.writable) {
log_Printf(LogDEBUG, "Updating resolver\n");
if (!ipcp_WriteDNS(ipcp)) {
ipcp->peer_reject |= (1 << (TY_PRIMARY_DNS - TY_ADJUST_NS));
ipcp->peer_reject |= (1 << (TY_SECONDARY_DNS - TY_ADJUST_NS));
} else
- bundle_AdjustDNS(fp->bundle, ipcp->dns);
+ bundle_AdjustDNS(fp->bundle);
} else {
log_Printf(LogDEBUG, "Not updating resolver (readonly)\n");
- bundle_AdjustDNS(fp->bundle, ipcp->dns);
+ bundle_AdjustDNS(fp->bundle);
}
}
@@ -1458,23 +1351,24 @@ int
ipcp_UseHisIPaddr(struct bundle *bundle, struct in_addr hisaddr)
{
struct ipcp *ipcp = &bundle->ncp.ipcp;
+ struct in_addr myaddr;
memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range);
iplist_reset(&ipcp->cfg.peer_list);
- ipcp->peer_ip = ipcp->cfg.peer_range.ipaddr = hisaddr;
- ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST;
- ipcp->cfg.peer_range.width = 32;
-
- if (ipcp_SetIPaddress(bundle, ipcp->cfg.my_range.ipaddr, hisaddr, 0) < 0)
- return 0;
+ ipcp->peer_ip = hisaddr;
+ ncprange_setip4host(&ipcp->cfg.peer_range, hisaddr);
+ ncprange_getip4addr(&ipcp->cfg.my_range, &myaddr);
- return 1; /* Ok */
+ return ipcp_SetIPaddress(ipcp, myaddr, hisaddr);
}
int
ipcp_UseHisaddr(struct bundle *bundle, const char *hisaddr, int setaddr)
{
- struct ipcp *ipcp = &bundle->ncp.ipcp;
+ struct in_addr myaddr;
+ struct ncp *ncp = &bundle->ncp;
+ struct ipcp *ipcp = &ncp->ipcp;
+ struct ncpaddr ncpaddr;
/* Use `hisaddr' for the peers address (set iface if `setaddr') */
memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range);
@@ -1488,25 +1382,26 @@ ipcp_UseHisaddr(struct bundle *bundle, const char *hisaddr, int setaddr)
log_Printf(LogWARN, "%s: None available !\n", ipcp->cfg.peer_list.src);
return 0;
}
- ipcp->cfg.peer_range.ipaddr.s_addr = ipcp->peer_ip.s_addr;
- ipcp->cfg.peer_range.mask.s_addr = INADDR_BROADCAST;
- ipcp->cfg.peer_range.width = 32;
+ ncprange_setip4host(&ipcp->cfg.peer_range, ipcp->peer_ip);
} else {
log_Printf(LogWARN, "%s: Invalid range !\n", hisaddr);
return 0;
}
- } else if (ParseAddr(ipcp, hisaddr, &ipcp->cfg.peer_range.ipaddr,
- &ipcp->cfg.peer_range.mask,
- &ipcp->cfg.peer_range.width) != 0) {
- ipcp->peer_ip.s_addr = ipcp->cfg.peer_range.ipaddr.s_addr;
+ } else if (ncprange_aton(&ipcp->cfg.peer_range, ncp, hisaddr) != 0) {
+ if (ncprange_family(&ipcp->cfg.my_range) != AF_INET) {
+ log_Printf(LogWARN, "%s: Not an AF_INET address !\n", hisaddr);
+ return 0;
+ }
+ ncprange_getip4addr(&ipcp->cfg.my_range, &myaddr);
+ ncprange_getip4addr(&ipcp->cfg.peer_range, &ipcp->peer_ip);
- if (setaddr && ipcp_SetIPaddress(bundle, ipcp->cfg.my_range.ipaddr,
- ipcp->cfg.peer_range.ipaddr, 0) < 0)
+ if (setaddr && !ipcp_SetIPaddress(ipcp, myaddr, ipcp->peer_ip))
return 0;
} else
return 0;
- bundle_AdjustFilters(bundle, NULL, &ipcp->peer_ip);
+ ncpaddr_setip4(&ncpaddr, ipcp->peer_ip);
+ bundle_AdjustFilters(bundle, NULL, &ncpaddr);
return 1; /* Ok */
}
@@ -1523,3 +1418,59 @@ addr2mask(struct in_addr addr)
return addr;
}
+
+size_t
+ipcp_QueueLen(struct ipcp *ipcp)
+{
+ struct mqueue *q;
+ size_t result;
+
+ result = 0;
+ for (q = ipcp->Queue; q < ipcp->Queue + IPCP_QUEUES(ipcp); q++)
+ result += q->len;
+
+ return result;
+}
+
+int
+ipcp_PushPacket(struct ipcp *ipcp, struct link *l)
+{
+ struct bundle *bundle = ipcp->fsm.bundle;
+ struct mqueue *queue;
+ struct mbuf *bp;
+ int m_len;
+ u_int32_t secs = 0;
+ unsigned alivesecs = 0;
+
+ if (ipcp->fsm.state != ST_OPENED)
+ return 0;
+
+ /*
+ * If ccp is not open but is required, do nothing.
+ */
+ if (l->ccp.fsm.state != ST_OPENED && ccp_Required(&l->ccp)) {
+ log_Printf(LogPHASE, "%s: Not transmitting... waiting for CCP\n", l->name);
+ return 0;
+ }
+
+ queue = ipcp->Queue + IPCP_QUEUES(ipcp) - 1;
+ do {
+ if (queue->top) {
+ bp = m_dequeue(queue);
+ bp = mbuf_Read(bp, &secs, sizeof secs);
+ bp = m_pullup(bp);
+ m_len = m_length(bp);
+ if (!FilterCheck(MBUF_CTOP(bp), AF_INET, &bundle->filter.alive,
+ &alivesecs)) {
+ if (secs == 0)
+ secs = alivesecs;
+ bundle_StartIdleTimer(bundle, secs);
+ }
+ link_PushPacket(l, bp, bundle, 0, PROTO_IP);
+ ipcp_AddOutOctets(ipcp, m_len);
+ return 1;
+ }
+ } while (queue-- != ipcp->Queue);
+
+ return 0;
+}
OpenPOWER on IntegriCloud