summaryrefslogtreecommitdiffstats
path: root/usr.sbin/ppp/ipcp.c
diff options
context:
space:
mode:
authorbrian <brian@FreeBSD.org>2001-08-14 16:05:52 +0000
committerbrian <brian@FreeBSD.org>2001-08-14 16:05:52 +0000
commitde3feff3f8839f8f26a69dfb7cd667332a8536dc (patch)
treeb09d46345a558a45e66b435c4386d76cf53405d3 /usr.sbin/ppp/ipcp.c
parentdbc6471fad42e595668d0f00254797ef89e618b0 (diff)
downloadFreeBSD-src-de3feff3f8839f8f26a69dfb7cd667332a8536dc.zip
FreeBSD-src-de3feff3f8839f8f26a69dfb7cd667332a8536dc.tar.gz
o Add ipv6 support, abstracting most NCP addresses into opaque
structures (well, they're treated as opaque). It's now possible to manage IPv6 interface addresses and routing table entries and to filter IPV6 traffic whether encapsulated or not. IPV6CP support is crude for now, and hasn't been tested against any other implementations. RADIUS and IPv6 are independent of eachother for now. ppp.linkup/ppp.linkdown aren't currently used by IPV6CP o Understand all protocols(5) in filter rules rather than only a select few. o Allow a mask specification for the ``delete'' command. It's now possible to specifically delete one of two conflicting routes. o When creating and deleting proxy arp entries, do it for all IPv4 interface addresses rather than doing it just for the ``current'' peer address. o When iface-alias isn't in effect, don't blow away manually (via ``iface add'') added interface addresses. o When listening on a tcp server (diagnostic) socket, bind so that a tcp46 socket is created -- allowing both IPv4 and IPv6 connections. o When displaying ICMP traffic, don't display the icmp type twice. When display traffic, display at least some information about unrecognised traffic. o Bump version Inspired after filtering work by: Makoto MATSUSHITA <matusita@jp.FreeBSD.org>
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