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>
This commit is contained in:
parent
135047c346
commit
30949fd4b5
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=81634
@ -4,10 +4,10 @@ PROG= ppp
|
||||
MAN= ppp.8
|
||||
SRCS= acf.c arp.c async.c auth.c bundle.c cbcp.c ccp.c chap.c chat.c \
|
||||
command.c datalink.c deflate.c defs.c exec.c filter.c fsm.c hdlc.c \
|
||||
iface.c ip.c ipcp.c iplist.c lcp.c link.c log.c lqr.c main.c \
|
||||
mbuf.c mp.c pap.c physical.c pred.c probe.c prompt.c proto.c route.c \
|
||||
server.c sig.c slcompress.c sync.c systems.c tcp.c tcpmss.c \
|
||||
throughput.c timer.c tty.c tun.c udp.c vjcomp.c
|
||||
iface.c ip.c ipcp.c ipv6cp.c iplist.c lcp.c link.c log.c lqr.c main.c \
|
||||
mbuf.c mp.c ncp.c ncpaddr.c pap.c physical.c pred.c probe.c prompt.c \
|
||||
proto.c route.c server.c sig.c slcompress.c sync.c systems.c tcp.c \
|
||||
tcpmss.c throughput.c timer.c tty.c tun.c udp.c vjcomp.c
|
||||
.if defined(NOSUID) || defined(PPP_NOSUID)
|
||||
BINMODE=554
|
||||
.else
|
||||
|
@ -57,13 +57,16 @@
|
||||
#include "slcompress.h"
|
||||
#include "lqr.h"
|
||||
#include "hdlc.h"
|
||||
#include "ncpaddr.h"
|
||||
#include "ipcp.h"
|
||||
#include "filter.h"
|
||||
#include "ipv6cp.h"
|
||||
#include "descriptor.h"
|
||||
#include "lcp.h"
|
||||
#include "ccp.h"
|
||||
#include "link.h"
|
||||
#include "mp.h"
|
||||
#include "ncp.h"
|
||||
#include "filter.h"
|
||||
#ifndef NORADIUS
|
||||
#include "radius.h"
|
||||
#endif
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <pwd.h>
|
||||
@ -51,6 +52,8 @@
|
||||
#include "slcompress.h"
|
||||
#include "lqr.h"
|
||||
#include "hdlc.h"
|
||||
#include "ncpaddr.h"
|
||||
#include "ip.h"
|
||||
#include "ipcp.h"
|
||||
#include "auth.h"
|
||||
#include "systems.h"
|
||||
@ -70,6 +73,8 @@
|
||||
#include "async.h"
|
||||
#include "physical.h"
|
||||
#include "datalink.h"
|
||||
#include "ipv6cp.h"
|
||||
#include "ncp.h"
|
||||
#include "bundle.h"
|
||||
|
||||
const char *
|
||||
|
@ -71,6 +71,8 @@
|
||||
#include "hdlc.h"
|
||||
#include "throughput.h"
|
||||
#include "slcompress.h"
|
||||
#include "ncpaddr.h"
|
||||
#include "ip.h"
|
||||
#include "ipcp.h"
|
||||
#include "filter.h"
|
||||
#include "descriptor.h"
|
||||
@ -82,6 +84,8 @@
|
||||
#ifndef NORADIUS
|
||||
#include "radius.h"
|
||||
#endif
|
||||
#include "ipv6cp.h"
|
||||
#include "ncp.h"
|
||||
#include "bundle.h"
|
||||
#include "async.h"
|
||||
#include "physical.h"
|
||||
@ -93,7 +97,6 @@
|
||||
#include "chat.h"
|
||||
#include "cbcp.h"
|
||||
#include "datalink.h"
|
||||
#include "ip.h"
|
||||
#include "iface.h"
|
||||
#include "server.h"
|
||||
#ifdef HAVE_DES
|
||||
@ -147,10 +150,13 @@ bundle_NewPhase(struct bundle *bundle, u_int new)
|
||||
break;
|
||||
|
||||
case PHASE_NETWORK:
|
||||
fsm_Up(&bundle->ncp.ipcp.fsm);
|
||||
fsm_Open(&bundle->ncp.ipcp.fsm);
|
||||
bundle->phase = new;
|
||||
log_DisplayPrompts();
|
||||
if (ncp_fsmStart(&bundle->ncp, bundle)) {
|
||||
bundle->phase = new;
|
||||
log_DisplayPrompts();
|
||||
} else {
|
||||
log_Printf(LogPHASE, "bundle: All NCPs are disabled\n");
|
||||
bundle_Close(bundle, NULL, CLOSE_STAYDOWN);
|
||||
}
|
||||
break;
|
||||
|
||||
case PHASE_TERMINATE:
|
||||
@ -214,8 +220,7 @@ bundle_ClearQueues(void *v)
|
||||
* dictionaries in use (causing the relevant RESET_REQ/RESET_ACK).
|
||||
*/
|
||||
|
||||
ip_DeleteQueue(&bundle->ncp.ipcp);
|
||||
mp_DeleteQueue(&bundle->ncp.mp);
|
||||
ncp_DeleteQueues(&bundle->ncp);
|
||||
for (dl = bundle->links; dl; dl = dl->next)
|
||||
physical_DeleteQueue(dl->physical);
|
||||
}
|
||||
@ -270,12 +275,14 @@ bundle_LayerUp(void *v, struct fsm *fp)
|
||||
|
||||
bundle_LinkAdded(bundle, p->dl);
|
||||
mp_CheckAutoloadTimer(&bundle->ncp.mp);
|
||||
} else if (fp->proto == PROTO_IPCP) {
|
||||
bundle_CalculateBandwidth(fp->bundle);
|
||||
time(&bundle->upat);
|
||||
bundle_StartIdleTimer(bundle, 0);
|
||||
} else if (isncp(fp->proto)) {
|
||||
if (ncp_LayersOpen(&fp->bundle->ncp) == 1) {
|
||||
bundle_CalculateBandwidth(fp->bundle);
|
||||
time(&bundle->upat);
|
||||
bundle_StartIdleTimer(bundle, 0);
|
||||
mp_CheckAutoloadTimer(&fp->bundle->ncp.mp);
|
||||
}
|
||||
bundle_Notify(bundle, EX_NORMAL);
|
||||
mp_CheckAutoloadTimer(&fp->bundle->ncp.mp);
|
||||
} else if (fp->proto == PROTO_CCP)
|
||||
bundle_CalculateBandwidth(fp->bundle); /* Against ccp_MTUOverhead */
|
||||
}
|
||||
@ -296,10 +303,12 @@ bundle_LayerDown(void *v, struct fsm *fp)
|
||||
|
||||
struct bundle *bundle = (struct bundle *)v;
|
||||
|
||||
if (fp->proto == PROTO_IPCP) {
|
||||
bundle_StopIdleTimer(bundle);
|
||||
bundle->upat = 0;
|
||||
mp_StopAutoloadTimer(&bundle->ncp.mp);
|
||||
if (isncp(fp->proto)) {
|
||||
if (ncp_LayersOpen(&fp->bundle->ncp) == 0) {
|
||||
bundle_StopIdleTimer(bundle);
|
||||
bundle->upat = 0;
|
||||
mp_StopAutoloadTimer(&bundle->ncp.mp);
|
||||
}
|
||||
} else if (fp->proto == PROTO_LCP) {
|
||||
struct datalink *dl;
|
||||
struct datalink *lost;
|
||||
@ -328,7 +337,7 @@ bundle_LayerDown(void *v, struct fsm *fp)
|
||||
|
||||
if (!others_active)
|
||||
/* Down the NCPs. We don't expect to get fsm_Close()d ourself ! */
|
||||
fsm2initial(&bundle->ncp.ipcp.fsm);
|
||||
ncp2initial(&bundle->ncp);
|
||||
}
|
||||
}
|
||||
|
||||
@ -343,7 +352,7 @@ bundle_LayerFinish(void *v, struct fsm *fp)
|
||||
struct bundle *bundle = (struct bundle *)v;
|
||||
struct datalink *dl;
|
||||
|
||||
if (fp->proto == PROTO_IPCP) {
|
||||
if (isncp(fp->proto) && !ncp_LayersUnfinished(&bundle->ncp)) {
|
||||
if (bundle_Phase(bundle) != PHASE_DEAD)
|
||||
bundle_NewPhase(bundle, PHASE_TERMINATE);
|
||||
for (dl = bundle->links; dl; dl = dl->next)
|
||||
@ -353,12 +362,6 @@ bundle_LayerFinish(void *v, struct fsm *fp)
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
bundle_LinkIsUp(const struct bundle *bundle)
|
||||
{
|
||||
return bundle->ncp.ipcp.fsm.state == ST_OPENED;
|
||||
}
|
||||
|
||||
void
|
||||
bundle_Close(struct bundle *bundle, const char *name, int how)
|
||||
{
|
||||
@ -398,11 +401,10 @@ bundle_Close(struct bundle *bundle, const char *name, int how)
|
||||
|
||||
if (!others_active) {
|
||||
bundle_StopIdleTimer(bundle);
|
||||
if (bundle->ncp.ipcp.fsm.state > ST_CLOSED ||
|
||||
bundle->ncp.ipcp.fsm.state == ST_STARTING)
|
||||
fsm_Close(&bundle->ncp.ipcp.fsm);
|
||||
if (ncp_LayersUnfinished(&bundle->ncp))
|
||||
ncp_Close(&bundle->ncp);
|
||||
else {
|
||||
fsm2initial(&bundle->ncp.ipcp.fsm);
|
||||
ncp2initial(&bundle->ncp);
|
||||
for (dl = bundle->links; dl; dl = dl->next)
|
||||
datalink_Close(dl, how);
|
||||
}
|
||||
@ -420,29 +422,6 @@ bundle_Down(struct bundle *bundle, int how)
|
||||
datalink_Down(dl, how);
|
||||
}
|
||||
|
||||
static size_t
|
||||
bundle_FillQueues(struct bundle *bundle)
|
||||
{
|
||||
size_t total;
|
||||
|
||||
if (bundle->ncp.mp.active)
|
||||
total = mp_FillQueues(bundle);
|
||||
else {
|
||||
struct datalink *dl;
|
||||
size_t add;
|
||||
|
||||
for (total = 0, dl = bundle->links; dl; dl = dl->next)
|
||||
if (dl->state == DATALINK_OPEN) {
|
||||
add = link_QueueLen(&dl->physical->link);
|
||||
if (add == 0 && dl->physical->out == NULL)
|
||||
add = ip_PushPacket(&dl->physical->link, bundle);
|
||||
total += add;
|
||||
}
|
||||
}
|
||||
|
||||
return total + ip_QueueLen(&bundle->ncp.ipcp);
|
||||
}
|
||||
|
||||
static int
|
||||
bundle_UpdateSet(struct fdescriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n)
|
||||
{
|
||||
@ -459,7 +438,8 @@ bundle_UpdateSet(struct fdescriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n)
|
||||
nlinks++;
|
||||
|
||||
if (nlinks) {
|
||||
queued = r ? bundle_FillQueues(bundle) : ip_QueueLen(&bundle->ncp.ipcp);
|
||||
queued = r ? ncp_FillPhysicalQueues(&bundle->ncp, bundle) :
|
||||
ncp_QueueLen(&bundle->ncp);
|
||||
|
||||
if (r && (bundle->phase == PHASE_NETWORK ||
|
||||
bundle->phys_type.all & PHYS_AUTO)) {
|
||||
@ -529,6 +509,7 @@ bundle_DescriptorRead(struct fdescriptor *d, struct bundle *bundle,
|
||||
{
|
||||
struct datalink *dl;
|
||||
unsigned secs;
|
||||
u_int32_t af;
|
||||
|
||||
if (descriptor_IsSet(&bundle->ncp.mp.server.desc, fdset))
|
||||
descriptor_Read(&bundle->ncp.mp.server.desc, bundle, fdset);
|
||||
@ -571,16 +552,23 @@ bundle_DescriptorRead(struct fdescriptor *d, struct bundle *bundle,
|
||||
bundle->dev.Name, n);
|
||||
return;
|
||||
}
|
||||
if (ntohl(tun.header.family) != AF_INET)
|
||||
af = ntohl(tun.header.family);
|
||||
#ifndef NOINET6
|
||||
if (af != AF_INET && af != AF_INET6)
|
||||
#else
|
||||
if (af != AF_INET)
|
||||
#endif
|
||||
/* XXX: Should be maintaining drop/family counts ! */
|
||||
return;
|
||||
}
|
||||
} else
|
||||
af = AF_INET;
|
||||
|
||||
if (((struct ip *)tun.data)->ip_dst.s_addr ==
|
||||
if (af == AF_INET && ((struct ip *)tun.data)->ip_dst.s_addr ==
|
||||
bundle->ncp.ipcp.my_ip.s_addr) {
|
||||
/* we've been asked to send something addressed *to* us :( */
|
||||
if (Enabled(bundle, OPT_LOOPBACK)) {
|
||||
pri = PacketCheck(bundle, tun.data, n, &bundle->filter.in, NULL, NULL);
|
||||
pri = PacketCheck(bundle, af, tun.data, n, &bundle->filter.in,
|
||||
NULL, NULL);
|
||||
if (pri >= 0) {
|
||||
n += sz - sizeof tun.data;
|
||||
write(bundle->dev.fd, data, n);
|
||||
@ -592,8 +580,8 @@ bundle_DescriptorRead(struct fdescriptor *d, struct bundle *bundle,
|
||||
}
|
||||
|
||||
/*
|
||||
* Process on-demand dialup. Output packets are queued within tunnel
|
||||
* device until IPCP is opened.
|
||||
* Process on-demand dialup. Output packets are queued within the tunnel
|
||||
* device until the appropriate NCP is opened.
|
||||
*/
|
||||
|
||||
if (bundle_Phase(bundle) == PHASE_DEAD) {
|
||||
@ -601,7 +589,8 @@ bundle_DescriptorRead(struct fdescriptor *d, struct bundle *bundle,
|
||||
* Note, we must be in AUTO mode :-/ otherwise our interface should
|
||||
* *not* be UP and we can't receive data
|
||||
*/
|
||||
pri = PacketCheck(bundle, tun.data, n, &bundle->filter.dial, NULL, NULL);
|
||||
pri = PacketCheck(bundle, af, tun.data, n, &bundle->filter.dial,
|
||||
NULL, NULL);
|
||||
if (pri >= 0)
|
||||
bundle_Open(bundle, NULL, PHYS_AUTO, 0);
|
||||
else
|
||||
@ -616,11 +605,12 @@ bundle_DescriptorRead(struct fdescriptor *d, struct bundle *bundle,
|
||||
}
|
||||
|
||||
secs = 0;
|
||||
pri = PacketCheck(bundle, tun.data, n, &bundle->filter.out, NULL, &secs);
|
||||
pri = PacketCheck(bundle, af, tun.data, n, &bundle->filter.out,
|
||||
NULL, &secs);
|
||||
if (pri >= 0) {
|
||||
/* Prepend the number of seconds timeout given in the filter */
|
||||
tun.header.timeout = secs;
|
||||
ip_Enqueue(&bundle->ncp.ipcp, pri, (char *)&tun, n + sizeof tun.header);
|
||||
ncp_Enqueue(&bundle->ncp, af, pri, (char *)&tun, n + sizeof tun.header);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -818,7 +808,10 @@ bundle_Create(const char *prefix, int type, int unit)
|
||||
bundle.cfg.idle.min_timeout = 0;
|
||||
*bundle.cfg.auth.name = '\0';
|
||||
*bundle.cfg.auth.key = '\0';
|
||||
bundle.cfg.opt = OPT_SROUTES | OPT_IDCHECK | OPT_LOOPBACK | OPT_TCPMSSFIXUP |
|
||||
bundle.cfg.opt = OPT_IDCHECK | OPT_LOOPBACK | OPT_SROUTES | OPT_TCPMSSFIXUP |
|
||||
#ifndef NOINET6
|
||||
OPT_IPCP | OPT_IPV6CP |
|
||||
#endif
|
||||
OPT_THROUGHPUT | OPT_UTMP;
|
||||
*bundle.cfg.label = '\0';
|
||||
bundle.cfg.ifqueue = DEF_IFQUEUE;
|
||||
@ -842,11 +835,7 @@ bundle_Create(const char *prefix, int type, int unit)
|
||||
bundle.desc.Read = bundle_DescriptorRead;
|
||||
bundle.desc.Write = bundle_DescriptorWrite;
|
||||
|
||||
mp_Init(&bundle.ncp.mp, &bundle);
|
||||
|
||||
/* Send over the first physical link by default */
|
||||
ipcp_Init(&bundle.ncp.ipcp, &bundle, &bundle.links->physical->link,
|
||||
&bundle.fsm);
|
||||
ncp_Init(&bundle.ncp, &bundle);
|
||||
|
||||
memset(&bundle.filter, '\0', sizeof bundle.filter);
|
||||
bundle.filter.in.fragok = bundle.filter.in.logok = 1;
|
||||
@ -875,7 +864,7 @@ bundle_Create(const char *prefix, int type, int unit)
|
||||
#endif
|
||||
|
||||
/* Clean out any leftover crud */
|
||||
iface_Clear(bundle.iface, IFACE_CLEAR_ALL);
|
||||
iface_Clear(bundle.iface, &bundle.ncp, 0, IFACE_CLEAR_ALL);
|
||||
|
||||
bundle_LockTun(&bundle);
|
||||
|
||||
@ -895,19 +884,18 @@ bundle_Destroy(struct bundle *bundle)
|
||||
struct datalink *dl;
|
||||
|
||||
/*
|
||||
* Clean up the interface. We don't need to timer_Stop()s, mp_Down(),
|
||||
* ipcp_CleanInterface() and bundle_DownInterface() unless we're getting
|
||||
* Clean up the interface. We don't really need to do the timer_Stop()s,
|
||||
* mp_Down(), iface_Clear() and bundle_DownInterface() unless we're getting
|
||||
* out under exceptional conditions such as a descriptor exception.
|
||||
*/
|
||||
timer_Stop(&bundle->idle.timer);
|
||||
timer_Stop(&bundle->choked.timer);
|
||||
mp_Down(&bundle->ncp.mp);
|
||||
ipcp_CleanInterface(&bundle->ncp.ipcp);
|
||||
iface_Clear(bundle->iface, &bundle->ncp, 0, IFACE_CLEAR_ALL);
|
||||
bundle_DownInterface(bundle);
|
||||
|
||||
#ifndef NORADIUS
|
||||
/* Tell the radius server the bad news */
|
||||
log_Printf(LogDEBUG, "Radius: Destroy called from bundle_Destroy\n");
|
||||
radius_Destroy(&bundle->radius);
|
||||
#endif
|
||||
|
||||
@ -916,7 +904,7 @@ bundle_Destroy(struct bundle *bundle)
|
||||
while (dl)
|
||||
dl = datalink_Destroy(dl);
|
||||
|
||||
ipcp_Destroy(&bundle->ncp.ipcp);
|
||||
ncp_Destroy(&bundle->ncp);
|
||||
|
||||
close(bundle->dev.fd);
|
||||
bundle_UnlockTun(bundle);
|
||||
@ -953,7 +941,7 @@ bundle_LinkClosed(struct bundle *bundle, struct datalink *dl)
|
||||
if (!other_links) {
|
||||
if (dl->physical->type != PHYS_AUTO) /* Not in -auto mode */
|
||||
bundle_DownInterface(bundle);
|
||||
fsm2initial(&bundle->ncp.ipcp.fsm);
|
||||
ncp2initial(&bundle->ncp);
|
||||
bundle_NewPhase(bundle, PHASE_DEAD);
|
||||
bundle_StopIdleTimer(bundle);
|
||||
}
|
||||
@ -1056,7 +1044,7 @@ bundle_ShowStatus(struct cmdargs const *arg)
|
||||
(secs / 60) % 60, secs % 60);
|
||||
}
|
||||
prompt_Printf(arg->prompt, "\n Queued: %lu of %u\n",
|
||||
(unsigned long)ip_QueueLen(&arg->bundle->ncp.ipcp),
|
||||
(unsigned long)ncp_QueueLen(&arg->bundle->ncp),
|
||||
arg->bundle->cfg.ifqueue);
|
||||
|
||||
prompt_Printf(arg->prompt, "\nDefaults:\n");
|
||||
@ -1096,23 +1084,18 @@ bundle_ShowStatus(struct cmdargs const *arg)
|
||||
} else
|
||||
prompt_Printf(arg->prompt, "disabled\n");
|
||||
|
||||
prompt_Printf(arg->prompt, " sendpipe: ");
|
||||
if (arg->bundle->ncp.ipcp.cfg.sendpipe > 0)
|
||||
prompt_Printf(arg->prompt, "%-20ld", arg->bundle->ncp.ipcp.cfg.sendpipe);
|
||||
else
|
||||
prompt_Printf(arg->prompt, "unspecified ");
|
||||
prompt_Printf(arg->prompt, " recvpipe: ");
|
||||
if (arg->bundle->ncp.ipcp.cfg.recvpipe > 0)
|
||||
prompt_Printf(arg->prompt, "%ld\n", arg->bundle->ncp.ipcp.cfg.recvpipe);
|
||||
else
|
||||
prompt_Printf(arg->prompt, "unspecified\n");
|
||||
|
||||
prompt_Printf(arg->prompt, " Sticky Routes: %-20.20s",
|
||||
optval(arg->bundle, OPT_SROUTES));
|
||||
prompt_Printf(arg->prompt, " Filter Decap: %s\n",
|
||||
prompt_Printf(arg->prompt, " Filter Decap: %-20.20s",
|
||||
optval(arg->bundle, OPT_FILTERDECAP));
|
||||
prompt_Printf(arg->prompt, " ID check: %-20.20s",
|
||||
prompt_Printf(arg->prompt, " ID check: %s\n",
|
||||
optval(arg->bundle, OPT_IDCHECK));
|
||||
prompt_Printf(arg->prompt, " Iface-Alias: %-20.20s",
|
||||
optval(arg->bundle, OPT_IFACEALIAS));
|
||||
#ifndef NOINET6
|
||||
prompt_Printf(arg->prompt, " IPCP: %s\n",
|
||||
optval(arg->bundle, OPT_IPCP));
|
||||
prompt_Printf(arg->prompt, " IPV6CP: %-20.20s",
|
||||
optval(arg->bundle, OPT_IPV6CP));
|
||||
#endif
|
||||
prompt_Printf(arg->prompt, " Keep-Session: %s\n",
|
||||
optval(arg->bundle, OPT_KEEPSESSION));
|
||||
prompt_Printf(arg->prompt, " Loopback: %-20.20s",
|
||||
@ -1123,14 +1106,14 @@ bundle_ShowStatus(struct cmdargs const *arg)
|
||||
optval(arg->bundle, OPT_PROXY));
|
||||
prompt_Printf(arg->prompt, " Proxyall: %s\n",
|
||||
optval(arg->bundle, OPT_PROXYALL));
|
||||
prompt_Printf(arg->prompt, " TCPMSS Fixup: %-20.20s",
|
||||
prompt_Printf(arg->prompt, " Sticky Routes: %-20.20s",
|
||||
optval(arg->bundle, OPT_SROUTES));
|
||||
prompt_Printf(arg->prompt, " TCPMSS Fixup: %s\n",
|
||||
optval(arg->bundle, OPT_TCPMSSFIXUP));
|
||||
prompt_Printf(arg->prompt, " Throughput: %s\n",
|
||||
prompt_Printf(arg->prompt, " Throughput: %-20.20s",
|
||||
optval(arg->bundle, OPT_THROUGHPUT));
|
||||
prompt_Printf(arg->prompt, " Utmp Logging: %-20.20s",
|
||||
prompt_Printf(arg->prompt, " Utmp Logging: %s\n",
|
||||
optval(arg->bundle, OPT_UTMP));
|
||||
prompt_Printf(arg->prompt, " Iface-Alias: %s\n",
|
||||
optval(arg->bundle, OPT_IFACEALIAS));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1183,7 +1166,7 @@ bundle_SetIdleTimer(struct bundle *bundle, int timeout, int min_timeout)
|
||||
bundle->cfg.idle.timeout = timeout;
|
||||
if (min_timeout >= 0)
|
||||
bundle->cfg.idle.min_timeout = min_timeout;
|
||||
if (bundle_LinkIsUp(bundle))
|
||||
if (ncp_LayersOpen(&bundle->ncp))
|
||||
bundle_StartIdleTimer(bundle, 0);
|
||||
}
|
||||
|
||||
@ -1795,18 +1778,20 @@ bundle_Exception(struct bundle *bundle, int fd)
|
||||
}
|
||||
|
||||
void
|
||||
bundle_AdjustFilters(struct bundle *bundle, struct in_addr *my_ip,
|
||||
struct in_addr *peer_ip)
|
||||
bundle_AdjustFilters(struct bundle *bundle, struct ncpaddr *local,
|
||||
struct ncpaddr *remote)
|
||||
{
|
||||
filter_AdjustAddr(&bundle->filter.in, my_ip, peer_ip, NULL);
|
||||
filter_AdjustAddr(&bundle->filter.out, my_ip, peer_ip, NULL);
|
||||
filter_AdjustAddr(&bundle->filter.dial, my_ip, peer_ip, NULL);
|
||||
filter_AdjustAddr(&bundle->filter.alive, my_ip, peer_ip, NULL);
|
||||
filter_AdjustAddr(&bundle->filter.in, local, remote, NULL);
|
||||
filter_AdjustAddr(&bundle->filter.out, local, remote, NULL);
|
||||
filter_AdjustAddr(&bundle->filter.dial, local, remote, NULL);
|
||||
filter_AdjustAddr(&bundle->filter.alive, local, remote, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
bundle_AdjustDNS(struct bundle *bundle, struct in_addr dns[2])
|
||||
bundle_AdjustDNS(struct bundle *bundle)
|
||||
{
|
||||
struct in_addr *dns = bundle->ncp.ipcp.ns.dns;
|
||||
|
||||
filter_AdjustAddr(&bundle->filter.in, NULL, NULL, dns);
|
||||
filter_AdjustAddr(&bundle->filter.out, NULL, NULL, dns);
|
||||
filter_AdjustAddr(&bundle->filter.dial, NULL, NULL, dns);
|
||||
|
@ -36,15 +36,19 @@
|
||||
#define OPT_FILTERDECAP 0x0001
|
||||
#define OPT_IDCHECK 0x0002
|
||||
#define OPT_IFACEALIAS 0x0004
|
||||
#define OPT_KEEPSESSION 0x0008
|
||||
#define OPT_LOOPBACK 0x0010
|
||||
#define OPT_PASSWDAUTH 0x0020
|
||||
#define OPT_PROXY 0x0040
|
||||
#define OPT_PROXYALL 0x0080
|
||||
#define OPT_SROUTES 0x0100
|
||||
#define OPT_TCPMSSFIXUP 0x0200
|
||||
#define OPT_THROUGHPUT 0x0400
|
||||
#define OPT_UTMP 0x0800
|
||||
#ifndef NOINET6
|
||||
#define OPT_IPCP 0x0008
|
||||
#define OPT_IPV6CP 0x0010
|
||||
#endif
|
||||
#define OPT_KEEPSESSION 0x0020
|
||||
#define OPT_LOOPBACK 0x0040
|
||||
#define OPT_PASSWDAUTH 0x0080
|
||||
#define OPT_PROXY 0x0100
|
||||
#define OPT_PROXYALL 0x0200
|
||||
#define OPT_SROUTES 0x0400
|
||||
#define OPT_TCPMSSFIXUP 0x0800
|
||||
#define OPT_THROUGHPUT 0x1000
|
||||
#define OPT_UTMP 0x2000
|
||||
|
||||
#define MAX_ENDDISC_CLASS 5
|
||||
|
||||
@ -109,10 +113,7 @@ struct bundle {
|
||||
} choked;
|
||||
} cfg;
|
||||
|
||||
struct {
|
||||
struct ipcp ipcp; /* Our IPCP FSM */
|
||||
struct mp mp; /* Our MP */
|
||||
} ncp;
|
||||
struct ncp ncp;
|
||||
|
||||
struct {
|
||||
struct filter in; /* incoming packet filter */
|
||||
@ -149,7 +150,6 @@ extern const char *bundle_PhaseName(struct bundle *);
|
||||
#define bundle_Phase(b) ((b)->phase)
|
||||
extern void bundle_NewPhase(struct bundle *, u_int);
|
||||
extern void bundle_LinksRemoved(struct bundle *);
|
||||
extern int bundle_LinkIsUp(const struct bundle *);
|
||||
extern void bundle_Close(struct bundle *, const char *, int);
|
||||
extern void bundle_Down(struct bundle *, int);
|
||||
extern void bundle_Open(struct bundle *, const char *, int, int);
|
||||
@ -184,9 +184,9 @@ extern void bundle_setsid(struct bundle *, int);
|
||||
extern void bundle_LockTun(struct bundle *);
|
||||
extern int bundle_HighestState(struct bundle *);
|
||||
extern int bundle_Exception(struct bundle *, int);
|
||||
extern void bundle_AdjustFilters(struct bundle *, struct in_addr *,
|
||||
struct in_addr *);
|
||||
extern void bundle_AdjustDNS(struct bundle *, struct in_addr [2]);
|
||||
extern void bundle_AdjustFilters(struct bundle *, struct ncpaddr *,
|
||||
struct ncpaddr *);
|
||||
extern void bundle_AdjustDNS(struct bundle *);
|
||||
extern void bundle_CalculateBandwidth(struct bundle *);
|
||||
extern void bundle_AutoAdjust(struct bundle *, int, int);
|
||||
extern int bundle_WantAutoloadTimer(struct bundle *);
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <stdio.h>
|
||||
@ -56,6 +57,8 @@
|
||||
#include "hdlc.h"
|
||||
#include "lcp.h"
|
||||
#include "ccp.h"
|
||||
#include "ncpaddr.h"
|
||||
#include "ip.h"
|
||||
#include "ipcp.h"
|
||||
#include "filter.h"
|
||||
#include "descriptor.h"
|
||||
@ -70,6 +73,8 @@
|
||||
#ifdef HAVE_DES
|
||||
#include "mppe.h"
|
||||
#endif
|
||||
#include "ipv6cp.h"
|
||||
#include "ncp.h"
|
||||
#include "bundle.h"
|
||||
|
||||
static void CcpSendConfigReq(struct fsm *);
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <errno.h>
|
||||
@ -66,6 +67,8 @@
|
||||
#include "chap.h"
|
||||
#include "iplist.h"
|
||||
#include "slcompress.h"
|
||||
#include "ncpaddr.h"
|
||||
#include "ip.h"
|
||||
#include "ipcp.h"
|
||||
#include "filter.h"
|
||||
#include "ccp.h"
|
||||
@ -75,6 +78,8 @@
|
||||
#ifndef NORADIUS
|
||||
#include "radius.h"
|
||||
#endif
|
||||
#include "ipv6cp.h"
|
||||
#include "ncp.h"
|
||||
#include "bundle.h"
|
||||
#include "chat.h"
|
||||
#include "cbcp.h"
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <errno.h>
|
||||
@ -63,6 +64,8 @@
|
||||
#include "chap.h"
|
||||
#include "slcompress.h"
|
||||
#include "iplist.h"
|
||||
#include "ncpaddr.h"
|
||||
#include "ip.h"
|
||||
#include "ipcp.h"
|
||||
#include "filter.h"
|
||||
#include "cbcp.h"
|
||||
@ -71,6 +74,8 @@
|
||||
#ifndef NORADIUS
|
||||
#include "radius.h"
|
||||
#endif
|
||||
#include "ipv6cp.h"
|
||||
#include "ncp.h"
|
||||
#include "bundle.h"
|
||||
#include "id.h"
|
||||
|
||||
|
@ -70,6 +70,8 @@
|
||||
#include "lqr.h"
|
||||
#include "hdlc.h"
|
||||
#include "lcp.h"
|
||||
#include "ncpaddr.h"
|
||||
#include "ip.h"
|
||||
#include "ipcp.h"
|
||||
#ifndef NONAT
|
||||
#include "nat_cmd.h"
|
||||
@ -88,6 +90,8 @@
|
||||
#ifndef NORADIUS
|
||||
#include "radius.h"
|
||||
#endif
|
||||
#include "ipv6cp.h"
|
||||
#include "ncp.h"
|
||||
#include "bundle.h"
|
||||
#include "server.h"
|
||||
#include "prompt.h"
|
||||
@ -159,7 +163,7 @@
|
||||
#define NEG_MPPE 54
|
||||
#define NEG_CHAP81 55
|
||||
|
||||
const char Version[] = "2.3.2";
|
||||
const char Version[] = "3.0.0";
|
||||
|
||||
static int ShowCommand(struct cmdargs const *);
|
||||
static int TerminalCommand(struct cmdargs const *);
|
||||
@ -454,9 +458,17 @@ command_Expand(char **nargv, int argc, char const *const *oargv,
|
||||
nargv[arg] = strdup(oargv[arg]);
|
||||
nargv[arg] = subst(nargv[arg], "HISADDR",
|
||||
inet_ntoa(bundle->ncp.ipcp.peer_ip));
|
||||
#ifndef NOINET6
|
||||
nargv[arg] = subst(nargv[arg], "HISADDR6",
|
||||
ncpaddr_ntoa(&bundle->ncp.ipv6cp.hisaddr));
|
||||
#endif
|
||||
nargv[arg] = subst(nargv[arg], "AUTHNAME", bundle->cfg.auth.name);
|
||||
nargv[arg] = subst(nargv[arg], "INTERFACE", bundle->iface->name);
|
||||
nargv[arg] = subst(nargv[arg], "MYADDR", inet_ntoa(bundle->ncp.ipcp.my_ip));
|
||||
#ifndef NOINET6
|
||||
nargv[arg] = subst(nargv[arg], "MYADDR6",
|
||||
ncpaddr_ntoa(&bundle->ncp.ipv6cp.myaddr));
|
||||
#endif
|
||||
nargv[arg] = subst(nargv[arg], "USER", bundle->ncp.mp.peer.authname);
|
||||
nargv[arg] = subst(nargv[arg], "PEER_ENDDISC",
|
||||
mp_Enddisc(bundle->ncp.mp.peer.enddisc.class,
|
||||
@ -676,7 +688,7 @@ static struct cmdtab const IfaceCommands[] =
|
||||
"Add or change an iface address", "iface add! addr[/bits| mask] peer",
|
||||
(void *)1},
|
||||
{"clear", NULL, IfaceClearCommand, LOCAL_AUTH,
|
||||
"Clear iface address(es)", "iface clear"},
|
||||
"Clear iface address(es)", "iface clear [INET | INET6]"},
|
||||
{"delete", "rm", IfaceDeleteCommand, LOCAL_AUTH,
|
||||
"Delete iface address", "iface delete addr", NULL},
|
||||
{NULL, "rm!", IfaceDeleteCommand, LOCAL_AUTH,
|
||||
@ -703,7 +715,7 @@ static struct cmdtab const Commands[] = {
|
||||
"Run a background command", "[!]bg command"},
|
||||
{"clear", NULL, ClearCommand, LOCAL_AUTH | LOCAL_CX_OPT,
|
||||
"Clear throughput statistics",
|
||||
"clear ipcp|physical [current|overall|peak]..."},
|
||||
"clear ipcp|ipv6cp|physical [current|overall|peak]..."},
|
||||
{"clone", NULL, CloneCommand, LOCAL_AUTH | LOCAL_CX,
|
||||
"Clone a link", "clone newname..."},
|
||||
{"close", NULL, CloseCommand, LOCAL_AUTH | LOCAL_CX_OPT,
|
||||
@ -845,6 +857,10 @@ static struct cmdtab const ShowCommands[] = {
|
||||
"Interface status", "show iface"},
|
||||
{"ipcp", NULL, ipcp_Show, LOCAL_AUTH,
|
||||
"IPCP status", "show ipcp"},
|
||||
#ifndef NOINET6
|
||||
{"ipv6cp", NULL, ipv6cp_Show, LOCAL_AUTH,
|
||||
"IPV6CP status", "show ipv6cp"},
|
||||
#endif
|
||||
{"layers", NULL, link_ShowLayers, LOCAL_AUTH | LOCAL_CX_OPT,
|
||||
"Protocol layers", "show layers"},
|
||||
{"lcp", NULL, lcp_ReportStatus, LOCAL_AUTH | LOCAL_CX,
|
||||
@ -857,6 +873,8 @@ static struct cmdtab const ShowCommands[] = {
|
||||
"log levels", "show log"},
|
||||
{"mem", NULL, mbuf_Show, LOCAL_AUTH,
|
||||
"mbuf allocations", "show mem"},
|
||||
{"ncp", NULL, ncp_Show, LOCAL_AUTH,
|
||||
"NCP status", "show ncp"},
|
||||
{"physical", NULL, physical_ShowStatus, LOCAL_AUTH | LOCAL_CX,
|
||||
"(low-level) link info", "show physical"},
|
||||
{"mp", "multilink", mp_ShowStatus, LOCAL_AUTH,
|
||||
@ -1404,43 +1422,42 @@ SetEscape(struct cmdargs const *arg)
|
||||
static int
|
||||
SetInterfaceAddr(struct cmdargs const *arg)
|
||||
{
|
||||
struct ipcp *ipcp = &arg->bundle->ncp.ipcp;
|
||||
struct ncp *ncp = &arg->bundle->ncp;
|
||||
struct ncpaddr ncpaddr;
|
||||
const char *hisaddr;
|
||||
|
||||
if (arg->argc > arg->argn + 4)
|
||||
return -1;
|
||||
|
||||
hisaddr = NULL;
|
||||
memset(&ipcp->cfg.my_range, '\0', sizeof ipcp->cfg.my_range);
|
||||
memset(&ipcp->cfg.peer_range, '\0', sizeof ipcp->cfg.peer_range);
|
||||
ipcp->cfg.HaveTriggerAddress = 0;
|
||||
ipcp->cfg.netmask.s_addr = INADDR_ANY;
|
||||
iplist_reset(&ipcp->cfg.peer_list);
|
||||
memset(&ncp->ipcp.cfg.my_range, '\0', sizeof ncp->ipcp.cfg.my_range);
|
||||
memset(&ncp->ipcp.cfg.peer_range, '\0', sizeof ncp->ipcp.cfg.peer_range);
|
||||
ncp->ipcp.cfg.HaveTriggerAddress = 0;
|
||||
ncp->ipcp.cfg.netmask.s_addr = INADDR_ANY;
|
||||
iplist_reset(&ncp->ipcp.cfg.peer_list);
|
||||
|
||||
if (arg->argc > arg->argn) {
|
||||
if (!ParseAddr(ipcp, arg->argv[arg->argn],
|
||||
&ipcp->cfg.my_range.ipaddr, &ipcp->cfg.my_range.mask,
|
||||
&ipcp->cfg.my_range.width))
|
||||
if (!ncprange_aton(&ncp->ipcp.cfg.my_range, ncp, arg->argv[arg->argn]))
|
||||
return 1;
|
||||
if (arg->argc > arg->argn+1) {
|
||||
hisaddr = arg->argv[arg->argn+1];
|
||||
if (arg->argc > arg->argn+2) {
|
||||
ipcp->ifmask = ipcp->cfg.netmask = GetIpAddr(arg->argv[arg->argn+2]);
|
||||
ncp->ipcp.ifmask = ncp->ipcp.cfg.netmask =
|
||||
GetIpAddr(arg->argv[arg->argn+2]);
|
||||
if (arg->argc > arg->argn+3) {
|
||||
ipcp->cfg.TriggerAddress = GetIpAddr(arg->argv[arg->argn+3]);
|
||||
ipcp->cfg.HaveTriggerAddress = 1;
|
||||
ncp->ipcp.cfg.TriggerAddress = GetIpAddr(arg->argv[arg->argn+3]);
|
||||
ncp->ipcp.cfg.HaveTriggerAddress = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 0.0.0.0 means any address (0 bits) */
|
||||
if (ipcp->cfg.my_range.ipaddr.s_addr == INADDR_ANY) {
|
||||
ipcp->cfg.my_range.mask.s_addr = INADDR_ANY;
|
||||
ipcp->cfg.my_range.width = 0;
|
||||
}
|
||||
ipcp->my_ip.s_addr = ipcp->cfg.my_range.ipaddr.s_addr;
|
||||
bundle_AdjustFilters(arg->bundle, &ipcp->my_ip, NULL);
|
||||
ncpaddr_getip4(&ncpaddr, &ncp->ipcp.my_ip);
|
||||
ncprange_getaddr(&ncp->ipcp.cfg.my_range, &ncpaddr);
|
||||
if (ncp->ipcp.my_ip.s_addr == INADDR_ANY)
|
||||
ncprange_setwidth(&ncp->ipcp.cfg.my_range, 0);
|
||||
bundle_AdjustFilters(arg->bundle, &ncpaddr, NULL);
|
||||
|
||||
if (hisaddr && !ipcp_UseHisaddr(arg->bundle, hisaddr,
|
||||
arg->bundle->phys_type.all & PHYS_AUTO))
|
||||
@ -1499,7 +1516,8 @@ SetVariable(struct cmdargs const *arg)
|
||||
const char *argp;
|
||||
struct datalink *cx = arg->cx; /* LOCAL_CX uses this */
|
||||
struct link *l = command_ChooseLink(arg); /* LOCAL_CX_OPT uses this */
|
||||
struct in_addr dummyaddr, *addr;
|
||||
struct in_addr *ipaddr;
|
||||
struct ncpaddr ncpaddr[2];
|
||||
|
||||
if (arg->argc > arg->argn)
|
||||
argp = arg->argv[arg->argn];
|
||||
@ -1929,27 +1947,30 @@ SetVariable(struct cmdargs const *arg)
|
||||
case VAR_NBNS:
|
||||
case VAR_DNS:
|
||||
if (param == VAR_DNS) {
|
||||
addr = arg->bundle->ncp.ipcp.cfg.ns.dns;
|
||||
addr[0].s_addr = addr[1].s_addr = INADDR_NONE;
|
||||
ipaddr = arg->bundle->ncp.ipcp.cfg.ns.dns;
|
||||
ipaddr[0].s_addr = ipaddr[1].s_addr = INADDR_NONE;
|
||||
} else {
|
||||
addr = arg->bundle->ncp.ipcp.cfg.ns.nbns;
|
||||
addr[0].s_addr = addr[1].s_addr = INADDR_ANY;
|
||||
ipaddr = arg->bundle->ncp.ipcp.cfg.ns.nbns;
|
||||
ipaddr[0].s_addr = ipaddr[1].s_addr = INADDR_ANY;
|
||||
}
|
||||
|
||||
if (arg->argc > arg->argn) {
|
||||
ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn],
|
||||
addr, &dummyaddr, &dummyint);
|
||||
if (arg->argc > arg->argn+1)
|
||||
ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn + 1],
|
||||
addr + 1, &dummyaddr, &dummyint);
|
||||
|
||||
if (addr[0].s_addr == INADDR_ANY) {
|
||||
addr[0].s_addr = addr[1].s_addr;
|
||||
addr[1].s_addr = INADDR_ANY;
|
||||
ncpaddr_aton(ncpaddr, &arg->bundle->ncp, arg->argv[arg->argn]);
|
||||
if (!ncpaddr_getip4(ncpaddr, ipaddr))
|
||||
return -1;
|
||||
if (arg->argc > arg->argn+1) {
|
||||
ncpaddr_aton(ncpaddr + 1, &arg->bundle->ncp, arg->argv[arg->argn + 1]);
|
||||
if (!ncpaddr_getip4(ncpaddr + 1, ipaddr + 1))
|
||||
return -1;
|
||||
}
|
||||
if (addr[0].s_addr == INADDR_NONE) {
|
||||
addr[0].s_addr = addr[1].s_addr;
|
||||
addr[1].s_addr = INADDR_NONE;
|
||||
|
||||
if (ipaddr[0].s_addr == INADDR_ANY) {
|
||||
ipaddr[0] = ipaddr[1];
|
||||
ipaddr[1].s_addr = INADDR_ANY;
|
||||
}
|
||||
if (ipaddr[0].s_addr == INADDR_NONE) {
|
||||
ipaddr[0] = ipaddr[1];
|
||||
ipaddr[1].s_addr = INADDR_NONE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -2011,12 +2032,12 @@ SetVariable(struct cmdargs const *arg)
|
||||
|
||||
case VAR_SENDPIPE:
|
||||
long_val = atol(argp);
|
||||
arg->bundle->ncp.ipcp.cfg.sendpipe = long_val;
|
||||
arg->bundle->ncp.cfg.sendpipe = long_val;
|
||||
break;
|
||||
|
||||
case VAR_RECVPIPE:
|
||||
long_val = atol(argp);
|
||||
arg->bundle->ncp.ipcp.cfg.recvpipe = long_val;
|
||||
arg->bundle->ncp.cfg.recvpipe = long_val;
|
||||
break;
|
||||
|
||||
#ifndef NORADIUS
|
||||
@ -2075,45 +2096,43 @@ SetVariable(struct cmdargs const *arg)
|
||||
|
||||
case VAR_URGENTPORTS:
|
||||
if (arg->argn == arg->argc) {
|
||||
ipcp_SetUrgentTOS(&arg->bundle->ncp.ipcp);
|
||||
ipcp_ClearUrgentTcpPorts(&arg->bundle->ncp.ipcp);
|
||||
ipcp_ClearUrgentUdpPorts(&arg->bundle->ncp.ipcp);
|
||||
ncp_SetUrgentTOS(&arg->bundle->ncp);
|
||||
ncp_ClearUrgentTcpPorts(&arg->bundle->ncp);
|
||||
ncp_ClearUrgentUdpPorts(&arg->bundle->ncp);
|
||||
} else if (!strcasecmp(arg->argv[arg->argn], "udp")) {
|
||||
ipcp_SetUrgentTOS(&arg->bundle->ncp.ipcp);
|
||||
ncp_SetUrgentTOS(&arg->bundle->ncp);
|
||||
if (arg->argn == arg->argc - 1)
|
||||
ipcp_ClearUrgentUdpPorts(&arg->bundle->ncp.ipcp);
|
||||
ncp_ClearUrgentUdpPorts(&arg->bundle->ncp);
|
||||
else for (f = arg->argn + 1; f < arg->argc; f++)
|
||||
if (*arg->argv[f] == '+')
|
||||
ipcp_AddUrgentUdpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f] + 1));
|
||||
ncp_AddUrgentUdpPort(&arg->bundle->ncp, atoi(arg->argv[f] + 1));
|
||||
else if (*arg->argv[f] == '-')
|
||||
ipcp_RemoveUrgentUdpPort(&arg->bundle->ncp.ipcp,
|
||||
atoi(arg->argv[f] + 1));
|
||||
ncp_RemoveUrgentUdpPort(&arg->bundle->ncp, atoi(arg->argv[f] + 1));
|
||||
else {
|
||||
if (f == arg->argn)
|
||||
ipcp_ClearUrgentUdpPorts(&arg->bundle->ncp.ipcp);
|
||||
ipcp_AddUrgentUdpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f]));
|
||||
ncp_ClearUrgentUdpPorts(&arg->bundle->ncp);
|
||||
ncp_AddUrgentUdpPort(&arg->bundle->ncp, atoi(arg->argv[f]));
|
||||
}
|
||||
} else if (arg->argn == arg->argc - 1 &&
|
||||
!strcasecmp(arg->argv[arg->argn], "none")) {
|
||||
ipcp_ClearUrgentTcpPorts(&arg->bundle->ncp.ipcp);
|
||||
ipcp_ClearUrgentUdpPorts(&arg->bundle->ncp.ipcp);
|
||||
ipcp_ClearUrgentTOS(&arg->bundle->ncp.ipcp);
|
||||
ncp_ClearUrgentTcpPorts(&arg->bundle->ncp);
|
||||
ncp_ClearUrgentUdpPorts(&arg->bundle->ncp);
|
||||
ncp_ClearUrgentTOS(&arg->bundle->ncp);
|
||||
} else {
|
||||
ipcp_SetUrgentTOS(&arg->bundle->ncp.ipcp);
|
||||
ncp_SetUrgentTOS(&arg->bundle->ncp);
|
||||
first = arg->argn;
|
||||
if (!strcasecmp(arg->argv[first], "tcp") && ++first == arg->argc)
|
||||
ipcp_ClearUrgentTcpPorts(&arg->bundle->ncp.ipcp);
|
||||
ncp_ClearUrgentTcpPorts(&arg->bundle->ncp);
|
||||
|
||||
for (f = first; f < arg->argc; f++)
|
||||
if (*arg->argv[f] == '+')
|
||||
ipcp_AddUrgentTcpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f] + 1));
|
||||
ncp_AddUrgentTcpPort(&arg->bundle->ncp, atoi(arg->argv[f] + 1));
|
||||
else if (*arg->argv[f] == '-')
|
||||
ipcp_RemoveUrgentTcpPort(&arg->bundle->ncp.ipcp,
|
||||
atoi(arg->argv[f] + 1));
|
||||
ncp_RemoveUrgentTcpPort(&arg->bundle->ncp, atoi(arg->argv[f] + 1));
|
||||
else {
|
||||
if (f == first)
|
||||
ipcp_ClearUrgentTcpPorts(&arg->bundle->ncp.ipcp);
|
||||
ipcp_AddUrgentTcpPort(&arg->bundle->ncp.ipcp, atoi(arg->argv[f]));
|
||||
ncp_ClearUrgentTcpPorts(&arg->bundle->ncp);
|
||||
ncp_AddUrgentTcpPort(&arg->bundle->ncp, atoi(arg->argv[f]));
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -2173,7 +2192,7 @@ static struct cmdtab const SetCommands[] = {
|
||||
"escape characters", "set escape hex-digit ..."},
|
||||
{"filter", NULL, filter_Set, LOCAL_AUTH,
|
||||
"packet filters", "set filter alive|dial|in|out rule-no permit|deny "
|
||||
"[src_addr[/width]] [dst_addr[/width]] [tcp|udp|icmp|ospf|igmp "
|
||||
"[src_addr[/width]] [dst_addr[/width]] [proto "
|
||||
"[src [lt|eq|gt port]] [dst [lt|eq|gt port]] [estab] [syn] [finrst]]"},
|
||||
{"hangup", NULL, SetVariable, LOCAL_AUTH | LOCAL_CX,
|
||||
"hangup script", "set hangup chat-script", (const void *) VAR_HANGUP},
|
||||
@ -2261,73 +2280,84 @@ SetCommand(struct cmdargs const *arg)
|
||||
static int
|
||||
AddCommand(struct cmdargs const *arg)
|
||||
{
|
||||
struct in_addr dest, gateway, netmask;
|
||||
int gw, addrs;
|
||||
struct ncpaddr gw;
|
||||
struct ncprange dest;
|
||||
struct in_addr host;
|
||||
int dest_default, gw_arg, addrs;
|
||||
|
||||
if (arg->argc != arg->argn+3 && arg->argc != arg->argn+2)
|
||||
return -1;
|
||||
|
||||
addrs = 0;
|
||||
if (arg->argc == arg->argn+2) {
|
||||
dest_default = 0;
|
||||
if (arg->argc == arg->argn + 2) {
|
||||
if (!strcasecmp(arg->argv[arg->argn], "default"))
|
||||
dest.s_addr = netmask.s_addr = INADDR_ANY;
|
||||
dest_default = 1;
|
||||
else {
|
||||
int width;
|
||||
|
||||
if (!ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn],
|
||||
&dest, &netmask, &width))
|
||||
if (!ncprange_aton(&dest, &arg->bundle->ncp, arg->argv[arg->argn]))
|
||||
return -1;
|
||||
if (!strncasecmp(arg->argv[arg->argn], "MYADDR", 6))
|
||||
addrs = ROUTE_DSTMYADDR;
|
||||
else if (!strncasecmp(arg->argv[arg->argn], "MYADDR6", 7))
|
||||
addrs = ROUTE_DSTMYADDR6;
|
||||
else if (!strncasecmp(arg->argv[arg->argn], "HISADDR", 7))
|
||||
addrs = ROUTE_DSTHISADDR;
|
||||
else if (!strncasecmp(arg->argv[arg->argn], "HISADDR6", 8))
|
||||
addrs = ROUTE_DSTHISADDR6;
|
||||
else if (!strncasecmp(arg->argv[arg->argn], "DNS0", 4))
|
||||
addrs = ROUTE_DSTDNS0;
|
||||
else if (!strncasecmp(arg->argv[arg->argn], "DNS1", 4))
|
||||
addrs = ROUTE_DSTDNS1;
|
||||
}
|
||||
gw = 1;
|
||||
gw_arg = 1;
|
||||
} else {
|
||||
if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) {
|
||||
addrs = ROUTE_DSTMYADDR;
|
||||
dest = arg->bundle->ncp.ipcp.my_ip;
|
||||
host = arg->bundle->ncp.ipcp.my_ip;
|
||||
} else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) {
|
||||
addrs = ROUTE_DSTHISADDR;
|
||||
dest = arg->bundle->ncp.ipcp.peer_ip;
|
||||
host = arg->bundle->ncp.ipcp.peer_ip;
|
||||
} else if (strcasecmp(arg->argv[arg->argn], "DNS0") == 0) {
|
||||
addrs = ROUTE_DSTDNS0;
|
||||
dest = arg->bundle->ncp.ipcp.ns.dns[0];
|
||||
host = arg->bundle->ncp.ipcp.ns.dns[0];
|
||||
} else if (strcasecmp(arg->argv[arg->argn], "DNS1") == 0) {
|
||||
addrs = ROUTE_DSTDNS1;
|
||||
dest = arg->bundle->ncp.ipcp.ns.dns[1];
|
||||
host = arg->bundle->ncp.ipcp.ns.dns[1];
|
||||
} else {
|
||||
dest = GetIpAddr(arg->argv[arg->argn]);
|
||||
if (dest.s_addr == INADDR_NONE) {
|
||||
host = GetIpAddr(arg->argv[arg->argn]);
|
||||
if (host.s_addr == INADDR_NONE) {
|
||||
log_Printf(LogWARN, "%s: Invalid destination address\n",
|
||||
arg->argv[arg->argn]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
netmask = GetIpAddr(arg->argv[arg->argn+1]);
|
||||
gw = 2;
|
||||
ncprange_setip4(&dest, host, GetIpAddr(arg->argv[arg->argn + 1]));
|
||||
gw_arg = 2;
|
||||
}
|
||||
|
||||
if (strcasecmp(arg->argv[arg->argn+gw], "HISADDR") == 0) {
|
||||
gateway = arg->bundle->ncp.ipcp.peer_ip;
|
||||
if (strcasecmp(arg->argv[arg->argn + gw_arg], "HISADDR") == 0) {
|
||||
ncpaddr_setip4(&gw, arg->bundle->ncp.ipcp.peer_ip);
|
||||
addrs |= ROUTE_GWHISADDR;
|
||||
#ifndef NOINET6
|
||||
} else if (strcasecmp(arg->argv[arg->argn + gw_arg], "HISADDR6") == 0) {
|
||||
ncpaddr_copy(&gw, &arg->bundle->ncp.ipv6cp.hisaddr);
|
||||
addrs |= ROUTE_GWHISADDR6;
|
||||
#endif
|
||||
} else {
|
||||
gateway = GetIpAddr(arg->argv[arg->argn+gw]);
|
||||
if (gateway.s_addr == INADDR_NONE) {
|
||||
if (!ncpaddr_aton(&gw, &arg->bundle->ncp, arg->argv[arg->argn + gw_arg])) {
|
||||
log_Printf(LogWARN, "%s: Invalid gateway address\n",
|
||||
arg->argv[arg->argn + gw]);
|
||||
arg->argv[arg->argn + gw_arg]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (rt_Set(arg->bundle, RTM_ADD, dest, gateway, netmask,
|
||||
arg->cmd->args ? 1 : 0, (addrs & ROUTE_GWHISADDR) ? 1 : 0)
|
||||
if (dest_default)
|
||||
ncprange_setdefault(&dest, ncpaddr_family(&gw));
|
||||
|
||||
if (rt_Set(arg->bundle, RTM_ADD, &dest, &gw, arg->cmd->args ? 1 : 0,
|
||||
((addrs & ROUTE_GWHISADDR) || (addrs & ROUTE_GWHISADDR6)) ? 1 : 0)
|
||||
&& addrs != ROUTE_STATIC)
|
||||
route_Add(&arg->bundle->ncp.ipcp.route, addrs, dest, netmask, gateway);
|
||||
route_Add(&arg->bundle->ncp.route, addrs, &dest, &gw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2335,39 +2365,43 @@ AddCommand(struct cmdargs const *arg)
|
||||
static int
|
||||
DeleteCommand(struct cmdargs const *arg)
|
||||
{
|
||||
struct in_addr dest, none;
|
||||
struct ncprange dest;
|
||||
int addrs;
|
||||
|
||||
if (arg->argc == arg->argn+1) {
|
||||
if(strcasecmp(arg->argv[arg->argn], "all") == 0) {
|
||||
route_IfDelete(arg->bundle, 0);
|
||||
route_DeleteAll(&arg->bundle->ncp.ipcp.route);
|
||||
route_DeleteAll(&arg->bundle->ncp.route);
|
||||
} else {
|
||||
addrs = 0;
|
||||
if (strcasecmp(arg->argv[arg->argn], "MYADDR") == 0) {
|
||||
dest = arg->bundle->ncp.ipcp.my_ip;
|
||||
ncprange_setip4host(&dest, arg->bundle->ncp.ipcp.my_ip);
|
||||
addrs = ROUTE_DSTMYADDR;
|
||||
#ifndef NOINET6
|
||||
} else if (strcasecmp(arg->argv[arg->argn], "MYADDR6") == 0) {
|
||||
ncprange_sethost(&dest, &arg->bundle->ncp.ipv6cp.myaddr);
|
||||
addrs = ROUTE_DSTMYADDR6;
|
||||
#endif
|
||||
} else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) {
|
||||
dest = arg->bundle->ncp.ipcp.peer_ip;
|
||||
ncprange_setip4host(&dest, arg->bundle->ncp.ipcp.peer_ip);
|
||||
addrs = ROUTE_DSTHISADDR;
|
||||
#ifndef NOINET6
|
||||
} else if (strcasecmp(arg->argv[arg->argn], "HISADDR6") == 0) {
|
||||
ncprange_sethost(&dest, &arg->bundle->ncp.ipv6cp.hisaddr);
|
||||
addrs = ROUTE_DSTHISADDR6;
|
||||
#endif
|
||||
} else if (strcasecmp(arg->argv[arg->argn], "DNS0") == 0) {
|
||||
dest = arg->bundle->ncp.ipcp.ns.dns[0];
|
||||
ncprange_setip4host(&dest, arg->bundle->ncp.ipcp.ns.dns[0]);
|
||||
addrs = ROUTE_DSTDNS0;
|
||||
} else if (strcasecmp(arg->argv[arg->argn], "DNS1") == 0) {
|
||||
dest = arg->bundle->ncp.ipcp.ns.dns[1];
|
||||
ncprange_setip4host(&dest, arg->bundle->ncp.ipcp.ns.dns[1]);
|
||||
addrs = ROUTE_DSTDNS1;
|
||||
} else {
|
||||
dest = GetIpAddr(arg->argv[arg->argn]);
|
||||
if (dest.s_addr == INADDR_NONE) {
|
||||
log_Printf(LogWARN, "%s: Invalid IP address\n", arg->argv[arg->argn]);
|
||||
return -1;
|
||||
}
|
||||
ncprange_aton(&dest, &arg->bundle->ncp, arg->argv[arg->argn]);
|
||||
addrs = ROUTE_STATIC;
|
||||
}
|
||||
none.s_addr = INADDR_ANY;
|
||||
rt_Set(arg->bundle, RTM_DELETE, dest, none, none,
|
||||
arg->cmd->args ? 1 : 0, 0);
|
||||
route_Delete(&arg->bundle->ncp.ipcp.route, addrs, dest);
|
||||
rt_Set(arg->bundle, RTM_DELETE, &dest, NULL, arg->cmd->args ? 1 : 0, 0);
|
||||
route_Delete(&arg->bundle->ncp.route, addrs, &dest);
|
||||
}
|
||||
} else
|
||||
return -1;
|
||||
@ -2685,6 +2719,12 @@ static struct cmdtab const NegotiateCommands[] = {
|
||||
{"iface-alias", NULL, IfaceAliasOptSet, LOCAL_AUTH,
|
||||
"retain interface addresses", "disable|enable",
|
||||
(const void *)OPT_IFACEALIAS},
|
||||
#ifndef NOINET6
|
||||
{"ipcp", NULL, OptSet, LOCAL_AUTH, "IP Network Control Protocol",
|
||||
"disable|enable", (const void *)OPT_IPCP},
|
||||
{"ipv6cp", NULL, OptSet, LOCAL_AUTH, "IPv6 Network Control Protocol",
|
||||
"disable|enable", (const void *)OPT_IPV6CP},
|
||||
#endif
|
||||
{"keep-session", NULL, OptSet, LOCAL_AUTH, "Retain device session leader",
|
||||
"disable|enable", (const void *)OPT_KEEPSESSION},
|
||||
{"loopback", NULL, OptSet, LOCAL_AUTH, "Loop packets for local iface",
|
||||
@ -2704,7 +2744,11 @@ static struct cmdtab const NegotiateCommands[] = {
|
||||
{"utmp", NULL, OptSet, LOCAL_AUTH, "Log connections in utmp",
|
||||
"disable|enable", (const void *)OPT_UTMP},
|
||||
|
||||
#define OPT_MAX 11 /* accept/deny allowed below and not above */
|
||||
#ifndef NOINET6
|
||||
#define OPT_MAX 13 /* accept/deny allowed below and not above */
|
||||
#else
|
||||
#define OPT_MAX 11
|
||||
#endif
|
||||
|
||||
{"acfcomp", NULL, NegotiateSet, LOCAL_AUTH | LOCAL_CX,
|
||||
"Address & Control field compression", "accept|deny|disable|enable",
|
||||
@ -2819,6 +2863,10 @@ ClearCommand(struct cmdargs const *arg)
|
||||
t = &cx->physical->link.stats.total;
|
||||
} else if (strcasecmp(arg->argv[arg->argn], "ipcp") == 0)
|
||||
t = &arg->bundle->ncp.ipcp.throughput;
|
||||
#ifndef NOINET6
|
||||
else if (strcasecmp(arg->argv[arg->argn], "ipv6cp") == 0)
|
||||
t = &arg->bundle->ncp.ipv6cp.throughput;
|
||||
#endif
|
||||
else
|
||||
return -1;
|
||||
|
||||
@ -2870,65 +2918,84 @@ RunListCommand(struct cmdargs const *arg)
|
||||
static int
|
||||
IfaceAddCommand(struct cmdargs const *arg)
|
||||
{
|
||||
int bits, n, how;
|
||||
struct in_addr ifa, mask, brd;
|
||||
struct ncpaddr peer, addr;
|
||||
struct ncprange ifa;
|
||||
struct in_addr mask;
|
||||
int n, how;
|
||||
|
||||
if (arg->argc == arg->argn + 1) {
|
||||
if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL))
|
||||
if (!ncprange_aton(&ifa, NULL, arg->argv[arg->argn]))
|
||||
return -1;
|
||||
mask.s_addr = brd.s_addr = INADDR_BROADCAST;
|
||||
ncpaddr_init(&peer);
|
||||
} else {
|
||||
if (arg->argc == arg->argn + 2) {
|
||||
if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, &mask, &bits))
|
||||
if (!ncprange_aton(&ifa, NULL, arg->argv[arg->argn]))
|
||||
return -1;
|
||||
n = 1;
|
||||
} else if (arg->argc == arg->argn + 3) {
|
||||
if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL))
|
||||
if (!ncpaddr_aton(&addr, NULL, arg->argv[arg->argn]))
|
||||
return -1;
|
||||
if (!ParseAddr(NULL, arg->argv[arg->argn + 1], &mask, NULL, NULL))
|
||||
if (ncpaddr_family(&addr) != AF_INET)
|
||||
return -1;
|
||||
ncprange_sethost(&ifa, &addr);
|
||||
if (!ncpaddr_aton(&addr, NULL, arg->argv[arg->argn + 1]))
|
||||
return -1;
|
||||
if (!ncpaddr_getip4(&addr, &mask))
|
||||
return -1;
|
||||
if (!ncprange_setip4mask(&ifa, mask))
|
||||
return -1;
|
||||
n = 2;
|
||||
} else
|
||||
return -1;
|
||||
|
||||
if (!ParseAddr(NULL, arg->argv[arg->argn + n], &brd, NULL, NULL))
|
||||
if (!ncpaddr_aton(&peer, NULL, arg->argv[arg->argn + n]))
|
||||
return -1;
|
||||
|
||||
if (ncprange_family(&ifa) != ncpaddr_family(&peer)) {
|
||||
log_Printf(LogWARN, "IfaceAddCommand: src and dst address families"
|
||||
" differ\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
how = IFACE_ADD_LAST;
|
||||
if (arg->cmd->args)
|
||||
how |= IFACE_FORCE_ADD;
|
||||
|
||||
return !iface_inAdd(arg->bundle->iface, ifa, mask, brd, how);
|
||||
return !iface_Add(arg->bundle->iface, &arg->bundle->ncp, &ifa, &peer, how);
|
||||
}
|
||||
|
||||
static int
|
||||
IfaceDeleteCommand(struct cmdargs const *arg)
|
||||
{
|
||||
struct in_addr ifa;
|
||||
struct ncpaddr ifa;
|
||||
struct in_addr ifa4;
|
||||
int ok;
|
||||
|
||||
if (arg->argc != arg->argn + 1)
|
||||
return -1;
|
||||
|
||||
if (!ParseAddr(NULL, arg->argv[arg->argn], &ifa, NULL, NULL))
|
||||
if (!ncpaddr_aton(&ifa, NULL, arg->argv[arg->argn]))
|
||||
return -1;
|
||||
|
||||
if (arg->bundle->ncp.ipcp.fsm.state == ST_OPENED &&
|
||||
arg->bundle->ncp.ipcp.my_ip.s_addr == ifa.s_addr) {
|
||||
ncpaddr_getip4(&ifa, &ifa4) &&
|
||||
arg->bundle->ncp.ipcp.my_ip.s_addr == ifa4.s_addr) {
|
||||
log_Printf(LogWARN, "%s: Cannot remove active interface address\n",
|
||||
inet_ntoa(ifa));
|
||||
ncpaddr_ntoa(&ifa));
|
||||
return 1;
|
||||
}
|
||||
|
||||
ok = iface_inDelete(arg->bundle->iface, ifa);
|
||||
ok = iface_Delete(arg->bundle->iface, &arg->bundle->ncp, &ifa);
|
||||
if (!ok) {
|
||||
if (arg->cmd->args)
|
||||
ok = 1;
|
||||
else if (arg->prompt)
|
||||
prompt_Printf(arg->prompt, "%s: No such address\n", inet_ntoa(ifa));
|
||||
prompt_Printf(arg->prompt, "%s: No such interface address\n",
|
||||
ncpaddr_ntoa(&ifa));
|
||||
else
|
||||
log_Printf(LogWARN, "%s: No such address\n", inet_ntoa(ifa));
|
||||
log_Printf(LogWARN, "%s: No such interface address\n",
|
||||
ncpaddr_ntoa(&ifa));
|
||||
}
|
||||
|
||||
return !ok;
|
||||
@ -2937,15 +3004,25 @@ IfaceDeleteCommand(struct cmdargs const *arg)
|
||||
static int
|
||||
IfaceClearCommand(struct cmdargs const *arg)
|
||||
{
|
||||
int how;
|
||||
int family, how;
|
||||
|
||||
if (arg->argc != arg->argn)
|
||||
family = 0;
|
||||
if (arg->argc == arg->argn + 1) {
|
||||
if (strcasecmp(arg->argv[arg->argn], "inet") == 0)
|
||||
family = AF_INET;
|
||||
#ifndef NOINET6
|
||||
else if (strcasecmp(arg->argv[arg->argn], "inet6") == 0)
|
||||
family = AF_INET6;
|
||||
#endif
|
||||
else
|
||||
return -1;
|
||||
} else if (arg->argc != arg->argn)
|
||||
return -1;
|
||||
|
||||
how = arg->bundle->ncp.ipcp.fsm.state == ST_OPENED ||
|
||||
arg->bundle->phys_type.all & PHYS_AUTO ?
|
||||
IFACE_CLEAR_ALIASES : IFACE_CLEAR_ALL;
|
||||
iface_Clear(arg->bundle->iface, how);
|
||||
iface_Clear(arg->bundle->iface, &arg->bundle->ncp, family, how);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <ctype.h>
|
||||
@ -56,12 +57,16 @@
|
||||
#include "physical.h"
|
||||
#include "iplist.h"
|
||||
#include "slcompress.h"
|
||||
#include "ncpaddr.h"
|
||||
#include "ip.h"
|
||||
#include "ipcp.h"
|
||||
#include "filter.h"
|
||||
#include "mp.h"
|
||||
#ifndef NORADIUS
|
||||
#include "radius.h"
|
||||
#endif
|
||||
#include "ipv6cp.h"
|
||||
#include "ncp.h"
|
||||
#include "bundle.h"
|
||||
#include "chat.h"
|
||||
#include "auth.h"
|
||||
@ -622,7 +627,7 @@ datalink_NCPUp(struct datalink *dl)
|
||||
return;
|
||||
} else {
|
||||
dl->bundle->ncp.mp.peer = dl->peer;
|
||||
ipcp_SetLink(&dl->bundle->ncp.ipcp, &dl->physical->link);
|
||||
ncp_SetLink(&dl->bundle->ncp, &dl->physical->link);
|
||||
auth_Select(dl->bundle, dl->peer.authname);
|
||||
}
|
||||
|
||||
|
@ -83,11 +83,15 @@
|
||||
#include "datalink.h"
|
||||
#include "slcompress.h"
|
||||
#include "iplist.h"
|
||||
#include "ncpaddr.h"
|
||||
#include "ip.h"
|
||||
#include "ipcp.h"
|
||||
#include "filter.h"
|
||||
#ifndef NORADIUS
|
||||
#include "radius.h"
|
||||
#endif
|
||||
#include "ipv6cp.h"
|
||||
#include "ncp.h"
|
||||
#include "bundle.h"
|
||||
#include "id.h"
|
||||
#include "iface.h"
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <netdb.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <stdio.h>
|
||||
@ -56,6 +57,8 @@
|
||||
#include "ccp.h"
|
||||
#include "link.h"
|
||||
#include "slcompress.h"
|
||||
#include "ncpaddr.h"
|
||||
#include "ip.h"
|
||||
#include "ipcp.h"
|
||||
#include "filter.h"
|
||||
#include "descriptor.h"
|
||||
@ -64,115 +67,20 @@
|
||||
#ifndef NORADIUS
|
||||
#include "radius.h"
|
||||
#endif
|
||||
#include "ipv6cp.h"
|
||||
#include "ncp.h"
|
||||
#include "bundle.h"
|
||||
|
||||
static int filter_Nam2Proto(int, char const *const *);
|
||||
static int filter_Nam2Op(const char *);
|
||||
|
||||
static const u_int32_t netmasks[33] = {
|
||||
0x00000000,
|
||||
0x80000000, 0xC0000000, 0xE0000000, 0xF0000000,
|
||||
0xF8000000, 0xFC000000, 0xFE000000, 0xFF000000,
|
||||
0xFF800000, 0xFFC00000, 0xFFE00000, 0xFFF00000,
|
||||
0xFFF80000, 0xFFFC0000, 0xFFFE0000, 0xFFFF0000,
|
||||
0xFFFF8000, 0xFFFFC000, 0xFFFFE000, 0xFFFFF000,
|
||||
0xFFFFF800, 0xFFFFFC00, 0xFFFFFE00, 0xFFFFFF00,
|
||||
0xFFFFFF80, 0xFFFFFFC0, 0xFFFFFFE0, 0xFFFFFFF0,
|
||||
0xFFFFFFF8, 0xFFFFFFFC, 0xFFFFFFFE, 0xFFFFFFFF,
|
||||
};
|
||||
|
||||
struct in_addr
|
||||
bits2mask(int bits)
|
||||
{
|
||||
struct in_addr result;
|
||||
|
||||
result.s_addr = htonl(netmasks[bits]);
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
ParseAddr(struct ipcp *ipcp, const char *data,
|
||||
struct in_addr *paddr, struct in_addr *pmask, int *pwidth)
|
||||
{
|
||||
int bits, len;
|
||||
char *wp;
|
||||
const char *cp;
|
||||
|
||||
if (pmask)
|
||||
pmask->s_addr = INADDR_BROADCAST; /* Assume 255.255.255.255 as default */
|
||||
|
||||
cp = pmask || pwidth ? strchr(data, '/') : NULL;
|
||||
len = cp ? cp - data : strlen(data);
|
||||
|
||||
if (ipcp && strncasecmp(data, "HISADDR", len) == 0)
|
||||
*paddr = ipcp->peer_ip;
|
||||
else if (ipcp && strncasecmp(data, "MYADDR", len) == 0)
|
||||
*paddr = ipcp->my_ip;
|
||||
else if (ipcp && strncasecmp(data, "DNS0", len) == 0)
|
||||
*paddr = ipcp->ns.dns[0];
|
||||
else if (ipcp && strncasecmp(data, "DNS1", len) == 0)
|
||||
*paddr = ipcp->ns.dns[1];
|
||||
else {
|
||||
char *s;
|
||||
|
||||
s = (char *)alloca(len + 1);
|
||||
strncpy(s, data, len);
|
||||
s[len] = '\0';
|
||||
*paddr = GetIpAddr(s);
|
||||
if (paddr->s_addr == INADDR_NONE) {
|
||||
log_Printf(LogWARN, "ParseAddr: %s: Bad address\n", s);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (cp && *++cp) {
|
||||
bits = strtol(cp, &wp, 0);
|
||||
if (cp == wp || bits < 0 || bits > 32) {
|
||||
log_Printf(LogWARN, "ParseAddr: bad mask width.\n");
|
||||
return 0;
|
||||
}
|
||||
} else if (paddr->s_addr == INADDR_ANY)
|
||||
/* An IP of 0.0.0.0 without a width is anything */
|
||||
bits = 0;
|
||||
else
|
||||
/* If a valid IP is given without a width, assume 32 bits */
|
||||
bits = 32;
|
||||
|
||||
if (pwidth)
|
||||
*pwidth = bits;
|
||||
|
||||
if (pmask) {
|
||||
if (paddr->s_addr == INADDR_ANY)
|
||||
pmask->s_addr = INADDR_ANY;
|
||||
else
|
||||
*pmask = bits2mask(bits);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
ParsePort(const char *service, int proto)
|
||||
ParsePort(const char *service, const char *proto)
|
||||
{
|
||||
const char *protocol_name;
|
||||
char *cp;
|
||||
struct servent *servent;
|
||||
char *cp;
|
||||
int port;
|
||||
|
||||
switch (proto) {
|
||||
case P_IPIP:
|
||||
protocol_name = "ipip";
|
||||
break;
|
||||
case P_UDP:
|
||||
protocol_name = "udp";
|
||||
break;
|
||||
case P_TCP:
|
||||
protocol_name = "tcp";
|
||||
break;
|
||||
default:
|
||||
protocol_name = 0;
|
||||
}
|
||||
|
||||
servent = getservbyname(service, protocol_name);
|
||||
servent = getservbyname(service, proto);
|
||||
if (servent != 0)
|
||||
return ntohs(servent->s_port);
|
||||
|
||||
@ -189,7 +97,8 @@ ParsePort(const char *service, int proto)
|
||||
* ICMP Syntax: src eq icmp_message_type
|
||||
*/
|
||||
static int
|
||||
ParseIcmp(int argc, char const *const *argv, struct filterent *tgt)
|
||||
ParseIcmp(int argc, char const *const *argv, const struct protoent *pe,
|
||||
struct filterent *tgt)
|
||||
{
|
||||
int type;
|
||||
char *cp;
|
||||
@ -197,7 +106,7 @@ ParseIcmp(int argc, char const *const *argv, struct filterent *tgt)
|
||||
switch (argc) {
|
||||
case 0:
|
||||
/* permit/deny all ICMP types */
|
||||
tgt->f_srcop = OP_NONE;
|
||||
tgt->f_srcop = tgt->f_dstop = OP_NONE;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
@ -209,6 +118,7 @@ ParseIcmp(int argc, char const *const *argv, struct filterent *tgt)
|
||||
}
|
||||
tgt->f_srcop = OP_EQ;
|
||||
tgt->f_srcport = type;
|
||||
tgt->f_dstop = OP_NONE;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -223,7 +133,7 @@ ParseIcmp(int argc, char const *const *argv, struct filterent *tgt)
|
||||
* UDP Syntax: [src op port] [dst op port]
|
||||
*/
|
||||
static int
|
||||
ParseUdpOrTcp(int argc, char const *const *argv, int proto,
|
||||
ParseUdpOrTcp(int argc, char const *const *argv, const struct protoent *pe,
|
||||
struct filterent *tgt)
|
||||
{
|
||||
tgt->f_srcop = tgt->f_dstop = OP_NONE;
|
||||
@ -232,10 +142,12 @@ ParseUdpOrTcp(int argc, char const *const *argv, int proto,
|
||||
if (argc >= 3 && !strcmp(*argv, "src")) {
|
||||
tgt->f_srcop = filter_Nam2Op(argv[1]);
|
||||
if (tgt->f_srcop == OP_NONE) {
|
||||
log_Printf(LogWARN, "ParseUdpOrTcp: bad operation\n");
|
||||
log_Printf(LogWARN, "ParseUdpOrTcp: bad operator\n");
|
||||
return 0;
|
||||
}
|
||||
tgt->f_srcport = ParsePort(argv[2], proto);
|
||||
if (pe == NULL)
|
||||
return 0;
|
||||
tgt->f_srcport = ParsePort(argv[2], pe->p_name);
|
||||
if (tgt->f_srcport == 0)
|
||||
return 0;
|
||||
argc -= 3;
|
||||
@ -245,17 +157,19 @@ ParseUdpOrTcp(int argc, char const *const *argv, int proto,
|
||||
if (argc >= 3 && !strcmp(argv[0], "dst")) {
|
||||
tgt->f_dstop = filter_Nam2Op(argv[1]);
|
||||
if (tgt->f_dstop == OP_NONE) {
|
||||
log_Printf(LogWARN, "ParseUdpOrTcp: bad operation\n");
|
||||
log_Printf(LogWARN, "ParseUdpOrTcp: bad operator\n");
|
||||
return 0;
|
||||
}
|
||||
tgt->f_dstport = ParsePort(argv[2], proto);
|
||||
if (pe == NULL)
|
||||
return 0;
|
||||
tgt->f_dstport = ParsePort(argv[2], pe->p_name);
|
||||
if (tgt->f_dstport == 0)
|
||||
return 0;
|
||||
argc -= 3;
|
||||
argv += 3;
|
||||
}
|
||||
|
||||
if (proto == P_TCP) {
|
||||
if (pe && pe->p_proto == IPPROTO_TCP) {
|
||||
for (; argc > 0; argc--, argv++)
|
||||
if (!strcmp(*argv, "estab"))
|
||||
tgt->f_estab = 1;
|
||||
@ -276,64 +190,33 @@ ParseUdpOrTcp(int argc, char const *const *argv, int proto,
|
||||
}
|
||||
|
||||
static int
|
||||
ParseIgmp(int argc, char const * const *argv, struct filterent *tgt)
|
||||
ParseGeneric(int argc, char const * const *argv, const struct protoent *pe,
|
||||
struct filterent *tgt)
|
||||
{
|
||||
/*
|
||||
* Filter currently is a catch-all. Requests are either permitted or
|
||||
* dropped.
|
||||
*/
|
||||
if (argc != 0) {
|
||||
log_Printf(LogWARN, "ParseIgmp: Too many parameters\n");
|
||||
log_Printf(LogWARN, "ParseGeneric: Too many parameters\n");
|
||||
return 0;
|
||||
} else
|
||||
tgt->f_srcop = OP_NONE;
|
||||
tgt->f_srcop = tgt->f_dstop = OP_NONE;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef P_GRE
|
||||
static int
|
||||
ParseGRE(int argc, char const * const *argv, struct filterent *tgt)
|
||||
{
|
||||
/*
|
||||
* Filter currently is a catch-all. Requests are either permitted or
|
||||
* dropped.
|
||||
*/
|
||||
if (argc != 0) {
|
||||
log_Printf(LogWARN, "ParseGRE: Too many parameters\n");
|
||||
return 0;
|
||||
} else
|
||||
tgt->f_srcop = OP_NONE;
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef P_OSPF
|
||||
static int
|
||||
ParseOspf(int argc, char const * const *argv, struct filterent *tgt)
|
||||
{
|
||||
/*
|
||||
* Filter currently is a catch-all. Requests are either permitted or
|
||||
* dropped.
|
||||
*/
|
||||
if (argc != 0) {
|
||||
log_Printf(LogWARN, "ParseOspf: Too many parameters\n");
|
||||
return 0;
|
||||
} else
|
||||
tgt->f_srcop = OP_NONE;
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static unsigned
|
||||
addrtype(const char *addr)
|
||||
{
|
||||
if (!strncasecmp(addr, "MYADDR", 6) && (addr[6] == '\0' || addr[6] == '/'))
|
||||
return T_MYADDR;
|
||||
if (!strncasecmp(addr, "MYADDR6", 7) && (addr[7] == '\0' || addr[7] == '/'))
|
||||
return T_MYADDR6;
|
||||
if (!strncasecmp(addr, "HISADDR", 7) && (addr[7] == '\0' || addr[7] == '/'))
|
||||
return T_HISADDR;
|
||||
if (!strncasecmp(addr, "HISADDR6", 8) && (addr[8] == '\0' || addr[8] == '/'))
|
||||
return T_HISADDR6;
|
||||
if (!strncasecmp(addr, "DNS0", 4) && (addr[4] == '\0' || addr[4] == '/'))
|
||||
return T_DNS0;
|
||||
if (!strncasecmp(addr, "DNS1", 4) && (addr[4] == '\0' || addr[4] == '/'))
|
||||
@ -343,7 +226,7 @@ addrtype(const char *addr)
|
||||
}
|
||||
|
||||
static const char *
|
||||
addrstr(struct in_addr addr, unsigned type)
|
||||
addrstr(struct ncprange *addr, unsigned type)
|
||||
{
|
||||
switch (type) {
|
||||
case T_MYADDR:
|
||||
@ -355,30 +238,17 @@ addrstr(struct in_addr addr, unsigned type)
|
||||
case T_DNS1:
|
||||
return "DNS1";
|
||||
}
|
||||
return inet_ntoa(addr);
|
||||
}
|
||||
|
||||
static const char *
|
||||
maskstr(int bits)
|
||||
{
|
||||
static char str[4];
|
||||
|
||||
if (bits == 32)
|
||||
*str = '\0';
|
||||
else
|
||||
snprintf(str, sizeof str, "/%d", bits);
|
||||
|
||||
return str;
|
||||
return ncprange_ntoa(addr);
|
||||
}
|
||||
|
||||
static int
|
||||
Parse(struct ipcp *ipcp, int argc, char const *const *argv,
|
||||
struct filterent *ofp)
|
||||
filter_Parse(struct ncp *ncp, int argc, char const *const *argv,
|
||||
struct filterent *ofp)
|
||||
{
|
||||
int action, proto;
|
||||
int val, ruleno;
|
||||
struct filterent fe;
|
||||
struct protoent *pe;
|
||||
char *wp;
|
||||
struct filterent filterdata;
|
||||
int action, family, ruleno, val, width;
|
||||
|
||||
ruleno = strtol(*argv, &wp, 0);
|
||||
if (*argv == wp || ruleno >= MAXFILTERS) {
|
||||
@ -401,8 +271,7 @@ Parse(struct ipcp *ipcp, int argc, char const *const *argv,
|
||||
}
|
||||
argv++;
|
||||
|
||||
proto = P_NONE;
|
||||
memset(&filterdata, '\0', sizeof filterdata);
|
||||
memset(&fe, '\0', sizeof fe);
|
||||
|
||||
val = strtol(*argv, &wp, 0);
|
||||
if (!*wp && val >= 0 && val < MAXFILTERS) {
|
||||
@ -420,56 +289,71 @@ Parse(struct ipcp *ipcp, int argc, char const *const *argv,
|
||||
ofp->f_action = A_NONE;
|
||||
return 1;
|
||||
} else {
|
||||
log_Printf(LogWARN, "Parse: bad action: %s\n", *argv);
|
||||
log_Printf(LogWARN, "Parse: %s: bad action\n", *argv);
|
||||
return 0;
|
||||
}
|
||||
filterdata.f_action = action;
|
||||
fe.f_action = action;
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
if (argc && argv[0][0] == '!' && !argv[0][1]) {
|
||||
filterdata.f_invert = 1;
|
||||
fe.f_invert = 1;
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
|
||||
proto = filter_Nam2Proto(argc, argv);
|
||||
if (proto == P_NONE) {
|
||||
if (!argc)
|
||||
log_Printf(LogWARN, "Parse: address/mask is expected.\n");
|
||||
else if (ParseAddr(ipcp, *argv, &filterdata.f_src.ipaddr,
|
||||
&filterdata.f_src.mask, &filterdata.f_src.width)) {
|
||||
filterdata.f_srctype = addrtype(*argv);
|
||||
ncprange_init(&fe.f_src);
|
||||
ncprange_init(&fe.f_dst);
|
||||
|
||||
if (argc == 0)
|
||||
pe = NULL;
|
||||
else if ((pe = getprotobyname(*argv)) == NULL && strcmp(*argv, "all") != 0) {
|
||||
if (argc < 2) {
|
||||
log_Printf(LogWARN, "Parse: Protocol or address pair expected\n");
|
||||
return 0;
|
||||
} else if (strcasecmp(*argv, "any") == 0 ||
|
||||
ncprange_aton(&fe.f_src, ncp, *argv)) {
|
||||
family = ncprange_family(&fe.f_src);
|
||||
if (!ncprange_getwidth(&fe.f_src, &width))
|
||||
width = 0;
|
||||
if (width == 0)
|
||||
ncprange_init(&fe.f_src);
|
||||
fe.f_srctype = addrtype(*argv);
|
||||
argc--;
|
||||
argv++;
|
||||
proto = filter_Nam2Proto(argc, argv);
|
||||
if (!argc)
|
||||
log_Printf(LogWARN, "Parse: address/mask is expected.\n");
|
||||
else if (proto == P_NONE) {
|
||||
if (ParseAddr(ipcp, *argv, &filterdata.f_dst.ipaddr,
|
||||
&filterdata.f_dst.mask, &filterdata.f_dst.width)) {
|
||||
filterdata.f_dsttype = addrtype(*argv);
|
||||
argc--;
|
||||
argv++;
|
||||
} else
|
||||
filterdata.f_dsttype = T_ADDR;
|
||||
if (argc) {
|
||||
proto = filter_Nam2Proto(argc, argv);
|
||||
if (proto == P_NONE) {
|
||||
log_Printf(LogWARN, "Parse: %s: Invalid protocol\n", *argv);
|
||||
return 0;
|
||||
} else {
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
}
|
||||
|
||||
if (strcasecmp(*argv, "any") == 0 ||
|
||||
ncprange_aton(&fe.f_dst, ncp, *argv)) {
|
||||
if (ncprange_family(&fe.f_dst) != AF_UNSPEC &&
|
||||
ncprange_family(&fe.f_src) != AF_UNSPEC &&
|
||||
family != ncprange_family(&fe.f_dst)) {
|
||||
log_Printf(LogWARN, "Parse: src and dst address families differ\n");
|
||||
return 0;
|
||||
}
|
||||
if (!ncprange_getwidth(&fe.f_dst, &width))
|
||||
width = 0;
|
||||
if (width == 0)
|
||||
ncprange_init(&fe.f_dst);
|
||||
fe.f_dsttype = addrtype(*argv);
|
||||
argc--;
|
||||
argv++;
|
||||
} else {
|
||||
argc--;
|
||||
argv++;
|
||||
log_Printf(LogWARN, "Parse: Protocol or address pair expected\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc) {
|
||||
if ((pe = getprotobyname(*argv)) == NULL && strcmp(*argv, "all") != 0) {
|
||||
log_Printf(LogWARN, "Parse: %s: Protocol expected\n", *argv);
|
||||
return 0;
|
||||
} else {
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log_Printf(LogWARN, "Parse: Address/protocol expected.\n");
|
||||
log_Printf(LogWARN, "Parse: Protocol or address pair expected\n");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
@ -477,60 +361,49 @@ Parse(struct ipcp *ipcp, int argc, char const *const *argv,
|
||||
argv++;
|
||||
}
|
||||
|
||||
if (argc >= 2 && strcmp(argv[argc - 2], "timeout") == 0) {
|
||||
filterdata.timeout = strtoul(argv[argc - 1], NULL, 10);
|
||||
if (argc >= 2 && strcmp(*argv, "timeout") == 0) {
|
||||
fe.timeout = strtoul(argv[1], NULL, 10);
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
}
|
||||
|
||||
val = 1;
|
||||
filterdata.f_proto = proto;
|
||||
fe.f_proto = (pe == NULL) ? 0 : pe->p_proto;
|
||||
|
||||
switch (proto) {
|
||||
case P_TCP:
|
||||
val = ParseUdpOrTcp(argc, argv, P_TCP, &filterdata);
|
||||
break;
|
||||
case P_UDP:
|
||||
val = ParseUdpOrTcp(argc, argv, P_UDP, &filterdata);
|
||||
break;
|
||||
case P_IPIP:
|
||||
val = ParseUdpOrTcp(argc, argv, P_IPIP, &filterdata);
|
||||
break;
|
||||
case P_ICMP:
|
||||
val = ParseIcmp(argc, argv, &filterdata);
|
||||
break;
|
||||
case P_IGMP:
|
||||
val = ParseIgmp(argc, argv, &filterdata);
|
||||
break;
|
||||
#ifdef P_OSPF
|
||||
case P_OSPF:
|
||||
val = ParseOspf(argc, argv, &filterdata);
|
||||
break;
|
||||
switch (fe.f_proto) {
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_IPIP:
|
||||
#ifndef NOINET6
|
||||
case IPPROTO_IPV6:
|
||||
#endif
|
||||
#ifdef P_GRE
|
||||
case P_GRE:
|
||||
val = ParseGRE(argc, argv, &filterdata);
|
||||
val = ParseUdpOrTcp(argc, argv, pe, &fe);
|
||||
break;
|
||||
case IPPROTO_ICMP:
|
||||
#ifndef NOINET6
|
||||
case IPPROTO_ICMPV6:
|
||||
#endif
|
||||
val = ParseIcmp(argc, argv, pe, &fe);
|
||||
break;
|
||||
default:
|
||||
val = ParseGeneric(argc, argv, pe, &fe);
|
||||
break;
|
||||
}
|
||||
|
||||
log_Printf(LogDEBUG, "Parse: Src: %s\n", inet_ntoa(filterdata.f_src.ipaddr));
|
||||
log_Printf(LogDEBUG, "Parse: Src mask: %s\n",
|
||||
inet_ntoa(filterdata.f_src.mask));
|
||||
log_Printf(LogDEBUG, "Parse: Dst: %s\n", inet_ntoa(filterdata.f_dst.ipaddr));
|
||||
log_Printf(LogDEBUG, "Parse: Dst mask: %s\n",
|
||||
inet_ntoa(filterdata.f_dst.mask));
|
||||
log_Printf(LogDEBUG, "Parse: Proto = %d\n", proto);
|
||||
log_Printf(LogDEBUG, "Parse: Src: %s\n", ncprange_ntoa(&fe.f_src));
|
||||
log_Printf(LogDEBUG, "Parse: Dst: %s\n", ncprange_ntoa(&fe.f_dst));
|
||||
log_Printf(LogDEBUG, "Parse: Proto: %d\n", fe.f_proto);
|
||||
|
||||
log_Printf(LogDEBUG, "Parse: src: %s (%d)\n",
|
||||
filter_Op2Nam(filterdata.f_srcop), filterdata.f_srcport);
|
||||
filter_Op2Nam(fe.f_srcop), fe.f_srcport);
|
||||
log_Printf(LogDEBUG, "Parse: dst: %s (%d)\n",
|
||||
filter_Op2Nam(filterdata.f_dstop), filterdata.f_dstport);
|
||||
log_Printf(LogDEBUG, "Parse: estab: %u\n", filterdata.f_estab);
|
||||
log_Printf(LogDEBUG, "Parse: syn: %u\n", filterdata.f_syn);
|
||||
log_Printf(LogDEBUG, "Parse: finrst: %u\n", filterdata.f_finrst);
|
||||
filter_Op2Nam(fe.f_dstop), fe.f_dstport);
|
||||
log_Printf(LogDEBUG, "Parse: estab: %u\n", fe.f_estab);
|
||||
log_Printf(LogDEBUG, "Parse: syn: %u\n", fe.f_syn);
|
||||
log_Printf(LogDEBUG, "Parse: finrst: %u\n", fe.f_finrst);
|
||||
|
||||
if (val)
|
||||
*ofp = filterdata;
|
||||
*ofp = fe;
|
||||
|
||||
return val;
|
||||
}
|
||||
@ -557,7 +430,7 @@ filter_Set(struct cmdargs const *arg)
|
||||
return -1;
|
||||
}
|
||||
|
||||
Parse(&arg->bundle->ncp.ipcp, arg->argc - arg->argn - 1,
|
||||
filter_Parse(&arg->bundle->ncp, arg->argc - arg->argn - 1,
|
||||
arg->argv + arg->argn + 1, filter->rule);
|
||||
return 0;
|
||||
}
|
||||
@ -580,18 +453,29 @@ filter_Action2Nam(int act)
|
||||
static void
|
||||
doShowFilter(struct filterent *fp, struct prompt *prompt)
|
||||
{
|
||||
struct protoent *pe;
|
||||
int n;
|
||||
|
||||
for (n = 0; n < MAXFILTERS; n++, fp++) {
|
||||
if (fp->f_action != A_NONE) {
|
||||
prompt_Printf(prompt, " %2d %s", n, filter_Action2Nam(fp->f_action));
|
||||
prompt_Printf(prompt, "%c ", fp->f_invert ? '!' : ' ');
|
||||
prompt_Printf(prompt, "%s%s ", addrstr(fp->f_src.ipaddr, fp->f_srctype),
|
||||
maskstr(fp->f_src.width));
|
||||
prompt_Printf(prompt, "%s%s ", addrstr(fp->f_dst.ipaddr, fp->f_dsttype),
|
||||
maskstr(fp->f_dst.width));
|
||||
|
||||
if (ncprange_isset(&fp->f_src))
|
||||
prompt_Printf(prompt, "%s ", addrstr(&fp->f_src, fp->f_srctype));
|
||||
else
|
||||
prompt_Printf(prompt, "any ");
|
||||
|
||||
if (ncprange_isset(&fp->f_dst))
|
||||
prompt_Printf(prompt, "%s ", addrstr(&fp->f_dst, fp->f_dsttype));
|
||||
else
|
||||
prompt_Printf(prompt, "any ");
|
||||
|
||||
if (fp->f_proto) {
|
||||
prompt_Printf(prompt, "%s", filter_Proto2Nam(fp->f_proto));
|
||||
if ((pe = getprotobynumber(fp->f_proto)) == NULL)
|
||||
prompt_Printf(prompt, "P:%d", fp->f_proto);
|
||||
else
|
||||
prompt_Printf(prompt, "%s", pe->p_name);
|
||||
|
||||
if (fp->f_srcop)
|
||||
prompt_Printf(prompt, " src %s %d", filter_Op2Nam(fp->f_srcop),
|
||||
@ -605,7 +489,8 @@ doShowFilter(struct filterent *fp, struct prompt *prompt)
|
||||
prompt_Printf(prompt, " syn");
|
||||
if (fp->f_finrst)
|
||||
prompt_Printf(prompt, " finrst");
|
||||
}
|
||||
} else
|
||||
prompt_Printf(prompt, "all");
|
||||
if (fp->timeout != 0)
|
||||
prompt_Printf(prompt, " timeout %u", fp->timeout);
|
||||
prompt_Printf(prompt, "\n");
|
||||
@ -652,33 +537,6 @@ filter_Show(struct cmdargs const *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char * const protoname[] = {
|
||||
"none", "tcp", "udp", "icmp", "ospf", "igmp", "gre", "ipip"
|
||||
};
|
||||
|
||||
const char *
|
||||
filter_Proto2Nam(int proto)
|
||||
{
|
||||
if (proto >= sizeof protoname / sizeof protoname[0])
|
||||
return "unknown";
|
||||
return protoname[proto];
|
||||
}
|
||||
|
||||
static int
|
||||
filter_Nam2Proto(int argc, char const *const *argv)
|
||||
{
|
||||
int proto;
|
||||
|
||||
if (argc == 0)
|
||||
proto = 0;
|
||||
else
|
||||
for (proto = sizeof protoname / sizeof protoname[0] - 1; proto; proto--)
|
||||
if (!strcasecmp(*argv, protoname[proto]))
|
||||
break;
|
||||
|
||||
return proto;
|
||||
}
|
||||
|
||||
static const char * const opname[] = {"none", "eq", "gt", "lt"};
|
||||
|
||||
const char *
|
||||
@ -703,35 +561,47 @@ filter_Nam2Op(const char *cp)
|
||||
}
|
||||
|
||||
void
|
||||
filter_AdjustAddr(struct filter *filter, struct in_addr *my_ip,
|
||||
struct in_addr *peer_ip, struct in_addr dns[2])
|
||||
filter_AdjustAddr(struct filter *filter, struct ncpaddr *local,
|
||||
struct ncpaddr *remote, struct in_addr *dns)
|
||||
{
|
||||
struct filterent *fp;
|
||||
int n;
|
||||
|
||||
for (fp = filter->rule, n = 0; n < MAXFILTERS; fp++, n++)
|
||||
if (fp->f_action != A_NONE) {
|
||||
if (my_ip) {
|
||||
if (fp->f_srctype == T_MYADDR)
|
||||
fp->f_src.ipaddr = *my_ip;
|
||||
if (fp->f_dsttype == T_MYADDR)
|
||||
fp->f_dst.ipaddr = *my_ip;
|
||||
if (local) {
|
||||
if (fp->f_srctype == T_MYADDR && ncpaddr_family(local) == AF_INET)
|
||||
ncprange_sethost(&fp->f_src, local);
|
||||
if (fp->f_dsttype == T_MYADDR && ncpaddr_family(local) == AF_INET)
|
||||
ncprange_sethost(&fp->f_dst, local);
|
||||
#ifndef NOINET6
|
||||
if (fp->f_srctype == T_MYADDR6 && ncpaddr_family(local) == AF_INET6)
|
||||
ncprange_sethost(&fp->f_src, local);
|
||||
if (fp->f_dsttype == T_MYADDR6 && ncpaddr_family(local) == AF_INET6)
|
||||
ncprange_sethost(&fp->f_dst, local);
|
||||
#endif
|
||||
}
|
||||
if (peer_ip) {
|
||||
if (fp->f_srctype == T_HISADDR)
|
||||
fp->f_src.ipaddr = *peer_ip;
|
||||
if (fp->f_dsttype == T_HISADDR)
|
||||
fp->f_dst.ipaddr = *peer_ip;
|
||||
if (remote) {
|
||||
if (fp->f_srctype == T_HISADDR && ncpaddr_family(remote) == AF_INET)
|
||||
ncprange_sethost(&fp->f_src, remote);
|
||||
if (fp->f_dsttype == T_HISADDR && ncpaddr_family(remote) == AF_INET)
|
||||
ncprange_sethost(&fp->f_dst, remote);
|
||||
#ifndef NOINET6
|
||||
if (fp->f_srctype == T_HISADDR6 && ncpaddr_family(remote) == AF_INET6)
|
||||
ncprange_sethost(&fp->f_src, remote);
|
||||
if (fp->f_dsttype == T_HISADDR6 && ncpaddr_family(remote) == AF_INET6)
|
||||
ncprange_sethost(&fp->f_dst, remote);
|
||||
#endif
|
||||
}
|
||||
if (dns) {
|
||||
if (fp->f_srctype == T_DNS0)
|
||||
fp->f_src.ipaddr = dns[0];
|
||||
ncprange_setip4host(&fp->f_src, dns[0]);
|
||||
if (fp->f_dsttype == T_DNS0)
|
||||
fp->f_dst.ipaddr = dns[0];
|
||||
ncprange_setip4host(&fp->f_dst, dns[0]);
|
||||
if (fp->f_srctype == T_DNS1)
|
||||
fp->f_src.ipaddr = dns[1];
|
||||
ncprange_setip4host(&fp->f_src, dns[1]);
|
||||
if (fp->f_dsttype == T_DNS1)
|
||||
fp->f_dst.ipaddr = dns[1];
|
||||
ncprange_setip4host(&fp->f_dst, dns[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,22 +28,6 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/* Known protocols - f_proto */
|
||||
#define P_NONE 0
|
||||
#define P_TCP 1
|
||||
#define P_UDP 2
|
||||
#define P_ICMP 3
|
||||
#ifdef IPPROTO_OSPFIGP
|
||||
#define P_OSPF 4
|
||||
#endif
|
||||
#define P_IGMP 5
|
||||
#ifdef IPPROTO_GRE
|
||||
#define P_GRE 6
|
||||
#endif
|
||||
#define P_ESP 7
|
||||
#define P_AH 8
|
||||
#define P_IPIP 9
|
||||
|
||||
/* Operations - f_srcop, f_dstop */
|
||||
#define OP_NONE 0
|
||||
#define OP_EQ 1
|
||||
@ -53,9 +37,11 @@
|
||||
/* srctype or dsttype */
|
||||
#define T_ADDR 0
|
||||
#define T_MYADDR 1
|
||||
#define T_HISADDR 2
|
||||
#define T_DNS0 3
|
||||
#define T_DNS1 4
|
||||
#define T_MYADDR6 2
|
||||
#define T_HISADDR 3
|
||||
#define T_HISADDR6 4
|
||||
#define T_DNS0 5
|
||||
#define T_DNS1 6
|
||||
|
||||
/*
|
||||
* There's a struct filterent for each possible filter rule. The
|
||||
@ -63,17 +49,12 @@
|
||||
* them) - which is also conveniently a power of 2 (32 bytes) on
|
||||
* architectures where sizeof(int)==4 (this makes indexing faster).
|
||||
*
|
||||
* f_action and f_proto only need to be 6 and 3 bits, respectively,
|
||||
* but making them 8 bits allows them to be efficently accessed using
|
||||
* byte operations as well as allowing space for future expansion
|
||||
* (expanding MAXFILTERS or converting f_proto IPPROTO_... values).
|
||||
*
|
||||
* Note that there are four free bits in the initial word for future
|
||||
* extensions.
|
||||
*/
|
||||
struct filterent {
|
||||
unsigned f_action : 8; /* Filtering action: goto or A_... */
|
||||
unsigned f_proto : 8; /* Protocol: P_... */
|
||||
int f_proto; /* Protocol: getprotoby*() */
|
||||
unsigned f_action : 8; /* Filtering action: goto or A_... */
|
||||
unsigned f_srcop : 2; /* Source port operation: OP_... */
|
||||
unsigned f_dstop : 2; /* Destination port operation: OP_... */
|
||||
unsigned f_srctype : 3; /* T_ value of src */
|
||||
@ -82,8 +63,8 @@ struct filterent {
|
||||
unsigned f_syn : 1; /* Check TCP SYN bit */
|
||||
unsigned f_finrst : 1; /* Check TCP FIN/RST bits */
|
||||
unsigned f_invert : 1; /* true to complement match */
|
||||
struct in_range f_src; /* Source address and mask */
|
||||
struct in_range f_dst; /* Destination address and mask */
|
||||
struct ncprange f_src; /* Source address and mask */
|
||||
struct ncprange f_dst; /* Destination address and mask */
|
||||
u_short f_srcport; /* Source port, compared with f_srcop */
|
||||
u_short f_dstport; /* Destination port, compared with f_dstop */
|
||||
unsigned timeout; /* Keep alive value for passed packet */
|
||||
@ -112,13 +93,9 @@ struct filter {
|
||||
struct ipcp;
|
||||
struct cmdargs;
|
||||
|
||||
extern int ParseAddr(struct ipcp *, const char *, struct in_addr *,
|
||||
struct in_addr *, int *);
|
||||
extern int filter_Show(struct cmdargs const *);
|
||||
extern int filter_Set(struct cmdargs const *);
|
||||
extern const char * filter_Action2Nam(int);
|
||||
extern const char *filter_Proto2Nam(int);
|
||||
extern const char *filter_Op2Nam(int);
|
||||
extern struct in_addr bits2mask(int);
|
||||
extern void filter_AdjustAddr(struct filter *, struct in_addr *,
|
||||
struct in_addr *, struct in_addr [2]);
|
||||
extern void filter_AdjustAddr(struct filter *, struct ncpaddr *,
|
||||
struct ncpaddr *, struct in_addr *);
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <string.h>
|
||||
@ -49,6 +50,8 @@
|
||||
#include "hdlc.h"
|
||||
#include "throughput.h"
|
||||
#include "slcompress.h"
|
||||
#include "ncpaddr.h"
|
||||
#include "ip.h"
|
||||
#include "ipcp.h"
|
||||
#include "filter.h"
|
||||
#include "descriptor.h"
|
||||
@ -59,6 +62,8 @@
|
||||
#ifndef NORADIUS
|
||||
#include "radius.h"
|
||||
#endif
|
||||
#include "ipv6cp.h"
|
||||
#include "ncp.h"
|
||||
#include "bundle.h"
|
||||
#include "async.h"
|
||||
#include "physical.h"
|
||||
@ -508,7 +513,6 @@ FsmRecvConfigReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
|
||||
return;
|
||||
case ST_OPENED:
|
||||
(*fp->fn->LayerDown)(fp);
|
||||
(*fp->parent->LayerDown)(fp->parent->object, fp);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -559,6 +563,7 @@ FsmRecvConfigReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
|
||||
NewState(fp, ST_ACKSENT);
|
||||
else
|
||||
NewState(fp, ST_REQSENT);
|
||||
(*fp->parent->LayerDown)(fp->parent->object, fp);
|
||||
break;
|
||||
case ST_REQSENT:
|
||||
if (ackaction)
|
||||
@ -889,6 +894,15 @@ FsmRecvProtoRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)
|
||||
fsm_Close(&fp->bundle->ncp.ipcp.fsm);
|
||||
}
|
||||
break;
|
||||
#ifndef NOINET6
|
||||
case PROTO_IPV6CP:
|
||||
if (fp->proto == PROTO_LCP) {
|
||||
log_Printf(LogPHASE, "%s: IPV6CP protocol reject closes IPV6CP !\n",
|
||||
fp->link->name);
|
||||
fsm_Close(&fp->bundle->ncp.ipv6cp.fsm);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case PROTO_MP:
|
||||
if (fp->proto == PROTO_LCP) {
|
||||
struct lcp *lcp = fsm2lcp(fp);
|
||||
|
@ -209,6 +209,7 @@ static struct {
|
||||
{ 0x0051, 0x0051, "KNX Bridging Data" },
|
||||
{ 0x0053, 0x0053, "Encryption" },
|
||||
{ 0x0055, 0x0055, "Individual Link Encryption" },
|
||||
{ 0x0057, 0x0057, "Internet Protocol V6" },
|
||||
{ 0x006f, 0x006f, "Stampede Bridging" },
|
||||
{ 0x0071, 0x0071, "BAP Bandwidth Allocation Protocol" },
|
||||
{ 0x0073, 0x0073, "MP+ Protocol" },
|
||||
@ -259,6 +260,7 @@ static struct {
|
||||
{ 0x8051, 0x8051, "KNX Bridging Control Protocol" },
|
||||
{ 0x8053, 0x8053, "Encryption Control Protocol" },
|
||||
{ 0x8055, 0x8055, "Individual Link Encryption Control Protocol" },
|
||||
{ 0x8057, 0x8057, "Internet Protocol V6 Control Protocol" },
|
||||
{ 0x806f, 0x806f, "Stampede Bridging Control Protocol" },
|
||||
{ 0x8073, 0x8073, "MP+ Control Protocol" },
|
||||
{ 0x8071, 0x8071, "BACP Bandwidth Allocation Control Protocol" },
|
||||
|
@ -31,10 +31,15 @@
|
||||
#include <netinet/in.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_var.h>
|
||||
#include <net/route.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in_var.h>
|
||||
#include <netinet/ip.h>
|
||||
#ifndef NOINET6
|
||||
#include <netinet6/nd6.h>
|
||||
#endif
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <errno.h>
|
||||
@ -60,6 +65,8 @@
|
||||
#include "throughput.h"
|
||||
#include "slcompress.h"
|
||||
#include "descriptor.h"
|
||||
#include "ncpaddr.h"
|
||||
#include "ip.h"
|
||||
#include "ipcp.h"
|
||||
#include "filter.h"
|
||||
#include "lcp.h"
|
||||
@ -69,32 +76,17 @@
|
||||
#ifndef NORADIUS
|
||||
#include "radius.h"
|
||||
#endif
|
||||
#include "ipv6cp.h"
|
||||
#include "ncp.h"
|
||||
#include "bundle.h"
|
||||
#include "prompt.h"
|
||||
#include "iface.h"
|
||||
|
||||
|
||||
static int
|
||||
bitsinmask(struct in_addr mask)
|
||||
{
|
||||
u_int32_t bitmask, maskaddr;
|
||||
int bits;
|
||||
|
||||
bitmask = 0xffffffff;
|
||||
maskaddr = ntohl(mask.s_addr);
|
||||
for (bits = 32; bits >= 0; bits--) {
|
||||
if (maskaddr == bitmask)
|
||||
break;
|
||||
bitmask &= ~(1 << (32 - bits));
|
||||
}
|
||||
|
||||
return bits;
|
||||
}
|
||||
|
||||
struct iface *
|
||||
iface_Create(const char *name)
|
||||
{
|
||||
int mib[6], s, maxtries, err;
|
||||
int mib[6], maxtries, err;
|
||||
size_t needed, namelen;
|
||||
char *buf, *ptr, *end;
|
||||
struct if_msghdr *ifm;
|
||||
@ -104,12 +96,6 @@ iface_Create(const char *name)
|
||||
struct iface *iface;
|
||||
struct iface_addr *addr;
|
||||
|
||||
s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (s < 0) {
|
||||
fprintf(stderr, "iface_Create: socket(): %s\n", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mib[0] = CTL_NET;
|
||||
mib[1] = PF_ROUTE;
|
||||
mib[2] = 0;
|
||||
@ -122,20 +108,17 @@ iface_Create(const char *name)
|
||||
do {
|
||||
if (maxtries-- == 0 || (err && err != ENOMEM)) {
|
||||
fprintf(stderr, "iface_Create: sysctl: %s\n", strerror(err));
|
||||
close(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
|
||||
fprintf(stderr, "iface_Create: sysctl: estimate: %s\n",
|
||||
strerror(errno));
|
||||
close(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((buf = (char *)malloc(needed)) == NULL) {
|
||||
fprintf(stderr, "iface_Create: malloc failed: %s\n", strerror(errno));
|
||||
close(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -166,8 +149,8 @@ iface_Create(const char *name)
|
||||
iface->index = ifm->ifm_index;
|
||||
iface->flags = ifm->ifm_flags;
|
||||
iface->mtu = 0;
|
||||
iface->in_addrs = 0;
|
||||
iface->in_addr = NULL;
|
||||
iface->addrs = 0;
|
||||
iface->addr = NULL;
|
||||
}
|
||||
ptr += ifm->ifm_msglen; /* First ifa_msghdr */
|
||||
for (; ptr < end; ptr += ifam->ifam_msglen) {
|
||||
@ -180,255 +163,350 @@ iface_Create(const char *name)
|
||||
/* Found a configured interface ! */
|
||||
iface_ParseHdr(ifam, sa);
|
||||
|
||||
if (sa[RTAX_IFA] && sa[RTAX_IFA]->sa_family == AF_INET) {
|
||||
if (sa[RTAX_IFA] && (sa[RTAX_IFA]->sa_family == AF_INET
|
||||
#ifndef NOINET6
|
||||
|| sa[RTAX_IFA]->sa_family == AF_INET6
|
||||
#endif
|
||||
)) {
|
||||
/* Record the address */
|
||||
|
||||
addr = (struct iface_addr *)realloc
|
||||
(iface->in_addr, (iface->in_addrs + 1) * sizeof iface->in_addr[0]);
|
||||
addr = (struct iface_addr *)
|
||||
realloc(iface->addr, (iface->addrs + 1) * sizeof iface->addr[0]);
|
||||
if (addr == NULL)
|
||||
break;
|
||||
iface->in_addr = addr;
|
||||
iface->addr = addr;
|
||||
|
||||
addr += iface->in_addrs;
|
||||
iface->in_addrs++;
|
||||
|
||||
addr->ifa = ((struct sockaddr_in *)sa[RTAX_IFA])->sin_addr;
|
||||
addr += iface->addrs;
|
||||
iface->addrs++;
|
||||
|
||||
ncprange_setsa(&addr->ifa, sa[RTAX_IFA], sa[RTAX_NETMASK]);
|
||||
if (sa[RTAX_BRD])
|
||||
addr->brd = ((struct sockaddr_in *)sa[RTAX_BRD])->sin_addr;
|
||||
ncpaddr_setsa(&addr->peer, sa[RTAX_BRD]);
|
||||
else
|
||||
addr->brd.s_addr = INADDR_ANY;
|
||||
|
||||
if (sa[RTAX_NETMASK])
|
||||
addr->mask = ((struct sockaddr_in *)sa[RTAX_NETMASK])->sin_addr;
|
||||
else
|
||||
addr->mask.s_addr = INADDR_ANY;
|
||||
|
||||
addr->bits = bitsinmask(addr->mask);
|
||||
ncpaddr_init(&addr->peer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(buf);
|
||||
close(s);
|
||||
|
||||
return iface;
|
||||
}
|
||||
|
||||
static void
|
||||
iface_addr_Zap(const char *name, struct iface_addr *addr)
|
||||
static int
|
||||
iface_addr_Zap(const char *name, struct iface_addr *addr, int s)
|
||||
{
|
||||
struct ifaliasreq ifra;
|
||||
struct sockaddr_in *me, *peer;
|
||||
int s;
|
||||
#ifndef NOINET6
|
||||
struct in6_aliasreq ifra6;
|
||||
#endif
|
||||
struct sockaddr_in *me4, *msk4, *peer4;
|
||||
struct sockaddr_storage ssme, sspeer, ssmsk;
|
||||
int res;
|
||||
|
||||
s = ID0socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (s < 0)
|
||||
log_Printf(LogERROR, "iface_addr_Zap: socket(): %s\n", strerror(errno));
|
||||
else {
|
||||
ncprange_getsa(&addr->ifa, &ssme, &ssmsk);
|
||||
ncpaddr_getsa(&addr->peer, &sspeer);
|
||||
res = 0;
|
||||
|
||||
switch (ncprange_family(&addr->ifa)) {
|
||||
case AF_INET:
|
||||
memset(&ifra, '\0', sizeof ifra);
|
||||
strncpy(ifra.ifra_name, name, sizeof ifra.ifra_name - 1);
|
||||
me = (struct sockaddr_in *)&ifra.ifra_addr;
|
||||
peer = (struct sockaddr_in *)&ifra.ifra_broadaddr;
|
||||
me->sin_family = peer->sin_family = AF_INET;
|
||||
me->sin_len = peer->sin_len = sizeof(struct sockaddr_in);
|
||||
me->sin_addr = addr->ifa;
|
||||
peer->sin_addr = addr->brd;
|
||||
log_Printf(LogDEBUG, "Delete %s\n", inet_ntoa(addr->ifa));
|
||||
if (ID0ioctl(s, SIOCDIFADDR, &ifra) < 0)
|
||||
log_Printf(LogWARN, "iface_addr_Zap: ioctl(SIOCDIFADDR, %s): %s\n",
|
||||
inet_ntoa(addr->ifa), strerror(errno));
|
||||
close(s);
|
||||
|
||||
me4 = (struct sockaddr_in *)&ifra.ifra_addr;
|
||||
memcpy(me4, &ssme, sizeof *me4);
|
||||
|
||||
msk4 = (struct sockaddr_in *)&ifra.ifra_mask;
|
||||
memcpy(msk4, &ssmsk, sizeof *msk4);
|
||||
|
||||
peer4 = (struct sockaddr_in *)&ifra.ifra_broadaddr;
|
||||
if (ncpaddr_family(&addr->peer) == AF_UNSPEC) {
|
||||
peer4->sin_family = AF_INET;
|
||||
peer4->sin_len = sizeof(*peer4);
|
||||
peer4->sin_addr.s_addr = INADDR_NONE;
|
||||
} else
|
||||
memcpy(peer4, &sspeer, sizeof *peer4);
|
||||
|
||||
res = ID0ioctl(s, SIOCDIFADDR, &ifra);
|
||||
break;
|
||||
|
||||
#ifndef NOINET6
|
||||
case AF_INET6:
|
||||
memset(&ifra6, '\0', sizeof ifra6);
|
||||
strncpy(ifra6.ifra_name, name, sizeof ifra6.ifra_name - 1);
|
||||
|
||||
memcpy(&ifra6.ifra_addr, &ssme, sizeof ifra6.ifra_addr);
|
||||
memcpy(&ifra6.ifra_prefixmask, &ssmsk, sizeof ifra6.ifra_prefixmask);
|
||||
ifra6.ifra_prefixmask.sin6_family = AF_UNSPEC;
|
||||
if (ncpaddr_family(&addr->peer) == AF_UNSPEC)
|
||||
ifra6.ifra_dstaddr.sin6_family = AF_UNSPEC;
|
||||
else
|
||||
memcpy(&ifra6.ifra_dstaddr, &sspeer, sizeof ifra6.ifra_dstaddr);
|
||||
ifra6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
|
||||
ifra6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
|
||||
|
||||
res = ID0ioctl(s, SIOCDIFADDR_IN6, &ifra6);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (res == -1) {
|
||||
char dst[40];
|
||||
const char *end =
|
||||
#ifndef NOINET6
|
||||
ncprange_family(&addr->ifa) == AF_INET6 ? "_IN6" :
|
||||
#endif
|
||||
"";
|
||||
|
||||
if (ncpaddr_family(&addr->peer) == AF_UNSPEC)
|
||||
log_Printf(LogWARN, "iface rm: ioctl(SIOCDIFADDR%s, %s): %s\n",
|
||||
end, ncprange_ntoa(&addr->ifa), strerror(errno));
|
||||
else {
|
||||
snprintf(dst, sizeof dst, "%s", ncpaddr_ntoa(&addr->peer));
|
||||
log_Printf(LogWARN, "iface rm: ioctl(SIOCDIFADDR%s, %s -> %s): %s\n",
|
||||
end, ncprange_ntoa(&addr->ifa), dst, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
return res != -1;
|
||||
}
|
||||
|
||||
static void
|
||||
iface_addr_Add(const char *name, struct iface_addr *addr, int s)
|
||||
{
|
||||
struct ifaliasreq ifra;
|
||||
#ifndef NOINET6
|
||||
struct in6_aliasreq ifra6;
|
||||
#endif
|
||||
struct sockaddr_in *me4, *msk4, *peer4;
|
||||
struct sockaddr_storage ssme, sspeer, ssmsk;
|
||||
int res;
|
||||
|
||||
ncprange_getsa(&addr->ifa, &ssme, &ssmsk);
|
||||
ncpaddr_getsa(&addr->peer, &sspeer);
|
||||
res = 0;
|
||||
|
||||
switch (ncprange_family(&addr->ifa)) {
|
||||
case AF_INET:
|
||||
memset(&ifra, '\0', sizeof ifra);
|
||||
strncpy(ifra.ifra_name, name, sizeof ifra.ifra_name - 1);
|
||||
|
||||
me4 = (struct sockaddr_in *)&ifra.ifra_addr;
|
||||
memcpy(me4, &ssme, sizeof *me4);
|
||||
|
||||
msk4 = (struct sockaddr_in *)&ifra.ifra_mask;
|
||||
memcpy(msk4, &ssmsk, sizeof *msk4);
|
||||
|
||||
peer4 = (struct sockaddr_in *)&ifra.ifra_broadaddr;
|
||||
if (ncpaddr_family(&addr->peer) == AF_UNSPEC) {
|
||||
peer4->sin_family = AF_INET;
|
||||
peer4->sin_len = sizeof(*peer4);
|
||||
peer4->sin_addr.s_addr = INADDR_NONE;
|
||||
} else
|
||||
memcpy(peer4, &sspeer, sizeof *peer4);
|
||||
|
||||
res = ID0ioctl(s, SIOCAIFADDR, &ifra);
|
||||
break;
|
||||
|
||||
#ifndef NOINET6
|
||||
case AF_INET6:
|
||||
memset(&ifra6, '\0', sizeof ifra6);
|
||||
strncpy(ifra6.ifra_name, name, sizeof ifra6.ifra_name - 1);
|
||||
|
||||
memcpy(&ifra6.ifra_addr, &ssme, sizeof ifra6.ifra_addr);
|
||||
memcpy(&ifra6.ifra_prefixmask, &ssmsk, sizeof ifra6.ifra_prefixmask);
|
||||
if (ncpaddr_family(&addr->peer) == AF_UNSPEC)
|
||||
ifra6.ifra_dstaddr.sin6_family = AF_UNSPEC;
|
||||
else
|
||||
memcpy(&ifra6.ifra_dstaddr, &sspeer, sizeof ifra6.ifra_dstaddr);
|
||||
ifra6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
|
||||
ifra6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
|
||||
|
||||
res = ID0ioctl(s, SIOCAIFADDR_IN6, &ifra6);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (res == -1) {
|
||||
char dst[40];
|
||||
const char *end =
|
||||
#ifndef NOINET6
|
||||
ncprange_family(&addr->ifa) == AF_INET6 ? "_IN6" :
|
||||
#endif
|
||||
"";
|
||||
|
||||
if (ncpaddr_family(&addr->peer) == AF_UNSPEC)
|
||||
log_Printf(LogWARN, "iface add: ioctl(SIOCAIFADDR%s, %s): %s\n",
|
||||
end, ncprange_ntoa(&addr->ifa), strerror(errno));
|
||||
else {
|
||||
snprintf(dst, sizeof dst, "%s", ncpaddr_ntoa(&addr->peer));
|
||||
log_Printf(LogWARN, "iface add: ioctl(SIOCDIFADDR%s, %s -> %s): %s\n",
|
||||
end, ncprange_ntoa(&addr->ifa), dst, strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
iface_inClear(struct iface *iface, int how)
|
||||
iface_Clear(struct iface *iface, struct ncp *ncp, int family, int how)
|
||||
{
|
||||
int n, addrs;
|
||||
int addrs, af, inskip, in6skip, n, s4 = -1, s6 = -1, *s;
|
||||
|
||||
if (iface->in_addrs) {
|
||||
addrs = n = how == IFACE_CLEAR_ALL ? 0 : 1;
|
||||
for (; n < iface->in_addrs; n++)
|
||||
iface_addr_Zap(iface->name, iface->in_addr + n);
|
||||
if (iface->addrs) {
|
||||
inskip = in6skip = how == IFACE_CLEAR_ALL ? 0 : 1;
|
||||
addrs = 0;
|
||||
|
||||
for (n = 0; n < iface->addrs; n++) {
|
||||
af = ncprange_family(&iface->addr[n].ifa);
|
||||
if (family == 0 || family == af) {
|
||||
if (!iface->addr[n].system && (how & IFACE_SYSTEM))
|
||||
continue;
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
if (inskip) {
|
||||
inskip = 0;
|
||||
continue;
|
||||
}
|
||||
s = &s4;
|
||||
break;
|
||||
|
||||
#ifndef NOINET6
|
||||
case AF_INET6:
|
||||
if (in6skip) {
|
||||
in6skip = 0;
|
||||
continue;
|
||||
}
|
||||
s = &s6;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (*s == -1 && (*s = ID0socket(af, SOCK_DGRAM, 0)) == -1)
|
||||
log_Printf(LogERROR, "iface_Clear: socket(): %s\n", strerror(errno));
|
||||
else if (iface_addr_Zap(iface->name, iface->addr + n, *s)) {
|
||||
ncp_IfaceAddrDeleted(ncp, iface->addr + n);
|
||||
bcopy(iface->addr + n + 1, iface->addr + n,
|
||||
(iface->addrs - n - 1) * sizeof *iface->addr);
|
||||
iface->addrs--;
|
||||
n--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
iface->in_addrs = addrs;
|
||||
/* Don't bother realloc()ing - we have little to gain */
|
||||
|
||||
if (s4)
|
||||
close(s4);
|
||||
if (s6)
|
||||
close(s6);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
iface_inAdd(struct iface *iface, struct in_addr ifa, struct in_addr mask,
|
||||
struct in_addr brd, int how)
|
||||
iface_Add(struct iface *iface, struct ncp *ncp, const struct ncprange *ifa,
|
||||
const struct ncpaddr *peer, int how)
|
||||
{
|
||||
int slot, s, chg, nochange;
|
||||
struct ifaliasreq ifra;
|
||||
struct sockaddr_in *me, *peer, *msk;
|
||||
int af, n, s, width;
|
||||
struct ncpaddr ifaddr, ncplocal;
|
||||
struct iface_addr *addr;
|
||||
|
||||
for (slot = 0; slot < iface->in_addrs; slot++)
|
||||
if (iface->in_addr[slot].ifa.s_addr == ifa.s_addr) {
|
||||
if (how & IFACE_FORCE_ADD)
|
||||
break;
|
||||
else
|
||||
/* errno = EEXIST; */
|
||||
return 0;
|
||||
}
|
||||
|
||||
addr = (struct iface_addr *)realloc
|
||||
(iface->in_addr, (iface->in_addrs + 1) * sizeof iface->in_addr[0]);
|
||||
if (addr == NULL) {
|
||||
log_Printf(LogERROR, "iface_inAdd: realloc: %s\n", strerror(errno));
|
||||
af = ncprange_family(ifa);
|
||||
if ((s = ID0socket(af, SOCK_DGRAM, 0)) == -1) {
|
||||
log_Printf(LogERROR, "iface_Add: socket(): %s\n", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
iface->in_addr = addr;
|
||||
ncprange_getaddr(ifa, &ncplocal);
|
||||
|
||||
/*
|
||||
* We've gotta be careful here. If we try to add an address with the
|
||||
* same destination as an existing interface, nothing will work.
|
||||
* Instead, we tweak all previous address entries that match the
|
||||
* to-be-added destination to 255.255.255.255 (w/ a similar netmask).
|
||||
* There *may* be more than one - if the user has ``iface add''ed
|
||||
* stuff previously.
|
||||
*/
|
||||
nochange = 0;
|
||||
s = -1;
|
||||
for (chg = 0; chg < iface->in_addrs; chg++) {
|
||||
if ((iface->in_addr[chg].brd.s_addr == brd.s_addr &&
|
||||
brd.s_addr != INADDR_BROADCAST) || chg == slot) {
|
||||
/*
|
||||
* If we've found an entry that exactly matches what we want to add,
|
||||
* don't remove it and then add it again. If we do, it's possible
|
||||
* that the kernel will (correctly) ``tidy up'' any routes that use
|
||||
* the IP number as a destination.
|
||||
*/
|
||||
if (chg == slot && iface->in_addr[chg].mask.s_addr == mask.s_addr) {
|
||||
if (brd.s_addr == iface->in_addr[slot].brd.s_addr)
|
||||
nochange = 1;
|
||||
/*
|
||||
* If only the destination address has changed, the SIOCAIFADDR
|
||||
* we do after the current loop will change it.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
if (s == -1 && (s = ID0socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
|
||||
log_Printf(LogERROR, "iface_inAdd: socket(): %s\n", strerror(errno));
|
||||
return 0;
|
||||
for (n = 0; n < iface->addrs; n++) {
|
||||
if (ncprange_contains(&iface->addr[n].ifa, &ncplocal)) {
|
||||
if (!(how & IFACE_FORCE_ADD)) {
|
||||
close(s);
|
||||
return 0; /* errno = EEXIST; */
|
||||
}
|
||||
|
||||
memset(&ifra, '\0', sizeof ifra);
|
||||
strncpy(ifra.ifra_name, iface->name, sizeof ifra.ifra_name - 1);
|
||||
me = (struct sockaddr_in *)&ifra.ifra_addr;
|
||||
msk = (struct sockaddr_in *)&ifra.ifra_mask;
|
||||
peer = (struct sockaddr_in *)&ifra.ifra_broadaddr;
|
||||
me->sin_family = msk->sin_family = peer->sin_family = AF_INET;
|
||||
me->sin_len = msk->sin_len = peer->sin_len = sizeof(struct sockaddr_in);
|
||||
me->sin_addr = iface->in_addr[chg].ifa;
|
||||
msk->sin_addr = iface->in_addr[chg].mask;
|
||||
peer->sin_addr = iface->in_addr[chg].brd;
|
||||
log_Printf(LogDEBUG, "Delete %s\n", inet_ntoa(me->sin_addr));
|
||||
ID0ioctl(s, SIOCDIFADDR, &ifra); /* Don't care if it fails... */
|
||||
if (chg != slot) {
|
||||
peer->sin_addr.s_addr = iface->in_addr[chg].brd.s_addr =
|
||||
msk->sin_addr.s_addr = iface->in_addr[chg].mask.s_addr =
|
||||
INADDR_BROADCAST;
|
||||
iface->in_addr[chg].bits = 32;
|
||||
log_Printf(LogDEBUG, "Add %s -> 255.255.255.255\n",
|
||||
inet_ntoa(me->sin_addr));
|
||||
if (ID0ioctl(s, SIOCAIFADDR, &ifra) < 0 && errno != EEXIST) {
|
||||
/* Oops - that's bad(ish) news ! We've lost an alias ! */
|
||||
log_Printf(LogERROR, "iface_inAdd: ioctl(SIOCAIFADDR): %s: %s\n",
|
||||
inet_ntoa(me->sin_addr), strerror(errno));
|
||||
iface->in_addrs--;
|
||||
bcopy(iface->in_addr + chg + 1, iface->in_addr + chg,
|
||||
(iface->in_addrs - chg) * sizeof iface->in_addr[0]);
|
||||
if (slot > chg)
|
||||
slot--;
|
||||
chg--;
|
||||
}
|
||||
if (ncprange_equal(&iface->addr[n].ifa, ifa) &&
|
||||
ncpaddr_equal(&iface->addr[n].peer, peer)) {
|
||||
close(s);
|
||||
return 1; /* Already there */
|
||||
}
|
||||
|
||||
width =
|
||||
#ifndef NOINET6
|
||||
(af == AF_INET6) ? 128 :
|
||||
#endif
|
||||
32;
|
||||
iface_addr_Zap(iface->name, iface->addr + n, s);
|
||||
ncprange_setwidth(&iface->addr[n].ifa, width);
|
||||
ncprange_getaddr(&iface->addr[n].ifa, &ifaddr);
|
||||
if (ncpaddr_equal(&ifaddr, &ncplocal))
|
||||
ncpaddr_copy(&iface->addr[n].peer, peer);
|
||||
else
|
||||
ncpaddr_init(&iface->addr[n].peer);
|
||||
iface_addr_Add(iface->name, iface->addr + n, s);
|
||||
if (ncpaddr_equal(&ifaddr, &ncplocal)) {
|
||||
close(s);
|
||||
ncp_IfaceAddrAdded(ncp, iface->addr + n);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!nochange) {
|
||||
if (s == -1 && (s = ID0socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
|
||||
log_Printf(LogERROR, "iface_inAdd: socket(): %s\n", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
memset(&ifra, '\0', sizeof ifra);
|
||||
strncpy(ifra.ifra_name, iface->name, sizeof ifra.ifra_name - 1);
|
||||
me = (struct sockaddr_in *)&ifra.ifra_addr;
|
||||
msk = (struct sockaddr_in *)&ifra.ifra_mask;
|
||||
peer = (struct sockaddr_in *)&ifra.ifra_broadaddr;
|
||||
me->sin_family = msk->sin_family = peer->sin_family = AF_INET;
|
||||
me->sin_len = msk->sin_len = peer->sin_len = sizeof(struct sockaddr_in);
|
||||
me->sin_addr = ifa;
|
||||
msk->sin_addr = mask;
|
||||
peer->sin_addr = brd;
|
||||
|
||||
if (log_IsKept(LogDEBUG)) {
|
||||
char buf[16];
|
||||
|
||||
strncpy(buf, inet_ntoa(brd), sizeof buf-1);
|
||||
buf[sizeof buf - 1] = '\0';
|
||||
log_Printf(LogDEBUG, "Add %s -> %s\n", inet_ntoa(ifa), buf);
|
||||
}
|
||||
|
||||
/* An EEXIST failure w/ brd == INADDR_BROADCAST is ok (and works!) */
|
||||
if (ID0ioctl(s, SIOCAIFADDR, &ifra) < 0 &&
|
||||
(brd.s_addr != INADDR_BROADCAST || errno != EEXIST)) {
|
||||
log_Printf(LogERROR, "iface_inAdd: ioctl(SIOCAIFADDR): %s: %s\n",
|
||||
inet_ntoa(ifa), strerror(errno));
|
||||
ID0ioctl(s, SIOCDIFADDR, &ifra); /* EEXIST ? */
|
||||
close(s);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (s != -1)
|
||||
addr = (struct iface_addr *)realloc
|
||||
(iface->addr, (iface->addrs + 1) * sizeof iface->addr[0]);
|
||||
if (addr == NULL) {
|
||||
log_Printf(LogERROR, "iface_inAdd: realloc: %s\n", strerror(errno));
|
||||
close(s);
|
||||
|
||||
if (slot == iface->in_addrs) {
|
||||
/* We're adding a new interface address */
|
||||
|
||||
if (how & IFACE_ADD_FIRST) {
|
||||
/* Stuff it at the start of our list */
|
||||
slot = 0;
|
||||
bcopy(iface->in_addr, iface->in_addr + 1,
|
||||
iface->in_addrs * sizeof iface->in_addr[0]);
|
||||
}
|
||||
|
||||
iface->in_addrs++;
|
||||
} else if (how & IFACE_ADD_FIRST) {
|
||||
/* Shift it up to the first slot */
|
||||
bcopy(iface->in_addr, iface->in_addr + 1, slot * sizeof iface->in_addr[0]);
|
||||
slot = 0;
|
||||
return 0;
|
||||
}
|
||||
iface->addr = addr;
|
||||
|
||||
iface->in_addr[slot].ifa = ifa;
|
||||
iface->in_addr[slot].mask = mask;
|
||||
iface->in_addr[slot].brd = brd;
|
||||
iface->in_addr[slot].bits = bitsinmask(iface->in_addr[slot].mask);
|
||||
if (how & IFACE_ADD_FIRST) {
|
||||
/* Stuff it at the start of our list */
|
||||
n = 0;
|
||||
bcopy(iface->addr, iface->addr + 1, iface->addrs * sizeof *iface->addr);
|
||||
} else
|
||||
n = iface->addrs;
|
||||
|
||||
iface->addrs++;
|
||||
ncprange_copy(&iface->addr[n].ifa, ifa);
|
||||
ncpaddr_copy(&iface->addr[n].peer, peer);
|
||||
iface->addr[n].system = !!(how & IFACE_SYSTEM);
|
||||
iface_addr_Add(iface->name, iface->addr + n, s);
|
||||
|
||||
close(s);
|
||||
ncp_IfaceAddrAdded(ncp, iface->addr + n);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
iface_inDelete(struct iface *iface, struct in_addr ip)
|
||||
iface_Delete(struct iface *iface, struct ncp *ncp, const struct ncpaddr *del)
|
||||
{
|
||||
int n;
|
||||
struct ncpaddr found;
|
||||
int n, res, s;
|
||||
|
||||
for (n = 0; n < iface->in_addrs; n++)
|
||||
if (iface->in_addr[n].ifa.s_addr == ip.s_addr) {
|
||||
iface_addr_Zap(iface->name, iface->in_addr + n);
|
||||
bcopy(iface->in_addr + n + 1, iface->in_addr + n,
|
||||
(iface->in_addrs - n - 1) * sizeof iface->in_addr[0]);
|
||||
iface->in_addrs--;
|
||||
return 1;
|
||||
if ((s = ID0socket(ncpaddr_family(del), SOCK_DGRAM, 0)) == -1) {
|
||||
log_Printf(LogERROR, "iface_Delete: socket(): %s\n", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (n = res = 0; n < iface->addrs; n++) {
|
||||
ncprange_getaddr(&iface->addr[n].ifa, &found);
|
||||
if (ncpaddr_equal(&found, del)) {
|
||||
iface_addr_Zap(iface->name, iface->addr + n, s);
|
||||
ncp_IfaceAddrDeleted(ncp, iface->addr + n);
|
||||
bcopy(iface->addr + n + 1, iface->addr + n,
|
||||
(iface->addrs - n - 1) * sizeof *iface->addr);
|
||||
iface->addrs--;
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
close(s);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#define IFACE_ADDFLAGS 1
|
||||
@ -495,7 +573,7 @@ iface_Destroy(struct iface *iface)
|
||||
|
||||
if (iface != NULL) {
|
||||
free(iface->name);
|
||||
free(iface->in_addr);
|
||||
free(iface->addr);
|
||||
free(iface);
|
||||
}
|
||||
}
|
||||
@ -527,8 +605,13 @@ struct {
|
||||
int
|
||||
iface_Show(struct cmdargs const *arg)
|
||||
{
|
||||
struct ncpaddr ncpaddr;
|
||||
struct iface *iface = arg->bundle->iface, *current;
|
||||
int f, flags;
|
||||
#ifndef NOINET6
|
||||
int scopeid, width;
|
||||
#endif
|
||||
struct in_addr mask;
|
||||
|
||||
current = iface_Create(iface->name);
|
||||
flags = iface->flags = current->flags;
|
||||
@ -542,20 +625,34 @@ iface_Show(struct cmdargs const *arg)
|
||||
flags &= ~if_flags[f].flag;
|
||||
}
|
||||
prompt_Printf(arg->prompt, "> mtu %d has %d address%s:\n", iface->mtu,
|
||||
iface->in_addrs, iface->in_addrs == 1 ? "" : "es");
|
||||
iface->addrs, iface->addrs == 1 ? "" : "es");
|
||||
|
||||
for (f = 0; f < iface->in_addrs; f++) {
|
||||
prompt_Printf(arg->prompt, " %s", inet_ntoa(iface->in_addr[f].ifa));
|
||||
if (iface->in_addr[f].bits >= 0)
|
||||
prompt_Printf(arg->prompt, "/%d", iface->in_addr[f].bits);
|
||||
if (iface->flags & IFF_POINTOPOINT)
|
||||
prompt_Printf(arg->prompt, " -> %s", inet_ntoa(iface->in_addr[f].brd));
|
||||
else if (iface->flags & IFF_BROADCAST)
|
||||
prompt_Printf(arg->prompt, " broadcast %s",
|
||||
inet_ntoa(iface->in_addr[f].brd));
|
||||
if (iface->in_addr[f].bits < 0)
|
||||
prompt_Printf(arg->prompt, " (mask %s)",
|
||||
inet_ntoa(iface->in_addr[f].mask));
|
||||
for (f = 0; f < iface->addrs; f++) {
|
||||
ncprange_getaddr(&iface->addr[f].ifa, &ncpaddr);
|
||||
switch (ncprange_family(&iface->addr[f].ifa)) {
|
||||
case AF_INET:
|
||||
prompt_Printf(arg->prompt, " inet %s --> ", ncpaddr_ntoa(&ncpaddr));
|
||||
if (ncpaddr_family(&iface->addr[f].peer) == AF_UNSPEC)
|
||||
prompt_Printf(arg->prompt, "255.255.255.255");
|
||||
else
|
||||
prompt_Printf(arg->prompt, "%s", ncpaddr_ntoa(&iface->addr[f].peer));
|
||||
ncprange_getip4mask(&iface->addr[f].ifa, &mask);
|
||||
prompt_Printf(arg->prompt, " netmask 0x%08lx", (long)ntohl(mask.s_addr));
|
||||
break;
|
||||
|
||||
#ifndef NOINET6
|
||||
case AF_INET6:
|
||||
prompt_Printf(arg->prompt, " inet6 %s", ncpaddr_ntoa(&ncpaddr));
|
||||
if (ncpaddr_family(&iface->addr[f].peer) != AF_UNSPEC)
|
||||
prompt_Printf(arg->prompt, " --> %s",
|
||||
ncpaddr_ntoa(&iface->addr[f].peer));
|
||||
ncprange_getwidth(&iface->addr[f].ifa, &width);
|
||||
prompt_Printf(arg->prompt, " prefixlen %d", width);
|
||||
if ((scopeid = ncprange_scopeid(&iface->addr[f].ifa)) != -1)
|
||||
prompt_Printf(arg->prompt, " scopeid 0x%x", (unsigned)scopeid);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
prompt_Printf(arg->prompt, "\n");
|
||||
}
|
||||
|
||||
|
@ -29,10 +29,9 @@
|
||||
struct ifa_msghdr;
|
||||
|
||||
struct iface_addr {
|
||||
struct in_addr ifa; /* local address */
|
||||
struct in_addr mask; /* netmask */
|
||||
int bits; /* netmask bits - -1 if not contiguous */
|
||||
struct in_addr brd; /* peer address */
|
||||
unsigned system : 1; /* System alias ? */
|
||||
struct ncprange ifa; /* local address/mask */
|
||||
struct ncpaddr peer; /* peer address */
|
||||
};
|
||||
|
||||
struct iface {
|
||||
@ -41,24 +40,24 @@ struct iface {
|
||||
int flags; /* Interface flags (IFF_*) */
|
||||
int mtu; /* struct tuninfo MTU */
|
||||
|
||||
int in_addrs; /* How many in_addr's */
|
||||
struct iface_addr *in_addr; /* Array of addresses (malloc'd) */
|
||||
int addrs; /* How many in_addr's */
|
||||
struct iface_addr *addr; /* Array of addresses (malloc'd) */
|
||||
};
|
||||
|
||||
#define IFACE_CLEAR_ALL 0 /* Nuke 'em all */
|
||||
#define IFACE_CLEAR_ALIASES 1 /* Leave the IPCP address */
|
||||
#define IFACE_CLEAR_ALIASES 1 /* Leave the NCP address */
|
||||
|
||||
#define IFACE_ADD_LAST 0 /* Just another alias */
|
||||
#define IFACE_ADD_FIRST 1 /* The IPCP address */
|
||||
#define IFACE_FORCE_ADD 2 /* OR'd with IFACE_ADD_{FIRST,LAST} */
|
||||
|
||||
#define iface_Clear iface_inClear /* Same for now */
|
||||
#define IFACE_SYSTEM 4 /* Set/clear SYSTEM entries */
|
||||
|
||||
extern struct iface *iface_Create(const char *name);
|
||||
extern void iface_inClear(struct iface *, int);
|
||||
extern int iface_inAdd(struct iface *, struct in_addr, struct in_addr,
|
||||
struct in_addr, int);
|
||||
extern int iface_inDelete(struct iface *, struct in_addr);
|
||||
extern void iface_Clear(struct iface *, struct ncp *, int, int);
|
||||
extern int iface_Add(struct iface *, struct ncp *, const struct ncprange *,
|
||||
const struct ncpaddr *, int);
|
||||
extern int iface_Delete(struct iface *, struct ncp *, const struct ncpaddr *);
|
||||
extern int iface_Show(struct cmdargs const *);
|
||||
extern int iface_SetFlags(const char *, int);
|
||||
extern int iface_ClearFlags(const char *, int);
|
||||
|
@ -33,6 +33,10 @@
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#ifndef NOINET6
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet/ip6.h>
|
||||
#endif
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/tcp.h>
|
||||
@ -40,7 +44,9 @@
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
@ -57,6 +63,8 @@
|
||||
#include "throughput.h"
|
||||
#include "iplist.h"
|
||||
#include "slcompress.h"
|
||||
#include "ncpaddr.h"
|
||||
#include "ip.h"
|
||||
#include "ipcp.h"
|
||||
#include "filter.h"
|
||||
#include "descriptor.h"
|
||||
@ -67,9 +75,10 @@
|
||||
#ifndef NORADIUS
|
||||
#include "radius.h"
|
||||
#endif
|
||||
#include "ipv6cp.h"
|
||||
#include "ncp.h"
|
||||
#include "bundle.h"
|
||||
#include "tun.h"
|
||||
#include "ip.h"
|
||||
|
||||
|
||||
#define OPCODE_QUERY 0
|
||||
@ -155,54 +164,90 @@ PortMatch(int op, u_short pport, u_short rport)
|
||||
}
|
||||
|
||||
/*
|
||||
* Check a packet against a defined filter
|
||||
* Returns 0 to accept the packet, non-zero to drop the packet
|
||||
* Check a packet against the given filter
|
||||
* Returns 0 to accept the packet, non-zero to drop the packet.
|
||||
* If psecs is not NULL, populate it with the timeout associated
|
||||
* with the filter rule matched.
|
||||
*
|
||||
* If filtering is enabled, the initial fragment of a datagram must
|
||||
* contain the complete protocol header, and subsequent fragments
|
||||
* must not attempt to over-write it.
|
||||
* If filtering is enabled, the initial fragment of a datagram must
|
||||
* contain the complete protocol header, and subsequent fragments
|
||||
* must not attempt to over-write it.
|
||||
*
|
||||
* One (and only one) of pip or pip6 must be set.
|
||||
*/
|
||||
static int
|
||||
FilterCheck(const struct ip *pip, const struct filter *filter, unsigned *psecs)
|
||||
int
|
||||
FilterCheck(const unsigned char *packet, u_int32_t family,
|
||||
const struct filter *filter, unsigned *psecs)
|
||||
{
|
||||
int gotinfo; /* true if IP payload decoded */
|
||||
int cproto; /* P_* protocol type if (gotinfo) */
|
||||
int cproto; /* IPPROTO_* protocol number if (gotinfo) */
|
||||
int estab, syn, finrst; /* TCP state flags if (gotinfo) */
|
||||
u_short sport, dport; /* src, dest port from packet if (gotinfo) */
|
||||
int n; /* filter rule to process */
|
||||
int len; /* bytes used in dbuff */
|
||||
int didname; /* true if filter header printed */
|
||||
int match; /* true if condition matched */
|
||||
int mindata; /* minimum data size or zero */
|
||||
const struct filterent *fp = filter->rule;
|
||||
char dbuff[100], dstip[16];
|
||||
char dbuff[100], dstip[16], prototxt[16];
|
||||
struct protoent *pe;
|
||||
struct ncpaddr srcaddr, dstaddr;
|
||||
const char *payload; /* IP payload */
|
||||
int datalen; /* IP datagram length */
|
||||
|
||||
if (fp->f_action == A_NONE)
|
||||
return 0; /* No rule is given. Permit this packet */
|
||||
|
||||
/*
|
||||
* Deny any packet fragment that tries to over-write the header.
|
||||
* Since we no longer have the real header available, punt on the
|
||||
* largest normal header - 20 bytes for TCP without options, rounded
|
||||
* up to the next possible fragment boundary. Since the smallest
|
||||
* `legal' MTU is 576, and the smallest recommended MTU is 296, any
|
||||
* fragmentation within this range is dubious at best
|
||||
*/
|
||||
len = ntohs(pip->ip_off) & IP_OFFMASK; /* fragment offset */
|
||||
if (len > 0) { /* Not first fragment within datagram */
|
||||
if (len < (24 >> 3)) { /* don't allow fragment to over-write header */
|
||||
log_Printf(LogFILTER, " error: illegal header\n");
|
||||
return 1;
|
||||
#ifndef NOINET6
|
||||
if (family == AF_INET6) {
|
||||
const struct ip6_hdr *pip6 = (const struct ip6_hdr *)packet;
|
||||
|
||||
ncpaddr_setip6(&srcaddr, &pip6->ip6_src);
|
||||
ncpaddr_setip6(&dstaddr, &pip6->ip6_dst);
|
||||
datalen = ntohs(pip6->ip6_plen); /* XXX: Wrong ? */
|
||||
payload = packet + sizeof *pip6; /* XXX: Wrong ? */
|
||||
cproto = pip6->ip6_nxt;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
/*
|
||||
* Deny any packet fragment that tries to over-write the header.
|
||||
* Since we no longer have the real header available, punt on the
|
||||
* largest normal header - 20 bytes for TCP without options, rounded
|
||||
* up to the next possible fragment boundary. Since the smallest
|
||||
* `legal' MTU is 576, and the smallest recommended MTU is 296, any
|
||||
* fragmentation within this range is dubious at best
|
||||
*/
|
||||
const struct ip *pip = (const struct ip *)packet;
|
||||
|
||||
len = ntohs(pip->ip_off) & IP_OFFMASK; /* fragment offset */
|
||||
if (len > 0) { /* Not first fragment within datagram */
|
||||
if (len < (24 >> 3)) { /* don't allow fragment to over-write header */
|
||||
log_Printf(LogFILTER, " error: illegal header\n");
|
||||
return 1;
|
||||
}
|
||||
/* permit fragments on in and out filter */
|
||||
if (!filter->fragok) {
|
||||
log_Printf(LogFILTER, " error: illegal fragmentation\n");
|
||||
return 1;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
/* permit fragments on in and out filter */
|
||||
if (!filter->fragok) {
|
||||
log_Printf(LogFILTER, " error: illegal fragmentation\n");
|
||||
return 1;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
cproto = gotinfo = estab = syn = finrst = didname = 0;
|
||||
ncpaddr_setip4(&srcaddr, pip->ip_src);
|
||||
ncpaddr_setip4(&dstaddr, pip->ip_dst);
|
||||
datalen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
|
||||
payload = packet + (pip->ip_hl << 2);
|
||||
cproto = pip->ip_p;
|
||||
}
|
||||
|
||||
if ((pe = getprotobynumber(cproto)) == NULL)
|
||||
snprintf(prototxt, sizeof prototxt, "%d", cproto);
|
||||
else
|
||||
snprintf(prototxt, sizeof prototxt, "%s", pe->p_name);
|
||||
gotinfo = estab = syn = finrst = didname = 0;
|
||||
sport = dport = 0;
|
||||
|
||||
for (n = 0; n < MAXFILTERS; ) {
|
||||
if (fp->f_action == A_NONE) {
|
||||
n++;
|
||||
@ -216,99 +261,76 @@ FilterCheck(const struct ip *pip, const struct filter *filter, unsigned *psecs)
|
||||
}
|
||||
|
||||
match = 0;
|
||||
if (!((pip->ip_src.s_addr ^ fp->f_src.ipaddr.s_addr) &
|
||||
fp->f_src.mask.s_addr) &&
|
||||
!((pip->ip_dst.s_addr ^ fp->f_dst.ipaddr.s_addr) &
|
||||
fp->f_dst.mask.s_addr)) {
|
||||
if (fp->f_proto != P_NONE) {
|
||||
|
||||
if ((ncprange_family(&fp->f_src) == AF_UNSPEC ||
|
||||
ncprange_contains(&fp->f_src, &srcaddr)) &&
|
||||
(ncprange_family(&fp->f_dst) == AF_UNSPEC ||
|
||||
ncprange_contains(&fp->f_dst, &dstaddr))) {
|
||||
if (fp->f_proto != 0) {
|
||||
if (!gotinfo) {
|
||||
const char *ptop = (const char *) pip + (pip->ip_hl << 2);
|
||||
const struct tcphdr *th;
|
||||
const struct udphdr *uh;
|
||||
const struct icmp *ih;
|
||||
int datalen; /* IP datagram length */
|
||||
#ifndef NOINET6
|
||||
const struct icmp6_hdr *ih6;
|
||||
#endif
|
||||
mindata = 0;
|
||||
sport = dport = 0;
|
||||
estab = syn = finrst = -1;
|
||||
|
||||
datalen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
|
||||
switch (pip->ip_p) {
|
||||
switch (cproto) {
|
||||
case IPPROTO_ICMP:
|
||||
cproto = P_ICMP;
|
||||
if (datalen < 8) { /* ICMP must be at least 8 octets */
|
||||
log_Printf(LogFILTER, " error: ICMP must be at least 8 octets\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
ih = (const struct icmp *) ptop;
|
||||
sport = ih->icmp_type;
|
||||
estab = syn = finrst = -1;
|
||||
mindata = 8; /* ICMP must be at least 8 octets */
|
||||
ih = (const struct icmp *)payload;
|
||||
sport = ntohs(ih->icmp_type);
|
||||
if (log_IsKept(LogDEBUG))
|
||||
snprintf(dbuff, sizeof dbuff, "sport = %d", sport);
|
||||
break;
|
||||
case IPPROTO_IGMP:
|
||||
cproto = P_IGMP;
|
||||
if (datalen < 8) { /* IGMP uses 8-octet messages */
|
||||
log_Printf(LogFILTER, " error: IGMP must be at least 8 octets\n");
|
||||
return 1;
|
||||
}
|
||||
estab = syn = finrst = -1;
|
||||
sport = ntohs(0);
|
||||
|
||||
#ifndef NOINET6
|
||||
case IPPROTO_ICMPV6:
|
||||
mindata = 8; /* ICMP must be at least 8 octets */
|
||||
ih6 = (const struct icmp6_hdr *)payload;
|
||||
sport = ntohs(ih6->icmp6_type);
|
||||
if (log_IsKept(LogDEBUG))
|
||||
snprintf(dbuff, sizeof dbuff, "sport = %d", sport);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case IPPROTO_IGMP:
|
||||
mindata = 8; /* IGMP uses 8-octet messages */
|
||||
break;
|
||||
|
||||
#ifdef IPPROTO_GRE
|
||||
case IPPROTO_GRE:
|
||||
cproto = P_GRE;
|
||||
if (datalen < 2) { /* GRE uses 2-octet+ messages */
|
||||
log_Printf(LogFILTER, " error: GRE must be at least 2 octets\n");
|
||||
return 1;
|
||||
}
|
||||
estab = syn = finrst = -1;
|
||||
sport = ntohs(0);
|
||||
mindata = 2; /* GRE uses 2-octet+ messages */
|
||||
break;
|
||||
#endif
|
||||
#ifdef IPPROTO_OSPFIGP
|
||||
case IPPROTO_OSPFIGP:
|
||||
cproto = P_OSPF;
|
||||
if (datalen < 8) { /* IGMP uses 8-octet messages */
|
||||
log_Printf(LogFILTER, " error: IGMP must be at least 8 octets\n");
|
||||
return 1;
|
||||
}
|
||||
estab = syn = finrst = -1;
|
||||
sport = ntohs(0);
|
||||
mindata = 8; /* IGMP uses 8-octet messages */
|
||||
break;
|
||||
#endif
|
||||
case IPPROTO_ESP:
|
||||
cproto = P_ESP;
|
||||
estab = syn = finrst = -1;
|
||||
sport = ntohs(0);
|
||||
#ifndef NOINET6
|
||||
case IPPROTO_IPV6:
|
||||
mindata = 20; /* RFC2893 Section 3.5: 5 * 32bit words */
|
||||
break;
|
||||
case IPPROTO_AH:
|
||||
cproto = P_AH;
|
||||
estab = syn = finrst = -1;
|
||||
sport = ntohs(0);
|
||||
break;
|
||||
case IPPROTO_IPIP:
|
||||
cproto = P_IPIP;
|
||||
sport = dport = 0;
|
||||
estab = syn = finrst = -1;
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
cproto = P_UDP;
|
||||
if (datalen < 8) { /* UDP header is 8 octets */
|
||||
log_Printf(LogFILTER, " error: UDP/IPIP"
|
||||
" must be at least 8 octets\n");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
uh = (const struct udphdr *) ptop;
|
||||
case IPPROTO_UDP:
|
||||
mindata = 8; /* UDP header is 8 octets */
|
||||
uh = (const struct udphdr *)payload;
|
||||
sport = ntohs(uh->uh_sport);
|
||||
dport = ntohs(uh->uh_dport);
|
||||
estab = syn = finrst = -1;
|
||||
if (log_IsKept(LogDEBUG))
|
||||
snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d",
|
||||
sport, dport);
|
||||
break;
|
||||
|
||||
case IPPROTO_TCP:
|
||||
cproto = P_TCP;
|
||||
th = (const struct tcphdr *) ptop;
|
||||
/* TCP headers are variable length. The following code
|
||||
th = (const struct tcphdr *)payload;
|
||||
/*
|
||||
* TCP headers are variable length. The following code
|
||||
* ensures that the TCP header length isn't de-referenced if
|
||||
* the datagram is too short
|
||||
*/
|
||||
@ -331,8 +353,13 @@ FilterCheck(const struct ip *pip, const struct filter *filter, unsigned *psecs)
|
||||
}
|
||||
break;
|
||||
default:
|
||||
log_Printf(LogFILTER, " error: unknown protocol\n");
|
||||
return 1; /* We'll block unknown type of packet */
|
||||
break;
|
||||
}
|
||||
|
||||
if (datalen < mindata) {
|
||||
log_Printf(LogFILTER, " error: proto %s must be at least"
|
||||
" %d octets\n", prototxt, mindata);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (log_IsKept(LogDEBUG)) {
|
||||
@ -342,11 +369,11 @@ FilterCheck(const struct ip *pip, const struct filter *filter, unsigned *psecs)
|
||||
", estab = %d, syn = %d, finrst = %d",
|
||||
estab, syn, finrst);
|
||||
}
|
||||
log_Printf(LogDEBUG, " Filter: proto = %s, %s\n",
|
||||
filter_Proto2Nam(cproto), dbuff);
|
||||
log_Printf(LogDEBUG, " Filter: proto = %s, %s\n", prototxt, dbuff);
|
||||
}
|
||||
gotinfo = 1;
|
||||
}
|
||||
|
||||
if (log_IsKept(LogDEBUG)) {
|
||||
if (fp->f_srcop != OP_NONE) {
|
||||
snprintf(dbuff, sizeof dbuff, ", src %s %d",
|
||||
@ -362,9 +389,8 @@ FilterCheck(const struct ip *pip, const struct filter *filter, unsigned *psecs)
|
||||
*dbuff = '\0';
|
||||
|
||||
log_Printf(LogDEBUG, " rule = %d: Address match, "
|
||||
"check against proto %s%s, action = %s\n",
|
||||
n, filter_Proto2Nam(fp->f_proto),
|
||||
dbuff, filter_Action2Nam(fp->f_action));
|
||||
"check against proto %d%s, action = %s\n",
|
||||
n, fp->f_proto, dbuff, filter_Action2Nam(fp->f_action));
|
||||
}
|
||||
|
||||
if (cproto == fp->f_proto) {
|
||||
@ -398,24 +424,23 @@ FilterCheck(const struct ip *pip, const struct filter *filter, unsigned *psecs)
|
||||
if (strcmp(filter->name, "DIAL") == 0) {
|
||||
/* If dial filter then even print out accept packets */
|
||||
if (log_IsKept(LogFILTER)) {
|
||||
snprintf(dstip, sizeof dstip, "%s", inet_ntoa(pip->ip_dst));
|
||||
snprintf(dstip, sizeof dstip, "%s", ncpaddr_ntoa(&dstaddr));
|
||||
log_Printf(LogFILTER, "%sbound rule = %d accept %s "
|
||||
"src = %s/%d dst = %s/%d\n",
|
||||
filter->name, n, filter_Proto2Nam(cproto),
|
||||
inet_ntoa(pip->ip_src), sport, dstip, dport);
|
||||
"src = %s:%d dst = %s:%d\n", filter->name, n, prototxt,
|
||||
ncpaddr_ntoa(&srcaddr), sport, dstip, dport);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
if (log_IsKept(LogFILTER)) {
|
||||
snprintf(dstip, sizeof dstip, "%s", inet_ntoa(pip->ip_dst));
|
||||
snprintf(dstip, sizeof dstip, "%s", ncpaddr_ntoa(&dstaddr));
|
||||
log_Printf(LogFILTER,
|
||||
"%sbound rule = %d deny %s src = %s/%d dst = %s/%d\n",
|
||||
filter->name, n, filter_Proto2Nam(cproto),
|
||||
inet_ntoa(pip->ip_src), sport, dstip, dport);
|
||||
filter->name, n, prototxt,
|
||||
ncpaddr_ntoa(&srcaddr), sport, dstip, dport);
|
||||
}
|
||||
return 1;
|
||||
} /* Explict math. Deny this packet */
|
||||
} /* Explict match. Deny this packet */
|
||||
}
|
||||
} else {
|
||||
n++;
|
||||
@ -424,31 +449,16 @@ FilterCheck(const struct ip *pip, const struct filter *filter, unsigned *psecs)
|
||||
}
|
||||
|
||||
if (log_IsKept(LogFILTER)) {
|
||||
snprintf(dstip, sizeof dstip, "%s", inet_ntoa(pip->ip_dst));
|
||||
snprintf(dstip, sizeof dstip, "%s", ncpaddr_ntoa(&dstaddr));
|
||||
log_Printf(LogFILTER,
|
||||
"%sbound rule = implicit deny %s src = %s/%d dst = %s/%d\n",
|
||||
filter->name, filter_Proto2Nam(cproto),
|
||||
inet_ntoa(pip->ip_src), sport, dstip, dport);
|
||||
filter->name, prototxt, ncpaddr_ntoa(&srcaddr), sport,
|
||||
dstip, dport);
|
||||
}
|
||||
|
||||
return 1; /* No rule is mached. Deny this packet */
|
||||
return 1; /* No rule matched, deny this packet */
|
||||
}
|
||||
|
||||
#ifdef notdef
|
||||
static void
|
||||
IcmpError(struct ip *pip, int code)
|
||||
{
|
||||
struct mbuf *bp;
|
||||
|
||||
if (pip->ip_p != IPPROTO_ICMP) {
|
||||
bp = m_get(m_len, MB_IPIN);
|
||||
memcpy(MBUF_CTOP(bp), ptr, m_len);
|
||||
vj_SendFrame(bp);
|
||||
ipcp_AddOutOctets(m_len);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
ip_LogDNS(const struct udphdr *uh, const char *direction)
|
||||
{
|
||||
@ -508,29 +518,60 @@ ip_LogDNS(const struct udphdr *uh, const char *direction)
|
||||
}
|
||||
|
||||
/*
|
||||
* For debugging aid.
|
||||
* Check if the given packet matches the given filter.
|
||||
* One of pip or pip6 must be set.
|
||||
*/
|
||||
int
|
||||
PacketCheck(struct bundle *bundle, unsigned char *cp, int nb,
|
||||
struct filter *filter, const char *prefix, unsigned *psecs)
|
||||
PacketCheck(struct bundle *bundle, u_int32_t family,
|
||||
const unsigned char *packet, int nb, struct filter *filter,
|
||||
const char *prefix, unsigned *psecs)
|
||||
{
|
||||
static const char *const TcpFlags[] = {
|
||||
"FIN", "SYN", "RST", "PSH", "ACK", "URG"
|
||||
};
|
||||
struct ip *pip;
|
||||
struct tcphdr *th;
|
||||
struct udphdr *uh;
|
||||
struct icmp *icmph;
|
||||
unsigned char *ptop;
|
||||
int mask, len, n, pri, logit, loglen, result;
|
||||
const struct tcphdr *th;
|
||||
const struct udphdr *uh;
|
||||
const struct icmp *icmph;
|
||||
#ifndef NOINET6
|
||||
const struct icmp6_hdr *icmp6h;
|
||||
#endif
|
||||
const unsigned char *payload;
|
||||
struct ncpaddr srcaddr, dstaddr;
|
||||
int cproto, mask, len, n, pri, logit, loglen, result;
|
||||
char logbuf[200];
|
||||
int datalen, frag;
|
||||
u_char tos;
|
||||
|
||||
logit = (log_IsKept(LogTCPIP) || log_IsKept(LogDNS)) &&
|
||||
(!filter || filter->logok);
|
||||
loglen = 0;
|
||||
pri = 0;
|
||||
|
||||
pip = (struct ip *)cp;
|
||||
#ifndef NOINET6
|
||||
if (family == AF_INET6) {
|
||||
const struct ip6_hdr *pip6 = (const struct ip6_hdr *)packet;
|
||||
|
||||
ncpaddr_setip6(&srcaddr, &pip6->ip6_src);
|
||||
ncpaddr_setip6(&dstaddr, &pip6->ip6_dst);
|
||||
datalen = ntohs(pip6->ip6_plen);
|
||||
payload = packet + sizeof *pip6;
|
||||
cproto = pip6->ip6_nxt;
|
||||
tos = 0; /* XXX: ??? */
|
||||
frag = 0; /* XXX: ??? */
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
const struct ip *pip = (const struct ip *)packet;
|
||||
|
||||
ncpaddr_setip4(&srcaddr, pip->ip_src);
|
||||
ncpaddr_setip4(&dstaddr, pip->ip_dst);
|
||||
datalen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
|
||||
payload = packet + (pip->ip_hl << 2);
|
||||
cproto = pip->ip_p;
|
||||
tos = pip->ip_tos;
|
||||
frag = ntohs(pip->ip_off) & IP_OFFMASK;
|
||||
}
|
||||
|
||||
uh = NULL;
|
||||
|
||||
if (logit && loglen < sizeof logbuf) {
|
||||
@ -542,57 +583,70 @@ PacketCheck(struct bundle *bundle, unsigned char *cp, int nb,
|
||||
snprintf(logbuf + loglen, sizeof logbuf - loglen, " ");
|
||||
loglen += strlen(logbuf + loglen);
|
||||
}
|
||||
ptop = (cp + (pip->ip_hl << 2));
|
||||
|
||||
switch (pip->ip_p) {
|
||||
switch (cproto) {
|
||||
case IPPROTO_ICMP:
|
||||
if (logit && loglen < sizeof logbuf) {
|
||||
len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - sizeof *icmph;
|
||||
icmph = (struct icmp *) ptop;
|
||||
len = datalen - sizeof *icmph;
|
||||
icmph = (const struct icmp *)payload;
|
||||
snprintf(logbuf + loglen, sizeof logbuf - loglen,
|
||||
"ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type);
|
||||
"ICMP: %s:%d ---> ", ncpaddr_ntoa(&srcaddr), icmph->icmp_type);
|
||||
loglen += strlen(logbuf + loglen);
|
||||
snprintf(logbuf + loglen, sizeof logbuf - loglen,
|
||||
"%s:%d (%d/%d)", inet_ntoa(pip->ip_dst), icmph->icmp_type,
|
||||
len, nb);
|
||||
"%s (%d/%d)", ncpaddr_ntoa(&dstaddr), len, nb);
|
||||
loglen += strlen(logbuf + loglen);
|
||||
}
|
||||
break;
|
||||
|
||||
#ifndef NOINET6
|
||||
case IPPROTO_ICMPV6:
|
||||
if (logit && loglen < sizeof logbuf) {
|
||||
len = datalen - sizeof *icmp6h;
|
||||
icmp6h = (const struct icmp6_hdr *)payload;
|
||||
snprintf(logbuf + loglen, sizeof logbuf - loglen,
|
||||
"ICMP: %s:%d ---> ", ncpaddr_ntoa(&srcaddr), icmp6h->icmp6_type);
|
||||
loglen += strlen(logbuf + loglen);
|
||||
snprintf(logbuf + loglen, sizeof logbuf - loglen,
|
||||
"%s (%d/%d)", ncpaddr_ntoa(&dstaddr), len, nb);
|
||||
loglen += strlen(logbuf + loglen);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
case IPPROTO_UDP:
|
||||
uh = (struct udphdr *) ptop;
|
||||
if (pip->ip_tos == IPTOS_LOWDELAY && bundle->ncp.ipcp.cfg.urgent.tos)
|
||||
uh = (const struct udphdr *)payload;
|
||||
if (tos == IPTOS_LOWDELAY && bundle->ncp.cfg.urgent.tos)
|
||||
pri++;
|
||||
|
||||
if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0 &&
|
||||
ipcp_IsUrgentUdpPort(&bundle->ncp.ipcp, ntohs(uh->uh_sport),
|
||||
ntohs(uh->uh_dport)))
|
||||
if (!frag && ncp_IsUrgentUdpPort(&bundle->ncp, ntohs(uh->uh_sport),
|
||||
ntohs(uh->uh_dport)))
|
||||
pri++;
|
||||
|
||||
if (logit && loglen < sizeof logbuf) {
|
||||
len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - sizeof *uh;
|
||||
len = datalen - sizeof *uh;
|
||||
snprintf(logbuf + loglen, sizeof logbuf - loglen,
|
||||
"UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
|
||||
"UDP: %s:%d ---> ", ncpaddr_ntoa(&srcaddr), ntohs(uh->uh_sport));
|
||||
loglen += strlen(logbuf + loglen);
|
||||
snprintf(logbuf + loglen, sizeof logbuf - loglen,
|
||||
"%s:%d (%d/%d)", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport),
|
||||
"%s:%d (%d/%d)", ncpaddr_ntoa(&dstaddr), ntohs(uh->uh_dport),
|
||||
len, nb);
|
||||
loglen += strlen(logbuf + loglen);
|
||||
}
|
||||
|
||||
if (Enabled(bundle, OPT_FILTERDECAP) &&
|
||||
ptop[sizeof *uh] == HDLC_ADDR && ptop[sizeof *uh + 1] == HDLC_UI) {
|
||||
payload[sizeof *uh] == HDLC_ADDR &&
|
||||
payload[sizeof *uh + 1] == HDLC_UI) {
|
||||
u_short proto;
|
||||
const char *type;
|
||||
|
||||
memcpy(&proto, ptop + sizeof *uh + 2, sizeof proto);
|
||||
memcpy(&proto, payload + sizeof *uh + 2, sizeof proto);
|
||||
type = NULL;
|
||||
|
||||
switch (ntohs(proto)) {
|
||||
case PROTO_IP:
|
||||
snprintf(logbuf + loglen, sizeof logbuf - loglen, " contains ");
|
||||
result = PacketCheck(bundle, ptop + sizeof *uh + 4,
|
||||
nb - (ptop - cp) - sizeof *uh - 4, filter,
|
||||
result = PacketCheck(bundle, AF_INET, payload + sizeof *uh + 4,
|
||||
nb - (payload - packet) - sizeof *uh - 4, filter,
|
||||
logbuf, psecs);
|
||||
if (result != -2)
|
||||
return result;
|
||||
@ -623,12 +677,11 @@ PacketCheck(struct bundle *bundle, unsigned char *cp, int nb,
|
||||
#ifdef IPPROTO_GRE
|
||||
case IPPROTO_GRE:
|
||||
if (logit && loglen < sizeof logbuf) {
|
||||
len = ntohs(pip->ip_len) - (pip->ip_hl << 2);
|
||||
snprintf(logbuf + loglen, sizeof logbuf - loglen,
|
||||
"GRE: %s ---> ", inet_ntoa(pip->ip_src));
|
||||
"GRE: %s ---> ", ncpaddr_ntoa(&srcaddr));
|
||||
loglen += strlen(logbuf + loglen);
|
||||
snprintf(logbuf + loglen, sizeof logbuf - loglen,
|
||||
"%s (%d/%d)", inet_ntoa(pip->ip_dst), len, nb);
|
||||
"%s (%d/%d)", ncpaddr_ntoa(&dstaddr), datalen, nb);
|
||||
loglen += strlen(logbuf + loglen);
|
||||
}
|
||||
break;
|
||||
@ -637,43 +690,64 @@ PacketCheck(struct bundle *bundle, unsigned char *cp, int nb,
|
||||
#ifdef IPPROTO_OSPFIGP
|
||||
case IPPROTO_OSPFIGP:
|
||||
if (logit && loglen < sizeof logbuf) {
|
||||
len = ntohs(pip->ip_len) - (pip->ip_hl << 2);
|
||||
snprintf(logbuf + loglen, sizeof logbuf - loglen,
|
||||
"OSPF: %s ---> ", inet_ntoa(pip->ip_src));
|
||||
"OSPF: %s ---> ", ncpaddr_ntoa(&srcaddr));
|
||||
loglen += strlen(logbuf + loglen);
|
||||
snprintf(logbuf + loglen, sizeof logbuf - loglen,
|
||||
"%s (%d/%d)", inet_ntoa(pip->ip_dst), len, nb);
|
||||
"%s (%d/%d)", ncpaddr_ntoa(&dstaddr), datalen, nb);
|
||||
loglen += strlen(logbuf + loglen);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifndef NOINET6
|
||||
case IPPROTO_IPV6:
|
||||
if (logit && loglen < sizeof logbuf) {
|
||||
snprintf(logbuf + loglen, sizeof logbuf - loglen,
|
||||
"IPv6: %s ---> ", ncpaddr_ntoa(&srcaddr));
|
||||
loglen += strlen(logbuf + loglen);
|
||||
snprintf(logbuf + loglen, sizeof logbuf - loglen,
|
||||
"%s (%d/%d)", ncpaddr_ntoa(&dstaddr), datalen, nb);
|
||||
loglen += strlen(logbuf + loglen);
|
||||
}
|
||||
|
||||
if (Enabled(bundle, OPT_FILTERDECAP)) {
|
||||
snprintf(logbuf + loglen, sizeof logbuf - loglen, " contains ");
|
||||
result = PacketCheck(bundle, AF_INET6, payload, nb - (payload - packet),
|
||||
filter, logbuf, psecs);
|
||||
if (result != -2)
|
||||
return result;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
case IPPROTO_IPIP:
|
||||
if (logit && loglen < sizeof logbuf) {
|
||||
snprintf(logbuf + loglen, sizeof logbuf - loglen,
|
||||
"IPIP: %s ---> ", inet_ntoa(pip->ip_src));
|
||||
"IPIP: %s ---> ", ncpaddr_ntoa(&srcaddr));
|
||||
loglen += strlen(logbuf + loglen);
|
||||
snprintf(logbuf + loglen, sizeof logbuf - loglen,
|
||||
"%s", inet_ntoa(pip->ip_dst));
|
||||
"%s", ncpaddr_ntoa(&dstaddr));
|
||||
loglen += strlen(logbuf + loglen);
|
||||
}
|
||||
|
||||
if (((struct ip *)ptop)->ip_v == 4) {
|
||||
snprintf(logbuf + loglen, sizeof logbuf - loglen, " contains ");
|
||||
result = PacketCheck(bundle, ptop, nb - (ptop - cp), filter,
|
||||
logbuf, psecs);
|
||||
if (result != -2)
|
||||
return result;
|
||||
}
|
||||
if (Enabled(bundle, OPT_FILTERDECAP) &&
|
||||
((const struct ip *)payload)->ip_v == 4) {
|
||||
snprintf(logbuf + loglen, sizeof logbuf - loglen, " contains ");
|
||||
result = PacketCheck(bundle, AF_INET, payload, nb - (payload - packet),
|
||||
filter, logbuf, psecs);
|
||||
if (result != -2)
|
||||
return result;
|
||||
}
|
||||
break;
|
||||
|
||||
case IPPROTO_ESP:
|
||||
if (logit && loglen < sizeof logbuf) {
|
||||
snprintf(logbuf + loglen, sizeof logbuf - loglen,
|
||||
"ESP: %s ---> ", inet_ntoa(pip->ip_src));
|
||||
"ESP: %s ---> ", ncpaddr_ntoa(&srcaddr));
|
||||
loglen += strlen(logbuf + loglen);
|
||||
snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s, spi %p",
|
||||
inet_ntoa(pip->ip_dst), ptop);
|
||||
ncpaddr_ntoa(&dstaddr), payload);
|
||||
loglen += strlen(logbuf + loglen);
|
||||
}
|
||||
break;
|
||||
@ -681,44 +755,43 @@ PacketCheck(struct bundle *bundle, unsigned char *cp, int nb,
|
||||
case IPPROTO_AH:
|
||||
if (logit && loglen < sizeof logbuf) {
|
||||
snprintf(logbuf + loglen, sizeof logbuf - loglen,
|
||||
"AH: %s ---> ", inet_ntoa(pip->ip_src));
|
||||
"AH: %s ---> ", ncpaddr_ntoa(&srcaddr));
|
||||
loglen += strlen(logbuf + loglen);
|
||||
snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s, spi %p",
|
||||
inet_ntoa(pip->ip_dst), ptop + sizeof(u_int32_t));
|
||||
ncpaddr_ntoa(&dstaddr), payload + sizeof(u_int32_t));
|
||||
loglen += strlen(logbuf + loglen);
|
||||
}
|
||||
break;
|
||||
|
||||
case IPPROTO_IGMP:
|
||||
if (logit && loglen < sizeof logbuf) {
|
||||
uh = (struct udphdr *) ptop;
|
||||
uh = (const struct udphdr *)payload;
|
||||
snprintf(logbuf + loglen, sizeof logbuf - loglen,
|
||||
"IGMP: %s:%d ---> ", inet_ntoa(pip->ip_src),
|
||||
"IGMP: %s:%d ---> ", ncpaddr_ntoa(&srcaddr),
|
||||
ntohs(uh->uh_sport));
|
||||
loglen += strlen(logbuf + loglen);
|
||||
snprintf(logbuf + loglen, sizeof logbuf - loglen,
|
||||
"%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
|
||||
"%s:%d", ncpaddr_ntoa(&dstaddr), ntohs(uh->uh_dport));
|
||||
loglen += strlen(logbuf + loglen);
|
||||
}
|
||||
break;
|
||||
|
||||
case IPPROTO_TCP:
|
||||
th = (struct tcphdr *) ptop;
|
||||
if (pip->ip_tos == IPTOS_LOWDELAY && bundle->ncp.ipcp.cfg.urgent.tos)
|
||||
th = (const struct tcphdr *)payload;
|
||||
if (tos == IPTOS_LOWDELAY && bundle->ncp.cfg.urgent.tos)
|
||||
pri++;
|
||||
|
||||
if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0 &&
|
||||
ipcp_IsUrgentTcpPort(&bundle->ncp.ipcp, ntohs(th->th_sport),
|
||||
ntohs(th->th_dport)))
|
||||
if (!frag && ncp_IsUrgentTcpPort(&bundle->ncp, ntohs(th->th_sport),
|
||||
ntohs(th->th_dport)))
|
||||
pri++;
|
||||
|
||||
if (logit && loglen < sizeof logbuf) {
|
||||
len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2);
|
||||
len = datalen - (th->th_off << 2);
|
||||
snprintf(logbuf + loglen, sizeof logbuf - loglen,
|
||||
"TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport));
|
||||
"TCP: %s:%d ---> ", ncpaddr_ntoa(&srcaddr), ntohs(th->th_sport));
|
||||
loglen += strlen(logbuf + loglen);
|
||||
snprintf(logbuf + loglen, sizeof logbuf - loglen,
|
||||
"%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport));
|
||||
"%s:%d", ncpaddr_ntoa(&dstaddr), ntohs(th->th_dport));
|
||||
loglen += strlen(logbuf + loglen);
|
||||
n = 0;
|
||||
for (mask = TH_FIN; mask != 0x40; mask <<= 1) {
|
||||
@ -733,10 +806,9 @@ PacketCheck(struct bundle *bundle, unsigned char *cp, int nb,
|
||||
(u_long)ntohl(th->th_seq), (u_long)ntohl(th->th_ack), len, nb);
|
||||
loglen += strlen(logbuf + loglen);
|
||||
if ((th->th_flags & TH_SYN) && nb > 40) {
|
||||
u_short *sp;
|
||||
const u_short *sp;
|
||||
|
||||
ptop += 20;
|
||||
sp = (u_short *) ptop;
|
||||
sp = (const u_short *)(payload + 20);
|
||||
if (ntohs(sp[0]) == 0x0204) {
|
||||
snprintf(logbuf + loglen, sizeof logbuf - loglen,
|
||||
" MSS = %d", ntohs(sp[1]));
|
||||
@ -749,15 +821,21 @@ PacketCheck(struct bundle *bundle, unsigned char *cp, int nb,
|
||||
default:
|
||||
if (prefix)
|
||||
return -2;
|
||||
|
||||
if (logit && loglen < sizeof logbuf) {
|
||||
snprintf(logbuf + loglen, sizeof logbuf - loglen,
|
||||
"<%d>: %s ---> ", cproto, ncpaddr_ntoa(&srcaddr));
|
||||
loglen += strlen(logbuf + loglen);
|
||||
snprintf(logbuf + loglen, sizeof logbuf - loglen,
|
||||
"%s (%d)", ncpaddr_ntoa(&dstaddr), nb);
|
||||
loglen += strlen(logbuf + loglen);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (filter && FilterCheck(pip, filter, psecs)) {
|
||||
if (filter && FilterCheck(packet, family, filter, psecs)) {
|
||||
if (logit)
|
||||
log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf);
|
||||
#ifdef notdef
|
||||
if (direction == 0)
|
||||
IcmpError(pip, pri);
|
||||
#endif
|
||||
result = -1;
|
||||
} else {
|
||||
/* Check Keep Alive filter */
|
||||
@ -765,7 +843,8 @@ PacketCheck(struct bundle *bundle, unsigned char *cp, int nb,
|
||||
unsigned alivesecs;
|
||||
|
||||
alivesecs = 0;
|
||||
if (filter && FilterCheck(pip, &bundle->filter.alive, &alivesecs))
|
||||
if (filter &&
|
||||
FilterCheck(packet, family, &bundle->filter.alive, &alivesecs))
|
||||
log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf);
|
||||
else if (psecs != NULL) {
|
||||
if(*psecs == 0)
|
||||
@ -789,47 +868,37 @@ PacketCheck(struct bundle *bundle, unsigned char *cp, int nb,
|
||||
return result;
|
||||
}
|
||||
|
||||
struct mbuf *
|
||||
ip_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
|
||||
static int
|
||||
ip_Input(struct bundle *bundle, struct link *l, struct mbuf *bp, u_int32_t af)
|
||||
{
|
||||
int nb, nw;
|
||||
struct tun_data tun;
|
||||
struct ip *pip;
|
||||
char *data;
|
||||
unsigned secs, alivesecs;
|
||||
|
||||
if (bundle->ncp.ipcp.fsm.state != ST_OPENED) {
|
||||
log_Printf(LogWARN, "ip_Input: IPCP not open - packet dropped\n");
|
||||
m_freem(bp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
m_settype(bp, MB_IPIN);
|
||||
nb = m_length(bp);
|
||||
if (nb > sizeof tun.data) {
|
||||
log_Printf(LogWARN, "ip_Input: %s: Packet too large (got %d, max %d)\n",
|
||||
l->name, nb, (int)(sizeof tun.data));
|
||||
m_freem(bp);
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
mbuf_Read(bp, tun.data, nb);
|
||||
|
||||
secs = 0;
|
||||
if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in, NULL, &secs) < 0)
|
||||
return NULL;
|
||||
if (PacketCheck(bundle, af, tun.data, nb, &bundle->filter.in,
|
||||
NULL, &secs) < 0)
|
||||
return 0;
|
||||
|
||||
pip = (struct ip *)tun.data;
|
||||
alivesecs = 0;
|
||||
if (!FilterCheck(pip, &bundle->filter.alive, &alivesecs)) {
|
||||
if (!FilterCheck(tun.data, af, &bundle->filter.alive, &alivesecs)) {
|
||||
if (secs == 0)
|
||||
secs = alivesecs;
|
||||
bundle_StartIdleTimer(bundle, secs);
|
||||
}
|
||||
|
||||
ipcp_AddInOctets(&bundle->ncp.ipcp, nb);
|
||||
|
||||
if (bundle->dev.header) {
|
||||
tun.header.family = htonl(AF_INET);
|
||||
tun.header.family = htonl(af);
|
||||
nb += sizeof tun - sizeof tun.data;
|
||||
data = (char *)&tun;
|
||||
} else
|
||||
@ -844,94 +913,45 @@ ip_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
|
||||
log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %d\n", l->name, nb, nw);
|
||||
}
|
||||
|
||||
return nb;
|
||||
}
|
||||
|
||||
struct mbuf *
|
||||
ipv4_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
|
||||
{
|
||||
int nb;
|
||||
|
||||
if (bundle->ncp.ipcp.fsm.state != ST_OPENED) {
|
||||
log_Printf(LogWARN, "ipv4_Input: IPCP not open - packet dropped\n");
|
||||
m_freem(bp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
m_settype(bp, MB_IPIN);
|
||||
|
||||
nb = ip_Input(bundle, l, bp, AF_INET);
|
||||
ipcp_AddInOctets(&bundle->ncp.ipcp, nb);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
ip_Enqueue(struct ipcp *ipcp, int pri, char *ptr, int count)
|
||||
#ifndef NOINET6
|
||||
struct mbuf *
|
||||
ipv6_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
|
||||
{
|
||||
struct mbuf *bp;
|
||||
int nb;
|
||||
|
||||
if (pri < 0 || pri >= IPCP_QUEUES(ipcp))
|
||||
log_Printf(LogERROR, "Can't store in ip queue %d\n", pri);
|
||||
else {
|
||||
/*
|
||||
* We allocate an extra 6 bytes, four at the front and two at the end.
|
||||
* This is an optimisation so that we need to do less work in
|
||||
* m_prepend() in acf_LayerPush() and proto_LayerPush() and
|
||||
* appending in hdlc_LayerPush().
|
||||
*/
|
||||
bp = m_get(count + 6, MB_IPOUT);
|
||||
bp->m_offset += 4;
|
||||
bp->m_len -= 6;
|
||||
memcpy(MBUF_CTOP(bp), ptr, count);
|
||||
m_enqueue(ipcp->Queue + pri, bp);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ip_DeleteQueue(struct ipcp *ipcp)
|
||||
{
|
||||
struct mqueue *queue;
|
||||
|
||||
for (queue = ipcp->Queue; queue < ipcp->Queue + IPCP_QUEUES(ipcp); queue++)
|
||||
while (queue->top)
|
||||
m_freem(m_dequeue(queue));
|
||||
}
|
||||
|
||||
size_t
|
||||
ip_QueueLen(struct ipcp *ipcp)
|
||||
{
|
||||
struct mqueue *queue;
|
||||
size_t result;
|
||||
|
||||
result = 0;
|
||||
for (queue = ipcp->Queue; queue < ipcp->Queue + IPCP_QUEUES(ipcp); queue++)
|
||||
result += queue->len;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
ip_PushPacket(struct link *l, struct bundle *bundle)
|
||||
{
|
||||
struct ipcp *ipcp = &bundle->ncp.ipcp;
|
||||
struct mqueue *queue;
|
||||
struct mbuf *bp;
|
||||
struct ip *pip;
|
||||
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;
|
||||
if (bundle->ncp.ipv6cp.fsm.state != ST_OPENED) {
|
||||
log_Printf(LogWARN, "ipv6_Input: IPV6CP not open - packet dropped\n");
|
||||
m_freem(bp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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);
|
||||
pip = (struct ip *)MBUF_CTOP(bp);
|
||||
if (!FilterCheck(pip, &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);
|
||||
m_settype(bp, MB_IPV6IN);
|
||||
|
||||
return 0;
|
||||
nb = ip_Input(bundle, l, bp, AF_INET6);
|
||||
ipv6cp_AddInOctets(&bundle->ncp.ipv6cp, nb);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
@ -34,9 +34,11 @@ struct link;
|
||||
struct bundle;
|
||||
|
||||
extern int ip_PushPacket(struct link *, struct bundle *);
|
||||
extern int PacketCheck(struct bundle *, unsigned char *, int, struct filter *,
|
||||
const char *, unsigned *secs);
|
||||
extern void ip_Enqueue(struct ipcp *, int, char *, int);
|
||||
extern struct mbuf *ip_Input(struct bundle *, struct link *, struct mbuf *);
|
||||
extern void ip_DeleteQueue(struct ipcp *);
|
||||
extern size_t ip_QueueLen(struct ipcp *);
|
||||
extern int PacketCheck(struct bundle *, u_int32_t, const unsigned char *, int,
|
||||
struct filter *, const char *, unsigned *secs);
|
||||
extern int FilterCheck(const unsigned char *, u_int32_t, const struct filter *,
|
||||
unsigned *);
|
||||
extern struct mbuf *ipv4_Input(struct bundle *, struct link *, struct mbuf *);
|
||||
#ifndef NOINET6
|
||||
extern struct mbuf *ipv6_Input(struct bundle *, struct link *, struct mbuf *);
|
||||
#endif
|
||||
|
@ -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;
|
||||
|
||||
if (ipcp->dns[1].s_addr == INADDR_NONE)
|
||||
ipcp->dns[1] = ipcp->dns[0];
|
||||
memcpy(ipcp->ns.dns, ipcp->cfg.ns.dns, sizeof ipcp->ns.dns);
|
||||
}
|
||||
|
||||
static int
|
||||
ipcp_doproxyall(struct bundle *bundle,
|
||||
int (*proxyfun)(struct bundle *, struct in_addr, int), int s)
|
||||
numaddresses(struct in_addr mask)
|
||||
{
|
||||
int n, ret;
|
||||
struct sticky_route *rp;
|
||||
struct in_addr addr;
|
||||
struct ipcp *ipcp;
|
||||
u_int32_t bit, haddr;
|
||||
int n;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
haddr = ntohl(mask.s_addr);
|
||||
bit = 1;
|
||||
n = 1;
|
||||
|
||||
do {
|
||||
if (!(haddr & bit))
|
||||
n <<= 1;
|
||||
} while (bit <<= 1);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static int
|
||||
ipcp_proxyarp(struct ipcp *ipcp,
|
||||
int (*proxyfun)(struct bundle *, struct in_addr, int),
|
||||
const struct iface_addr *addr)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
ipcp->peer_ip = hisaddr;
|
||||
ncprange_setip4host(&ipcp->cfg.peer_range, hisaddr);
|
||||
ncprange_getip4addr(&ipcp->cfg.my_range, &myaddr);
|
||||
|
||||
if (ipcp_SetIPaddress(bundle, ipcp->cfg.my_range.ipaddr, hisaddr, 0) < 0)
|
||||
return 0;
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -42,20 +42,6 @@
|
||||
#define TY_SECONDARY_NBNS 132
|
||||
#define TY_ADJUST_NS 119 /* subtract from NS val for REJECT bit */
|
||||
|
||||
struct sticky_route;
|
||||
|
||||
struct in_range {
|
||||
struct in_addr ipaddr;
|
||||
struct in_addr mask;
|
||||
int width;
|
||||
};
|
||||
|
||||
struct port_range {
|
||||
unsigned nports; /* How many ports */
|
||||
unsigned maxports; /* How many allocated (malloc) ports */
|
||||
u_short *port; /* The actual ports */
|
||||
};
|
||||
|
||||
struct ipcp {
|
||||
struct fsm fsm; /* The finite state machine */
|
||||
|
||||
@ -66,14 +52,11 @@ struct ipcp {
|
||||
unsigned neg : 2; /* VJ negotiation */
|
||||
} vj;
|
||||
|
||||
struct in_range my_range; /* MYADDR spec */
|
||||
struct ncprange my_range; /* MYADDR spec */
|
||||
struct in_addr netmask; /* Iface netmask (unused by most OSs) */
|
||||
struct in_range peer_range; /* HISADDR spec */
|
||||
struct ncprange peer_range; /* HISADDR spec */
|
||||
struct iplist peer_list; /* Ranges of HISADDR values */
|
||||
|
||||
u_long sendpipe; /* route sendpipe size */
|
||||
u_long recvpipe; /* route recvpipe size */
|
||||
|
||||
struct in_addr TriggerAddress; /* Address to suggest in REQ */
|
||||
unsigned HaveTriggerAddress : 1; /* Trigger address specified */
|
||||
|
||||
@ -83,12 +66,7 @@ struct ipcp {
|
||||
struct in_addr nbns[2]; /* NetBIOS NS addresses offered */
|
||||
} ns;
|
||||
|
||||
struct {
|
||||
struct port_range tcp, udp; /* The range of urgent ports */
|
||||
unsigned tos : 1; /* Urgent IPTOS_LOWDELAY packets ? */
|
||||
} urgent;
|
||||
|
||||
struct fsm_retry fsm; /* How often/frequently to resend requests */
|
||||
struct fsm_retry fsm; /* frequency to resend requests */
|
||||
} cfg;
|
||||
|
||||
struct {
|
||||
@ -104,8 +82,6 @@ struct ipcp {
|
||||
char *resolv_nons; /* Contents of resolv.conf without ns */
|
||||
} ns;
|
||||
|
||||
struct sticky_route *route; /* List of dynamic routes */
|
||||
|
||||
unsigned heis1172 : 1; /* True if he is speaking rfc1172 */
|
||||
|
||||
unsigned peer_req : 1; /* Any TY_IPADDR REQs from the peer ? */
|
||||
@ -117,8 +93,6 @@ struct ipcp {
|
||||
struct in_addr my_ip; /* IP address I'm willing to use */
|
||||
u_int32_t my_compproto; /* VJ params I'm willing to use */
|
||||
|
||||
struct in_addr dns[2]; /* DNSs to REQ/ACK */
|
||||
|
||||
u_int32_t peer_reject; /* Request codes rejected by peer */
|
||||
u_int32_t my_reject; /* Request codes I have rejected */
|
||||
|
||||
@ -132,6 +106,7 @@ struct ipcp {
|
||||
struct bundle;
|
||||
struct link;
|
||||
struct cmdargs;
|
||||
struct iface_addr;
|
||||
|
||||
extern void ipcp_Init(struct ipcp *, struct bundle *, struct link *,
|
||||
const struct fsm_parent *);
|
||||
@ -146,32 +121,12 @@ extern void ipcp_AddOutOctets(struct ipcp *, int);
|
||||
extern int ipcp_UseHisIPaddr(struct bundle *, struct in_addr);
|
||||
extern int ipcp_UseHisaddr(struct bundle *, const char *, int);
|
||||
extern int ipcp_vjset(struct cmdargs const *);
|
||||
extern void ipcp_CleanInterface(struct ipcp *);
|
||||
extern void ipcp_IfaceAddrAdded(struct ipcp *, const struct iface_addr *);
|
||||
extern void ipcp_IfaceAddrDeleted(struct ipcp *, const struct iface_addr *);
|
||||
extern int ipcp_InterfaceUp(struct ipcp *);
|
||||
extern int ipcp_IsUrgentPort(struct port_range *, u_short, u_short);
|
||||
extern void ipcp_AddUrgentPort(struct port_range *, u_short);
|
||||
extern void ipcp_RemoveUrgentPort(struct port_range *, u_short);
|
||||
extern void ipcp_ClearUrgentPorts(struct port_range *);
|
||||
extern struct in_addr addr2mask(struct in_addr);
|
||||
extern int ipcp_WriteDNS(struct ipcp *);
|
||||
extern void ipcp_RestoreDNS(struct ipcp *);
|
||||
extern void ipcp_LoadDNS(struct ipcp *);
|
||||
|
||||
#define ipcp_IsUrgentTcpPort(ipcp, p1, p2) \
|
||||
ipcp_IsUrgentPort(&(ipcp)->cfg.urgent.tcp, p1, p2)
|
||||
#define ipcp_IsUrgentUdpPort(ipcp, p1, p2) \
|
||||
ipcp_IsUrgentPort(&(ipcp)->cfg.urgent.udp, p1, p2)
|
||||
#define ipcp_AddUrgentTcpPort(ipcp, p) \
|
||||
ipcp_AddUrgentPort(&(ipcp)->cfg.urgent.tcp, p)
|
||||
#define ipcp_AddUrgentUdpPort(ipcp, p) \
|
||||
ipcp_AddUrgentPort(&(ipcp)->cfg.urgent.udp, p)
|
||||
#define ipcp_RemoveUrgentTcpPort(ipcp, p) \
|
||||
ipcp_RemoveUrgentPort(&(ipcp)->cfg.urgent.tcp, p)
|
||||
#define ipcp_RemoveUrgentUdpPort(ipcp, p) \
|
||||
ipcp_RemoveUrgentPort(&(ipcp)->cfg.urgent.udp, p)
|
||||
#define ipcp_ClearUrgentTcpPorts(ipcp) \
|
||||
ipcp_ClearUrgentPorts(&(ipcp)->cfg.urgent.tcp)
|
||||
#define ipcp_ClearUrgentUdpPorts(ipcp) \
|
||||
ipcp_ClearUrgentPorts(&(ipcp)->cfg.urgent.udp)
|
||||
#define ipcp_ClearUrgentTOS(ipcp) (ipcp)->cfg.urgent.tos = 0;
|
||||
#define ipcp_SetUrgentTOS(ipcp) (ipcp)->cfg.urgent.tos = 1;
|
||||
extern size_t ipcp_QueueLen(struct ipcp *);
|
||||
extern int ipcp_PushPacket(struct ipcp *, struct link *);
|
||||
|
601
usr.sbin/ppp/ipv6cp.c
Normal file
601
usr.sbin/ppp/ipv6cp.c
Normal file
@ -0,0 +1,601 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Brian Somers <brian@Awfulhak.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/route.h>
|
||||
#include <net/if.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include "layer.h"
|
||||
#include "defs.h"
|
||||
#include "mbuf.h"
|
||||
#include "timer.h"
|
||||
#include "fsm.h"
|
||||
#include "iplist.h"
|
||||
#include "throughput.h"
|
||||
#include "slcompress.h"
|
||||
#include "lqr.h"
|
||||
#include "hdlc.h"
|
||||
#include "lcp.h"
|
||||
#include "ncpaddr.h"
|
||||
#include "ip.h"
|
||||
#include "ipcp.h"
|
||||
#include "ipv6cp.h"
|
||||
#include "filter.h"
|
||||
#include "descriptor.h"
|
||||
#include "ccp.h"
|
||||
#include "link.h"
|
||||
#include "mp.h"
|
||||
#ifndef NORADIUS
|
||||
#include "radius.h"
|
||||
#endif
|
||||
#include "ncp.h"
|
||||
#include "bundle.h"
|
||||
#include "route.h"
|
||||
#include "iface.h"
|
||||
#include "log.h"
|
||||
#include "proto.h"
|
||||
#include "command.h"
|
||||
#include "prompt.h"
|
||||
#include "async.h"
|
||||
#include "physical.h"
|
||||
|
||||
|
||||
#ifndef NOINET6
|
||||
static int ipv6cp_LayerUp(struct fsm *);
|
||||
static void ipv6cp_LayerDown(struct fsm *);
|
||||
static void ipv6cp_LayerStart(struct fsm *);
|
||||
static void ipv6cp_LayerFinish(struct fsm *);
|
||||
static void ipv6cp_InitRestartCounter(struct fsm *, int);
|
||||
static void ipv6cp_SendConfigReq(struct fsm *);
|
||||
static void ipv6cp_SentTerminateReq(struct fsm *);
|
||||
static void ipv6cp_SendTerminateAck(struct fsm *, u_char);
|
||||
static void ipv6cp_DecodeConfig(struct fsm *, u_char *, int, int,
|
||||
struct fsm_decode *);
|
||||
|
||||
static struct fsm_callbacks ipv6cp_Callbacks = {
|
||||
ipv6cp_LayerUp,
|
||||
ipv6cp_LayerDown,
|
||||
ipv6cp_LayerStart,
|
||||
ipv6cp_LayerFinish,
|
||||
ipv6cp_InitRestartCounter,
|
||||
ipv6cp_SendConfigReq,
|
||||
ipv6cp_SentTerminateReq,
|
||||
ipv6cp_SendTerminateAck,
|
||||
ipv6cp_DecodeConfig,
|
||||
fsm_NullRecvResetReq,
|
||||
fsm_NullRecvResetAck
|
||||
};
|
||||
|
||||
static u_int32_t
|
||||
GenerateToken(void)
|
||||
{
|
||||
/* Generate random number which will be used as negotiation token */
|
||||
randinit();
|
||||
|
||||
return random() + 1;
|
||||
}
|
||||
|
||||
static int
|
||||
ipcp_SetIPv6address(struct ipv6cp *ipv6cp, u_int32_t mytok, u_int32_t histok)
|
||||
{
|
||||
struct bundle *bundle = ipv6cp->fsm.bundle;
|
||||
struct in6_addr myaddr, hisaddr;
|
||||
struct ncprange myrange, dst;
|
||||
|
||||
memset(&myaddr, '\0', sizeof myaddr);
|
||||
memset(&hisaddr, '\0', sizeof hisaddr);
|
||||
|
||||
myaddr.s6_addr[0] = 0xfe;
|
||||
myaddr.s6_addr[1] = 0x80;
|
||||
*(u_int32_t *)(myaddr.s6_addr + 12) = htonl(mytok);
|
||||
|
||||
hisaddr.s6_addr[0] = 0xfe;
|
||||
hisaddr.s6_addr[1] = 0x80;
|
||||
*(u_int32_t *)(hisaddr.s6_addr + 12) = htonl(histok);
|
||||
|
||||
ncpaddr_setip6(&ipv6cp->myaddr, &myaddr);
|
||||
ncpaddr_setip6(&ipv6cp->hisaddr, &hisaddr);
|
||||
ncprange_sethost(&myrange, &ipv6cp->myaddr);
|
||||
|
||||
if (!iface_Add(bundle->iface, &bundle->ncp, &myrange, &ipv6cp->hisaddr,
|
||||
IFACE_ADD_FIRST|IFACE_FORCE_ADD|IFACE_SYSTEM))
|
||||
return 0;
|
||||
|
||||
if (!Enabled(bundle, OPT_IFACEALIAS))
|
||||
iface_Clear(bundle->iface, &bundle->ncp, AF_INET6,
|
||||
IFACE_CLEAR_ALIASES|IFACE_SYSTEM);
|
||||
|
||||
if (bundle->ncp.cfg.sendpipe > 0 || bundle->ncp.cfg.recvpipe > 0) {
|
||||
ncprange_sethost(&dst, &ipv6cp->hisaddr);
|
||||
rt_Update(bundle, &dst);
|
||||
}
|
||||
|
||||
if (Enabled(bundle, OPT_SROUTES))
|
||||
route_Change(bundle, bundle->ncp.route, &ipv6cp->myaddr, &ipv6cp->hisaddr);
|
||||
|
||||
#ifndef NORADIUS
|
||||
if (bundle->radius.valid)
|
||||
route_Change(bundle, bundle->radius.routes, &ipv6cp->myaddr,
|
||||
&ipv6cp->hisaddr);
|
||||
#endif
|
||||
|
||||
return 1; /* Ok */
|
||||
}
|
||||
|
||||
void
|
||||
ipv6cp_Init(struct ipv6cp *ipv6cp, struct bundle *bundle, struct link *l,
|
||||
const struct fsm_parent *parent)
|
||||
{
|
||||
static const char * const timer_names[] =
|
||||
{"IPV6CP restart", "IPV6CP openmode", "IPV6CP stopped"};
|
||||
int n;
|
||||
|
||||
fsm_Init(&ipv6cp->fsm, "IPV6CP", PROTO_IPV6CP, 1, IPV6CP_MAXCODE, LogIPV6CP,
|
||||
bundle, l, parent, &ipv6cp_Callbacks, timer_names);
|
||||
|
||||
ipv6cp->cfg.fsm.timeout = DEF_FSMRETRY;
|
||||
ipv6cp->cfg.fsm.maxreq = DEF_FSMTRIES;
|
||||
ipv6cp->cfg.fsm.maxtrm = DEF_FSMTRIES;
|
||||
|
||||
ipv6cp->my_token = GenerateToken();
|
||||
while ((ipv6cp->peer_token = GenerateToken()) == ipv6cp->my_token)
|
||||
;
|
||||
|
||||
n = 100;
|
||||
while (n &&
|
||||
!ipcp_SetIPv6address(ipv6cp, ipv6cp->my_token, ipv6cp->peer_token))
|
||||
while (n && (ipv6cp->my_token = GenerateToken()) == ipv6cp->peer_token)
|
||||
n--;
|
||||
|
||||
throughput_init(&ipv6cp->throughput, SAMPLE_PERIOD);
|
||||
memset(ipv6cp->Queue, '\0', sizeof ipv6cp->Queue);
|
||||
ipv6cp_Setup(ipv6cp);
|
||||
}
|
||||
|
||||
void
|
||||
ipv6cp_Destroy(struct ipv6cp *ipv6cp)
|
||||
{
|
||||
throughput_destroy(&ipv6cp->throughput);
|
||||
}
|
||||
|
||||
void
|
||||
ipv6cp_Setup(struct ipv6cp *ipv6cp)
|
||||
{
|
||||
ncpaddr_init(&ipv6cp->myaddr);
|
||||
ncpaddr_init(&ipv6cp->hisaddr);
|
||||
|
||||
ipv6cp->his_reject = 0;
|
||||
ipv6cp->my_reject = 0;
|
||||
}
|
||||
|
||||
void
|
||||
ipv6cp_SetLink(struct ipv6cp *ipv6cp, struct link *l)
|
||||
{
|
||||
ipv6cp->fsm.link = l;
|
||||
}
|
||||
|
||||
int
|
||||
ipv6cp_Show(struct cmdargs const *arg)
|
||||
{
|
||||
struct ipv6cp *ipv6cp = &arg->bundle->ncp.ipv6cp;
|
||||
|
||||
prompt_Printf(arg->prompt, "%s [%s]\n", ipv6cp->fsm.name,
|
||||
State2Nam(ipv6cp->fsm.state));
|
||||
if (ipv6cp->fsm.state == ST_OPENED) {
|
||||
prompt_Printf(arg->prompt, " His side: %s\n",
|
||||
ncpaddr_ntoa(&ipv6cp->hisaddr));
|
||||
prompt_Printf(arg->prompt, " My side: %s\n",
|
||||
ncpaddr_ntoa(&ipv6cp->myaddr));
|
||||
prompt_Printf(arg->prompt, " Queued packets: %lu\n",
|
||||
(unsigned long)ipv6cp_QueueLen(ipv6cp));
|
||||
}
|
||||
|
||||
prompt_Printf(arg->prompt, "\nDefaults:\n");
|
||||
prompt_Printf(arg->prompt, " FSM retry = %us, max %u Config"
|
||||
" REQ%s, %u Term REQ%s\n\n", ipv6cp->cfg.fsm.timeout,
|
||||
ipv6cp->cfg.fsm.maxreq, ipv6cp->cfg.fsm.maxreq == 1 ? "" : "s",
|
||||
ipv6cp->cfg.fsm.maxtrm, ipv6cp->cfg.fsm.maxtrm == 1 ? "" : "s");
|
||||
|
||||
throughput_disp(&ipv6cp->throughput, arg->prompt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct mbuf *
|
||||
ipv6cp_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
|
||||
{
|
||||
/* Got PROTO_IPV6CP from link */
|
||||
m_settype(bp, MB_IPV6CPIN);
|
||||
if (bundle_Phase(bundle) == PHASE_NETWORK)
|
||||
fsm_Input(&bundle->ncp.ipv6cp.fsm, bp);
|
||||
else {
|
||||
if (bundle_Phase(bundle) < PHASE_NETWORK)
|
||||
log_Printf(LogIPV6CP, "%s: Error: Unexpected IPV6CP in phase %s"
|
||||
" (ignored)\n", l->name, bundle_PhaseName(bundle));
|
||||
m_freem(bp);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
ipv6cp_AddInOctets(struct ipv6cp *ipv6cp, int n)
|
||||
{
|
||||
throughput_addin(&ipv6cp->throughput, n);
|
||||
}
|
||||
|
||||
void
|
||||
ipv6cp_AddOutOctets(struct ipv6cp *ipv6cp, int n)
|
||||
{
|
||||
throughput_addout(&ipv6cp->throughput, n);
|
||||
}
|
||||
|
||||
void
|
||||
ipv6cp_IfaceAddrAdded(struct ipv6cp *ipv6cp, const struct iface_addr *addr)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ipv6cp_IfaceAddrDeleted(struct ipv6cp *ipv6cp, const struct iface_addr *addr)
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
ipv6cp_InterfaceUp(struct ipv6cp *ipv6cp)
|
||||
{
|
||||
if (!ipcp_SetIPv6address(ipv6cp, ipv6cp->my_token, ipv6cp->peer_token)) {
|
||||
log_Printf(LogERROR, "ipv6cp_InterfaceUp: unable to set ipv6 address\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!iface_SetFlags(ipv6cp->fsm.bundle->iface->name, IFF_UP)) {
|
||||
log_Printf(LogERROR, "ipv6cp_InterfaceUp: Can't set the IFF_UP"
|
||||
" flag on %s\n", ipv6cp->fsm.bundle->iface->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t
|
||||
ipv6cp_QueueLen(struct ipv6cp *ipv6cp)
|
||||
{
|
||||
struct mqueue *q;
|
||||
size_t result;
|
||||
|
||||
result = 0;
|
||||
for (q = ipv6cp->Queue; q < ipv6cp->Queue + IPV6CP_QUEUES(ipv6cp); q++)
|
||||
result += q->len;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
ipv6cp_PushPacket(struct ipv6cp *ipv6cp, struct link *l)
|
||||
{
|
||||
struct bundle *bundle = ipv6cp->fsm.bundle;
|
||||
struct mqueue *queue;
|
||||
struct mbuf *bp;
|
||||
int m_len;
|
||||
u_int32_t secs = 0;
|
||||
unsigned alivesecs = 0;
|
||||
|
||||
if (ipv6cp->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 = ipv6cp->Queue + IPV6CP_QUEUES(ipv6cp) - 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_INET6, &bundle->filter.alive,
|
||||
&alivesecs)) {
|
||||
if (secs == 0)
|
||||
secs = alivesecs;
|
||||
bundle_StartIdleTimer(bundle, secs);
|
||||
}
|
||||
link_PushPacket(l, bp, bundle, 0, PROTO_IPV6);
|
||||
ipv6cp_AddOutOctets(ipv6cp, m_len);
|
||||
return 1;
|
||||
}
|
||||
} while (queue-- != ipv6cp->Queue);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ipv6cp_LayerUp(struct fsm *fp)
|
||||
{
|
||||
/* We're now up */
|
||||
struct ipv6cp *ipv6cp = fsm2ipv6cp(fp);
|
||||
char tbuff[40];
|
||||
|
||||
log_Printf(LogIPV6CP, "%s: LayerUp.\n", fp->link->name);
|
||||
if (!ipv6cp_InterfaceUp(ipv6cp))
|
||||
return 0;
|
||||
|
||||
snprintf(tbuff, sizeof tbuff, "%s", ncpaddr_ntoa(&ipv6cp->myaddr));
|
||||
log_Printf(LogIPV6CP, "myaddr %s hisaddr = %s\n",
|
||||
tbuff, ncpaddr_ntoa(&ipv6cp->hisaddr));
|
||||
|
||||
/* XXX: Call radius_Account() and system_Select() */
|
||||
|
||||
fp->more.reqs = fp->more.naks = fp->more.rejs = ipv6cp->cfg.fsm.maxreq * 3;
|
||||
log_DisplayPrompts();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
ipv6cp_LayerDown(struct fsm *fp)
|
||||
{
|
||||
/* About to come down */
|
||||
struct ipv6cp *ipv6cp = fsm2ipv6cp(fp);
|
||||
static int recursing;
|
||||
char addr[40];
|
||||
|
||||
if (!recursing++) {
|
||||
snprintf(addr, sizeof addr, "%s", ncpaddr_ntoa(&ipv6cp->myaddr));
|
||||
log_Printf(LogIPV6CP, "%s: LayerDown: %s\n", fp->link->name, addr);
|
||||
|
||||
/* XXX: Call radius_Account() and system_Select() */
|
||||
|
||||
ipv6cp_Setup(ipv6cp);
|
||||
}
|
||||
recursing--;
|
||||
}
|
||||
|
||||
static void
|
||||
ipv6cp_LayerStart(struct fsm *fp)
|
||||
{
|
||||
/* We're about to start up ! */
|
||||
struct ipv6cp *ipv6cp = fsm2ipv6cp(fp);
|
||||
|
||||
log_Printf(LogIPV6CP, "%s: LayerStart.\n", fp->link->name);
|
||||
throughput_start(&ipv6cp->throughput, "IPV6CP throughput",
|
||||
Enabled(fp->bundle, OPT_THROUGHPUT));
|
||||
fp->more.reqs = fp->more.naks = fp->more.rejs = ipv6cp->cfg.fsm.maxreq * 3;
|
||||
ipv6cp->peer_tokenreq = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ipv6cp_LayerFinish(struct fsm *fp)
|
||||
{
|
||||
/* We're now down */
|
||||
struct ipv6cp *ipv6cp = fsm2ipv6cp(fp);
|
||||
|
||||
log_Printf(LogIPV6CP, "%s: LayerFinish.\n", fp->link->name);
|
||||
throughput_stop(&ipv6cp->throughput);
|
||||
throughput_log(&ipv6cp->throughput, LogIPV6CP, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
ipv6cp_InitRestartCounter(struct fsm *fp, int what)
|
||||
{
|
||||
/* Set fsm timer load */
|
||||
struct ipv6cp *ipv6cp = fsm2ipv6cp(fp);
|
||||
|
||||
fp->FsmTimer.load = ipv6cp->cfg.fsm.timeout * SECTICKS;
|
||||
switch (what) {
|
||||
case FSM_REQ_TIMER:
|
||||
fp->restart = ipv6cp->cfg.fsm.maxreq;
|
||||
break;
|
||||
case FSM_TRM_TIMER:
|
||||
fp->restart = ipv6cp->cfg.fsm.maxtrm;
|
||||
break;
|
||||
default:
|
||||
fp->restart = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ipv6cp_SendConfigReq(struct fsm *fp)
|
||||
{
|
||||
/* Send config REQ please */
|
||||
struct physical *p = link2physical(fp->link);
|
||||
struct ipv6cp *ipv6cp = fsm2ipv6cp(fp);
|
||||
u_char buff[6];
|
||||
struct lcp_opt *o;
|
||||
|
||||
o = (struct lcp_opt *)buff;
|
||||
|
||||
if ((p && !physical_IsSync(p)) || !REJECTED(ipv6cp, TY_TOKEN)) {
|
||||
memcpy(o->data, &ipv6cp->my_token, 4);
|
||||
INC_LCP_OPT(TY_TOKEN, 6, o);
|
||||
}
|
||||
|
||||
fsm_Output(fp, CODE_CONFIGREQ, fp->reqid, buff, (u_char *)o - buff,
|
||||
MB_IPV6CPOUT);
|
||||
}
|
||||
|
||||
static void
|
||||
ipv6cp_SentTerminateReq(struct fsm *fp)
|
||||
{
|
||||
/* Term REQ just sent by FSM */
|
||||
}
|
||||
|
||||
static void
|
||||
ipv6cp_SendTerminateAck(struct fsm *fp, u_char id)
|
||||
{
|
||||
/* Send Term ACK please */
|
||||
fsm_Output(fp, CODE_TERMACK, id, NULL, 0, MB_IPV6CPOUT);
|
||||
}
|
||||
|
||||
static const char *
|
||||
protoname(int proto)
|
||||
{
|
||||
static const char *cftypes[] = { "TOKEN", "COMPPROTO" };
|
||||
|
||||
if (proto > 0 && proto <= sizeof cftypes / sizeof *cftypes)
|
||||
return cftypes[proto - 1];
|
||||
|
||||
return NumStr(proto, NULL, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
ipv6cp_ValidateToken(struct ipv6cp *ipv6cp, u_int32_t token,
|
||||
struct fsm_decode *dec)
|
||||
{
|
||||
if (token != 0 && token != ipv6cp->my_token)
|
||||
ipv6cp->peer_token = token;
|
||||
|
||||
if (token == ipv6cp->peer_token) {
|
||||
*dec->ackend++ = TY_TOKEN;
|
||||
*dec->ackend++ = 6;
|
||||
memcpy(dec->ackend, &ipv6cp->peer_token, 4);
|
||||
dec->ackend += 4;
|
||||
} else {
|
||||
*dec->nakend++ = TY_TOKEN;
|
||||
*dec->nakend++ = 6;
|
||||
memcpy(dec->nakend, &ipv6cp->peer_token, 4);
|
||||
dec->nakend += 4;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ipv6cp_DecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type,
|
||||
struct fsm_decode *dec)
|
||||
{
|
||||
/* Deal with incoming PROTO_IPV6CP */
|
||||
struct ipv6cp *ipv6cp = fsm2ipv6cp(fp);
|
||||
int type, length, n;
|
||||
char tbuff[100];
|
||||
u_int32_t token;
|
||||
|
||||
while (plen >= sizeof(struct fsmconfig)) {
|
||||
type = *cp;
|
||||
length = cp[1];
|
||||
|
||||
if (length == 0) {
|
||||
log_Printf(LogIPV6CP, "%s: IPV6CP size zero\n", fp->link->name);
|
||||
break;
|
||||
}
|
||||
|
||||
snprintf(tbuff, sizeof tbuff, " %s[%d] ", protoname(type), length);
|
||||
|
||||
switch (type) {
|
||||
case TY_TOKEN:
|
||||
memcpy(&token, cp + 2, 4);
|
||||
log_Printf(LogIPV6CP, "%s 0x%08lx\n", tbuff, (unsigned long)token);
|
||||
|
||||
switch (mode_type) {
|
||||
case MODE_REQ:
|
||||
ipv6cp->peer_tokenreq = 1;
|
||||
ipv6cp_ValidateToken(ipv6cp, token, dec);
|
||||
break;
|
||||
|
||||
case MODE_NAK:
|
||||
if (token == 0) {
|
||||
log_Printf(log_IsKept(LogIPV6CP) ? LogIPV6CP : LogPHASE,
|
||||
"0x00000000: Unacceptable token!\n");
|
||||
fsm_Close(&ipv6cp->fsm);
|
||||
} else if (token == ipv6cp->peer_token)
|
||||
log_Printf(log_IsKept(LogIPV6CP) ? LogIPV6CP : LogPHASE,
|
||||
"0x08lx: Unacceptable token!\n", (unsigned long)token);
|
||||
else if (token != ipv6cp->my_token) {
|
||||
n = 100;
|
||||
while (n && !ipcp_SetIPv6address(ipv6cp, token, ipv6cp->peer_token))
|
||||
while (n && (token = GenerateToken()) == ipv6cp->peer_token)
|
||||
n--;
|
||||
|
||||
if (n == 0) {
|
||||
log_Printf(log_IsKept(LogIPV6CP) ? LogIPV6CP : LogPHASE,
|
||||
"0x00000000: Unacceptable token!\n");
|
||||
fsm_Close(&ipv6cp->fsm);
|
||||
} else {
|
||||
log_Printf(LogIPV6CP, "%s changing token: 0x%08lx --> 0x%08lx\n",
|
||||
tbuff, (unsigned long)ipv6cp->my_token,
|
||||
(unsigned long)token);
|
||||
ipv6cp->my_token = token;
|
||||
bundle_AdjustFilters(fp->bundle, &ipv6cp->myaddr, NULL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MODE_REJ:
|
||||
ipv6cp->his_reject |= (1 << type);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (mode_type != MODE_NOP) {
|
||||
ipv6cp->my_reject |= (1 << type);
|
||||
memcpy(dec->rejend, cp, length);
|
||||
dec->rejend += length;
|
||||
}
|
||||
break;
|
||||
}
|
||||
plen -= length;
|
||||
cp += length;
|
||||
}
|
||||
|
||||
if (mode_type != MODE_NOP) {
|
||||
if (mode_type == MODE_REQ && !ipv6cp->peer_tokenreq) {
|
||||
if (dec->rejend == dec->rej && dec->nakend == dec->nak) {
|
||||
/*
|
||||
* Pretend the peer has requested a TOKEN.
|
||||
* We do this to ensure that we only send one NAK if the only
|
||||
* reason for the NAK is because the peer isn't sending a
|
||||
* TY_TOKEN REQ. This stops us from repeatedly trying to tell
|
||||
* the peer that we have to have an IP address on their end.
|
||||
*/
|
||||
ipv6cp->peer_tokenreq = 1;
|
||||
}
|
||||
ipv6cp_ValidateToken(ipv6cp, 0, dec);
|
||||
}
|
||||
if (dec->rejend != dec->rej) {
|
||||
/* rejects are preferred */
|
||||
dec->ackend = dec->ack;
|
||||
dec->nakend = dec->nak;
|
||||
} else if (dec->nakend != dec->nak)
|
||||
/* then NAKs */
|
||||
dec->ackend = dec->ack;
|
||||
}
|
||||
}
|
||||
#endif
|
81
usr.sbin/ppp/ipv6cp.h
Normal file
81
usr.sbin/ppp/ipv6cp.h
Normal file
@ -0,0 +1,81 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Brian Somers <brian@Awfulhak.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef NOINET6
|
||||
#define IPV6CP_MAXCODE CODE_CODEREJ
|
||||
|
||||
#define TY_TOKEN 1
|
||||
#define TY_COMPPROTO 2
|
||||
|
||||
struct ipv6cp {
|
||||
struct fsm fsm; /* The finite state machine */
|
||||
|
||||
struct {
|
||||
struct fsm_retry fsm; /* frequency to resend requests */
|
||||
} cfg;
|
||||
|
||||
unsigned peer_tokenreq : 1; /* Any TY_TOKEN REQs from the peer ? */
|
||||
|
||||
u_int32_t my_token; /* Token I'm willing to use */
|
||||
u_int32_t peer_token; /* Token he's willing to use */
|
||||
|
||||
struct ncpaddr myaddr; /* Local address */
|
||||
struct ncpaddr hisaddr; /* Peer address */
|
||||
|
||||
u_int32_t his_reject; /* Request codes rejected by peer */
|
||||
u_int32_t my_reject; /* Request codes I have rejected */
|
||||
|
||||
struct pppThroughput throughput; /* throughput statistics */
|
||||
struct mqueue Queue[2]; /* Output packet queues */
|
||||
};
|
||||
|
||||
#define fsm2ipv6cp(fp) (fp->proto == PROTO_IPV6CP ? (struct ipv6cp *)fp : NULL)
|
||||
#define IPV6CP_QUEUES(ipv6cp) (sizeof ipv6cp->Queue / sizeof ipv6cp->Queue[0])
|
||||
|
||||
struct bundle;
|
||||
struct link;
|
||||
struct cmdargs;
|
||||
struct iface_addr;
|
||||
|
||||
extern void ipv6cp_Init(struct ipv6cp *, struct bundle *, struct link *,
|
||||
const struct fsm_parent *);
|
||||
extern void ipv6cp_Destroy(struct ipv6cp *);
|
||||
extern void ipv6cp_Setup(struct ipv6cp *);
|
||||
extern void ipv6cp_SetLink(struct ipv6cp *, struct link *);
|
||||
|
||||
extern int ipv6cp_Show(struct cmdargs const *);
|
||||
extern struct mbuf *ipv6cp_Input(struct bundle *, struct link *, struct mbuf *);
|
||||
extern void ipv6cp_AddInOctets(struct ipv6cp *, int);
|
||||
extern void ipv6cp_AddOutOctets(struct ipv6cp *, int);
|
||||
|
||||
extern void ipv6cp_IfaceAddrAdded(struct ipv6cp *, const struct iface_addr *);
|
||||
extern void ipv6cp_IfaceAddrDeleted(struct ipv6cp *, const struct iface_addr *);
|
||||
extern int ipv6cp_InterfaceUp(struct ipv6cp *);
|
||||
extern size_t ipv6cp_QueueLen(struct ipv6cp *);
|
||||
extern int ipv6cp_PushPacket(struct ipv6cp *, struct link *);
|
||||
#endif
|
@ -32,6 +32,7 @@
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <signal.h>
|
||||
@ -62,6 +63,8 @@
|
||||
#include "physical.h"
|
||||
#include "prompt.h"
|
||||
#include "slcompress.h"
|
||||
#include "ncpaddr.h"
|
||||
#include "ip.h"
|
||||
#include "ipcp.h"
|
||||
#include "filter.h"
|
||||
#include "mp.h"
|
||||
@ -73,6 +76,8 @@
|
||||
#ifndef NORADIUS
|
||||
#include "radius.h"
|
||||
#endif
|
||||
#include "ipv6cp.h"
|
||||
#include "ncp.h"
|
||||
#include "bundle.h"
|
||||
|
||||
/* for received LQRs */
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
@ -57,8 +58,10 @@
|
||||
#include "mp.h"
|
||||
#include "iplist.h"
|
||||
#include "slcompress.h"
|
||||
#include "ipcp.h"
|
||||
#include "ncpaddr.h"
|
||||
#include "ip.h"
|
||||
#include "ipcp.h"
|
||||
#include "ipv6cp.h"
|
||||
#include "auth.h"
|
||||
#include "pap.h"
|
||||
#include "chap.h"
|
||||
@ -317,10 +320,16 @@ static const struct {
|
||||
u_short proto;
|
||||
struct mbuf *(*fn)(struct bundle *, struct link *, struct mbuf *);
|
||||
} despatcher[] = {
|
||||
{ PROTO_IP, ip_Input },
|
||||
{ PROTO_IP, ipv4_Input },
|
||||
#ifndef NOINET6
|
||||
{ PROTO_IPV6, ipv6_Input },
|
||||
#endif
|
||||
{ PROTO_MP, mp_Input },
|
||||
{ PROTO_LCP, lcp_Input },
|
||||
{ PROTO_IPCP, ipcp_Input },
|
||||
#ifndef NOINET6
|
||||
{ PROTO_IPV6CP, ipv6cp_Input },
|
||||
#endif
|
||||
{ PROTO_PAP, pap_Input },
|
||||
{ PROTO_CHAP, chap_Input },
|
||||
{ PROTO_CCP, ccp_Input },
|
||||
|
@ -42,7 +42,7 @@
|
||||
#include "descriptor.h"
|
||||
#include "prompt.h"
|
||||
|
||||
static const char * const LogNames[] = {
|
||||
static const char *const LogNames[] = {
|
||||
"Async",
|
||||
"CBCP",
|
||||
"CCP",
|
||||
@ -55,6 +55,7 @@ static const char * const LogNames[] = {
|
||||
"HDLC",
|
||||
"ID0",
|
||||
"IPCP",
|
||||
"IPV6CP",
|
||||
"LCP",
|
||||
"LQM",
|
||||
"Phase",
|
||||
|
@ -39,20 +39,21 @@
|
||||
#define LogHDLC (10)
|
||||
#define LogID0 (11)
|
||||
#define LogIPCP (12)
|
||||
#define LogLCP (13)
|
||||
#define LogLQM (14)
|
||||
#define LogPHASE (15)
|
||||
#define LogPHYSICAL (16) /* syslog(LOG_INFO, ....) */
|
||||
#define LogSYNC (17) /* syslog(LOG_INFO, ....) */
|
||||
#define LogTCPIP (18)
|
||||
#define LogTIMER (19) /* syslog(LOG_DEBUG, ....) */
|
||||
#define LogTUN (20) /* If set, tun%d is output with each message */
|
||||
#define LogWARN (21) /* Sent to VarTerm else syslog(LOG_WARNING, ) */
|
||||
#define LogERROR (22) /* syslog(LOG_ERR, ....), + sent to VarTerm */
|
||||
#define LogALERT (23) /* syslog(LOG_ALERT, ....) */
|
||||
#define LogIPV6CP (13)
|
||||
#define LogLCP (14)
|
||||
#define LogLQM (15)
|
||||
#define LogPHASE (16)
|
||||
#define LogPHYSICAL (17) /* syslog(LOG_INFO, ....) */
|
||||
#define LogSYNC (18) /* syslog(LOG_INFO, ....) */
|
||||
#define LogTCPIP (19)
|
||||
#define LogTIMER (20) /* syslog(LOG_DEBUG, ....) */
|
||||
#define LogTUN (21) /* If set, tun%d is output with each message */
|
||||
#define LogWARN (22) /* Sent to VarTerm else syslog(LOG_WARNING, ) */
|
||||
#define LogERROR (23) /* syslog(LOG_ERR, ....), + sent to VarTerm */
|
||||
#define LogALERT (24) /* syslog(LOG_ALERT, ....) */
|
||||
|
||||
#define LogMAXCONF (20)
|
||||
#define LogMAX (23)
|
||||
#define LogMAXCONF (21)
|
||||
#define LogMAX (24)
|
||||
|
||||
struct mbuf;
|
||||
struct cmdargs;
|
||||
|
@ -71,6 +71,8 @@
|
||||
#include "iplist.h"
|
||||
#include "throughput.h"
|
||||
#include "slcompress.h"
|
||||
#include "ncpaddr.h"
|
||||
#include "ip.h"
|
||||
#include "ipcp.h"
|
||||
#include "filter.h"
|
||||
#include "descriptor.h"
|
||||
@ -79,6 +81,8 @@
|
||||
#ifndef NORADIUS
|
||||
#include "radius.h"
|
||||
#endif
|
||||
#include "ipv6cp.h"
|
||||
#include "ncp.h"
|
||||
#include "bundle.h"
|
||||
#include "auth.h"
|
||||
#include "systems.h"
|
||||
@ -413,7 +417,7 @@ main(int argc, char **argv)
|
||||
bundle_SetLabel(bundle, lastlabel);
|
||||
|
||||
if (sw.mode == PHYS_AUTO &&
|
||||
bundle->ncp.ipcp.cfg.peer_range.ipaddr.s_addr == INADDR_ANY) {
|
||||
ncprange_family(&bundle->ncp.ipcp.cfg.peer_range) == AF_UNSPEC) {
|
||||
prompt_Printf(prompt, "You must ``set ifaddr'' with a peer address "
|
||||
"in auto mode.\n");
|
||||
AbortProgram(EX_START);
|
||||
|
@ -87,13 +87,13 @@ static const char *
|
||||
mbuftype(int type)
|
||||
{
|
||||
static const char * const mbufdesc[MB_MAX] = {
|
||||
"ip in", "ip out", "nat in", "nat out", "mp in", "mp out",
|
||||
"vj in", "vj out", "icompd in", "icompd out", "compd in", "compd out",
|
||||
"lqr in", "lqr out", "echo in", "echo out", "proto in", "proto out",
|
||||
"acf in", "acf out", "sync in", "sync out", "hdlc in", "hdlc out",
|
||||
"async in", "async out", "cbcp in", "cbcp out", "chap in", "chap out",
|
||||
"pap in", "pap out", "ccp in", "ccp out", "ipcp in", "ipcp out",
|
||||
"lcp in", "lcp out"
|
||||
"ip in", "ip out", "ipv6 in", "ipv6 out", "nat in", "nat out",
|
||||
"mp in", "mp out", "vj in", "vj out", "icompd in", "icompd out",
|
||||
"compd in", "compd out", "lqr in", "lqr out", "echo in", "echo out",
|
||||
"proto in", "proto out", "acf in", "acf out", "sync in", "sync out",
|
||||
"hdlc in", "hdlc out", "async in", "async out", "cbcp in", "cbcp out",
|
||||
"chap in", "chap out", "pap in", "pap out", "ccp in", "ccp out",
|
||||
"ipcp in", "ipcp out", "ipv6cp in", "ipv6cp out", "lcp in", "lcp out"
|
||||
};
|
||||
|
||||
return type < 0 || type >= MB_MAX ? "unknown" : mbufdesc[type];
|
||||
|
@ -52,43 +52,47 @@ struct mqueue {
|
||||
|
||||
#define MB_IPIN 0
|
||||
#define MB_IPOUT 1
|
||||
#define MB_NATIN 2
|
||||
#define MB_NATOUT 3
|
||||
#define MB_MPIN 4
|
||||
#define MB_MPOUT 5
|
||||
#define MB_VJIN 6
|
||||
#define MB_VJOUT 7
|
||||
#define MB_ICOMPDIN 8
|
||||
#define MB_ICOMPDOUT 9
|
||||
#define MB_COMPDIN 10
|
||||
#define MB_COMPDOUT 11
|
||||
#define MB_LQRIN 12
|
||||
#define MB_LQROUT 13
|
||||
#define MB_ECHOIN 14
|
||||
#define MB_ECHOOUT 15
|
||||
#define MB_PROTOIN 16
|
||||
#define MB_PROTOOUT 17
|
||||
#define MB_ACFIN 18
|
||||
#define MB_ACFOUT 19
|
||||
#define MB_SYNCIN 20
|
||||
#define MB_SYNCOUT 21
|
||||
#define MB_HDLCIN 22
|
||||
#define MB_HDLCOUT 23
|
||||
#define MB_ASYNCIN 24
|
||||
#define MB_ASYNCOUT 25
|
||||
#define MB_CBCPIN 26
|
||||
#define MB_CBCPOUT 27
|
||||
#define MB_CHAPIN 28
|
||||
#define MB_CHAPOUT 29
|
||||
#define MB_PAPIN 30
|
||||
#define MB_PAPOUT 31
|
||||
#define MB_CCPIN 32
|
||||
#define MB_CCPOUT 33
|
||||
#define MB_IPCPIN 34
|
||||
#define MB_IPCPOUT 35
|
||||
#define MB_LCPIN 36
|
||||
#define MB_LCPOUT 37
|
||||
#define MB_UNKNOWN 38
|
||||
#define MB_IPV6IN 2
|
||||
#define MB_IPV6OUT 3
|
||||
#define MB_NATIN 4
|
||||
#define MB_NATOUT 5
|
||||
#define MB_MPIN 6
|
||||
#define MB_MPOUT 7
|
||||
#define MB_VJIN 8
|
||||
#define MB_VJOUT 9
|
||||
#define MB_ICOMPDIN 10
|
||||
#define MB_ICOMPDOUT 11
|
||||
#define MB_COMPDIN 12
|
||||
#define MB_COMPDOUT 13
|
||||
#define MB_LQRIN 14
|
||||
#define MB_LQROUT 15
|
||||
#define MB_ECHOIN 16
|
||||
#define MB_ECHOOUT 17
|
||||
#define MB_PROTOIN 18
|
||||
#define MB_PROTOOUT 19
|
||||
#define MB_ACFIN 20
|
||||
#define MB_ACFOUT 21
|
||||
#define MB_SYNCIN 22
|
||||
#define MB_SYNCOUT 23
|
||||
#define MB_HDLCIN 24
|
||||
#define MB_HDLCOUT 25
|
||||
#define MB_ASYNCIN 26
|
||||
#define MB_ASYNCOUT 27
|
||||
#define MB_CBCPIN 28
|
||||
#define MB_CBCPOUT 29
|
||||
#define MB_CHAPIN 30
|
||||
#define MB_CHAPOUT 31
|
||||
#define MB_PAPIN 32
|
||||
#define MB_PAPOUT 33
|
||||
#define MB_CCPIN 34
|
||||
#define MB_CCPOUT 35
|
||||
#define MB_IPCPIN 36
|
||||
#define MB_IPCPOUT 37
|
||||
#define MB_IPV6CPIN 38
|
||||
#define MB_IPV6CPOUT 39
|
||||
#define MB_LCPIN 40
|
||||
#define MB_LCPOUT 41
|
||||
#define MB_UNKNOWN 42
|
||||
#define MB_MAX MB_UNKNOWN
|
||||
|
||||
#define M_MAXLEN (4352 - sizeof(struct mbuf)) /* > HDLCSIZE */
|
||||
|
@ -61,6 +61,8 @@
|
||||
#include "slcompress.h"
|
||||
#include "lqr.h"
|
||||
#include "hdlc.h"
|
||||
#include "ncpaddr.h"
|
||||
#include "ip.h"
|
||||
#include "ipcp.h"
|
||||
#include "auth.h"
|
||||
#include "lcp.h"
|
||||
@ -79,8 +81,9 @@
|
||||
#ifndef NORADIUS
|
||||
#include "radius.h"
|
||||
#endif
|
||||
#include "ipv6cp.h"
|
||||
#include "ncp.h"
|
||||
#include "bundle.h"
|
||||
#include "ip.h"
|
||||
#include "prompt.h"
|
||||
#include "id.h"
|
||||
#include "arp.h"
|
||||
@ -243,6 +246,7 @@ mp_Init(struct mp *mp, struct bundle *bundle)
|
||||
|
||||
mp->out.seq = 0;
|
||||
mp->out.link = 0;
|
||||
mp->out.af = AF_INET;
|
||||
mp->seq.min_in = 0;
|
||||
mp->seq.next_in = 0;
|
||||
mp->inbufs = NULL;
|
||||
@ -336,6 +340,7 @@ mp_Up(struct mp *mp, struct datalink *dl)
|
||||
|
||||
mp->out.seq = 0;
|
||||
mp->out.link = 0;
|
||||
mp->out.af = AF_INET;
|
||||
mp->seq.min_in = 0;
|
||||
mp->seq.next_in = 0;
|
||||
|
||||
@ -355,8 +360,8 @@ mp_Up(struct mp *mp, struct datalink *dl)
|
||||
log_Printf(LogPHASE, "mp: Listening on %s\n", mp->server.socket.sun_path);
|
||||
log_Printf(LogPHASE, " First link: %s\n", dl->name);
|
||||
|
||||
/* Re-point our IPCP layer at our MP link */
|
||||
ipcp_SetLink(&mp->bundle->ncp.ipcp, &mp->link);
|
||||
/* Re-point our NCP layers at our MP link */
|
||||
ncp_SetLink(&mp->bundle->ncp, &mp->link);
|
||||
|
||||
/* Our lcp's already up 'cos of the NULL parent */
|
||||
if (ccp_SetOpenMode(&mp->link.ccp)) {
|
||||
@ -657,7 +662,7 @@ mp_Output(struct mp *mp, struct bundle *bundle, struct link *l,
|
||||
}
|
||||
|
||||
int
|
||||
mp_FillQueues(struct bundle *bundle)
|
||||
mp_FillPhysicalQueues(struct bundle *bundle)
|
||||
{
|
||||
struct mp *mp = &bundle->ncp.mp;
|
||||
struct datalink *dl, *fdl;
|
||||
@ -665,6 +670,7 @@ mp_FillQueues(struct bundle *bundle)
|
||||
int thislink, nlinks;
|
||||
u_int32_t begin, end;
|
||||
struct mbuf *m, *mo;
|
||||
struct link *bestlink;
|
||||
|
||||
thislink = nlinks = 0;
|
||||
for (fdl = NULL, dl = bundle->links; dl; dl = dl->next) {
|
||||
@ -706,7 +712,7 @@ mp_FillQueues(struct bundle *bundle)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!link_QueueLen(&mp->link)) {
|
||||
if (!mp_QueueLen(mp)) {
|
||||
struct datalink *other;
|
||||
int mrutoosmall;
|
||||
|
||||
@ -714,7 +720,8 @@ mp_FillQueues(struct bundle *bundle)
|
||||
* If there's only a single open link in our bundle and we haven't got
|
||||
* MP level link compression, queue outbound traffic directly via that
|
||||
* link's protocol stack rather than using the MP link. This results
|
||||
* in the outbound traffic going out as PROTO_IP rather than PROTO_MP.
|
||||
* in the outbound traffic going out as PROTO_IP or PROTO_IPV6 rather
|
||||
* than PROTO_MP.
|
||||
*/
|
||||
for (other = dl->next; other; other = other->next)
|
||||
if (other->state == DATALINK_OPEN)
|
||||
@ -734,9 +741,9 @@ mp_FillQueues(struct bundle *bundle)
|
||||
}
|
||||
}
|
||||
|
||||
if (!ip_PushPacket(other ? &mp->link : &dl->physical->link, bundle))
|
||||
/* Nothing else to send */
|
||||
break;
|
||||
bestlink = other ? &mp->link : &dl->physical->link;
|
||||
if (!ncp_PushPacket(&bundle->ncp, &mp->out.af, bestlink))
|
||||
break; /* Nothing else to send */
|
||||
|
||||
if (mrutoosmall)
|
||||
log_Printf(LogDEBUG, "Don't send data as PROTO_IP, MRU < MRRU\n");
|
||||
@ -978,7 +985,7 @@ mp_SetEnddisc(struct cmdargs const *arg)
|
||||
mp->cfg.enddisc.len = strlen(mp->cfg.enddisc.address);
|
||||
} else if (!strcasecmp(arg->argv[arg->argn], "ip")) {
|
||||
if (arg->bundle->ncp.ipcp.my_ip.s_addr == INADDR_ANY)
|
||||
addr = arg->bundle->ncp.ipcp.cfg.my_range.ipaddr;
|
||||
ncprange_getip4addr(&arg->bundle->ncp.ipcp.cfg.my_range, &addr);
|
||||
else
|
||||
addr = arg->bundle->ncp.ipcp.my_ip;
|
||||
memcpy(mp->cfg.enddisc.address, &addr.s_addr, sizeof addr.s_addr);
|
||||
@ -989,7 +996,7 @@ mp_SetEnddisc(struct cmdargs const *arg)
|
||||
int s;
|
||||
|
||||
if (arg->bundle->ncp.ipcp.my_ip.s_addr == INADDR_ANY)
|
||||
addr = arg->bundle->ncp.ipcp.cfg.my_range.ipaddr;
|
||||
ncprange_getip4addr(&arg->bundle->ncp.ipcp.cfg.my_range, &addr);
|
||||
else
|
||||
addr = arg->bundle->ncp.ipcp.my_ip;
|
||||
|
||||
@ -1195,8 +1202,8 @@ mp_LinkLost(struct mp *mp, struct datalink *dl)
|
||||
mp_Assemble(mp, NULL, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
mp_DeleteQueue(struct mp *mp)
|
||||
size_t
|
||||
mp_QueueLen(struct mp *mp)
|
||||
{
|
||||
link_DeleteQueue(&mp->link);
|
||||
return link_QueueLen(&mp->link);
|
||||
}
|
||||
|
@ -84,6 +84,7 @@ struct mp {
|
||||
struct {
|
||||
u_int32_t seq; /* next outgoing seq */
|
||||
int link; /* Next link to send on */
|
||||
int af; /* Next address family to send */
|
||||
} out;
|
||||
|
||||
struct {
|
||||
@ -133,13 +134,13 @@ extern void mp_linkInit(struct mp_link *);
|
||||
extern int mp_Up(struct mp *, struct datalink *);
|
||||
extern void mp_Down(struct mp *);
|
||||
extern struct mbuf *mp_Input(struct bundle *, struct link *, struct mbuf *);
|
||||
extern int mp_FillQueues(struct bundle *);
|
||||
extern int mp_FillPhysicalQueues(struct bundle *);
|
||||
extern int mp_SetDatalinkBandwidth(struct cmdargs const *);
|
||||
extern int mp_ShowStatus(struct cmdargs const *);
|
||||
extern const char *mp_Enddisc(u_char, const char *, int);
|
||||
extern int mp_SetEnddisc(struct cmdargs const *);
|
||||
extern void mp_LinkLost(struct mp *, struct datalink *);
|
||||
extern void mp_DeleteQueue(struct mp *);
|
||||
extern void mp_RestartAutoloadTimer(struct mp *);
|
||||
extern void mp_CheckAutoloadTimer(struct mp *);
|
||||
extern void mp_StopAutoloadTimer(struct mp *);
|
||||
extern size_t mp_QueueLen(struct mp *);
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <stdio.h>
|
||||
@ -63,7 +64,10 @@
|
||||
#include "mbuf.h"
|
||||
#include "lqr.h"
|
||||
#include "hdlc.h"
|
||||
#include "ncpaddr.h"
|
||||
#include "ip.h"
|
||||
#include "ipcp.h"
|
||||
#include "ipv6cp.h"
|
||||
#include "lcp.h"
|
||||
#include "ccp.h"
|
||||
#include "link.h"
|
||||
@ -72,7 +76,7 @@
|
||||
#ifndef NORADIUS
|
||||
#include "radius.h"
|
||||
#endif
|
||||
#include "ip.h"
|
||||
#include "ncp.h"
|
||||
#include "bundle.h"
|
||||
|
||||
|
||||
@ -547,7 +551,8 @@ nat_LayerPull(struct bundle *bundle, struct link *l, struct mbuf *bp,
|
||||
bp = NULL;
|
||||
} else if (log_IsKept(LogTCPIP)) {
|
||||
log_Printf(LogTCPIP, "NAT engine ignored data:\n");
|
||||
PacketCheck(bundle, MBUF_CTOP(bp), bp->m_len, NULL, NULL, NULL);
|
||||
PacketCheck(bundle, AF_INET, MBUF_CTOP(bp), bp->m_len, NULL,
|
||||
NULL, NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
|
550
usr.sbin/ppp/ncp.c
Normal file
550
usr.sbin/ppp/ncp.c
Normal file
@ -0,0 +1,550 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Brian Somers <brian@Awfulhak.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
#include <net/route.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <resolv.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "layer.h"
|
||||
#include "ua.h"
|
||||
#include "defs.h"
|
||||
#include "command.h"
|
||||
#include "mbuf.h"
|
||||
#include "log.h"
|
||||
#include "timer.h"
|
||||
#include "fsm.h"
|
||||
#include "proto.h"
|
||||
#include "iplist.h"
|
||||
#include "throughput.h"
|
||||
#include "slcompress.h"
|
||||
#include "lqr.h"
|
||||
#include "hdlc.h"
|
||||
#include "lcp.h"
|
||||
#include "ncpaddr.h"
|
||||
#include "ip.h"
|
||||
#include "ipcp.h"
|
||||
#include "filter.h"
|
||||
#include "descriptor.h"
|
||||
#include "vjcomp.h"
|
||||
#include "async.h"
|
||||
#include "ccp.h"
|
||||
#include "link.h"
|
||||
#include "physical.h"
|
||||
#include "mp.h"
|
||||
#ifndef NORADIUS
|
||||
#include "radius.h"
|
||||
#endif
|
||||
#include "ipv6cp.h"
|
||||
#include "ncp.h"
|
||||
#include "bundle.h"
|
||||
#include "id.h"
|
||||
#include "arp.h"
|
||||
#include "systems.h"
|
||||
#include "prompt.h"
|
||||
#include "route.h"
|
||||
#include "iface.h"
|
||||
#include "chat.h"
|
||||
#include "auth.h"
|
||||
#include "chap.h"
|
||||
#include "pap.h"
|
||||
#include "cbcp.h"
|
||||
#include "datalink.h"
|
||||
|
||||
|
||||
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])
|
||||
|
||||
void
|
||||
ncp_Init(struct ncp *ncp, struct bundle *bundle)
|
||||
{
|
||||
ncp->afq = AF_INET;
|
||||
ncp->route = NULL;
|
||||
|
||||
ncp->cfg.urgent.tcp.nports = ncp->cfg.urgent.tcp.maxports = NDEFTCPPORTS;
|
||||
ncp->cfg.urgent.tcp.port = (u_short *)malloc(NDEFTCPPORTS * sizeof(u_short));
|
||||
memcpy(ncp->cfg.urgent.tcp.port, default_urgent_tcp_ports,
|
||||
NDEFTCPPORTS * sizeof(u_short));
|
||||
ncp->cfg.urgent.tos = 1;
|
||||
|
||||
ncp->cfg.urgent.udp.nports = ncp->cfg.urgent.udp.maxports = NDEFUDPPORTS;
|
||||
ncp->cfg.urgent.udp.port = (u_short *)malloc(NDEFUDPPORTS * sizeof(u_short));
|
||||
memcpy(ncp->cfg.urgent.udp.port, default_urgent_udp_ports,
|
||||
NDEFUDPPORTS * sizeof(u_short));
|
||||
|
||||
|
||||
mp_Init(&ncp->mp, bundle);
|
||||
|
||||
/* Send over the first physical link by default */
|
||||
ipcp_Init(&ncp->ipcp, bundle, &bundle->links->physical->link,
|
||||
&bundle->fsm);
|
||||
#ifndef NOINET6
|
||||
ipv6cp_Init(&ncp->ipv6cp, bundle, &bundle->links->physical->link,
|
||||
&bundle->fsm);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
ncp_Destroy(struct ncp *ncp)
|
||||
{
|
||||
ipcp_Destroy(&ncp->ipcp);
|
||||
#ifndef NOINET6
|
||||
ipv6cp_Destroy(&ncp->ipv6cp);
|
||||
#endif
|
||||
|
||||
if (ncp->cfg.urgent.tcp.maxports) {
|
||||
ncp->cfg.urgent.tcp.nports = ncp->cfg.urgent.tcp.maxports = 0;
|
||||
free(ncp->cfg.urgent.tcp.port);
|
||||
ncp->cfg.urgent.tcp.port = NULL;
|
||||
}
|
||||
if (ncp->cfg.urgent.udp.maxports) {
|
||||
ncp->cfg.urgent.udp.nports = ncp->cfg.urgent.udp.maxports = 0;
|
||||
free(ncp->cfg.urgent.udp.port);
|
||||
ncp->cfg.urgent.udp.port = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ncp_fsmStart(struct ncp *ncp, struct bundle *bundle)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
#ifndef NOINET6
|
||||
if (Enabled(bundle, OPT_IPCP)) {
|
||||
#endif
|
||||
fsm_Up(&ncp->ipcp.fsm);
|
||||
fsm_Open(&ncp->ipcp.fsm);
|
||||
res++;
|
||||
#ifndef NOINET6
|
||||
}
|
||||
|
||||
if (Enabled(bundle, OPT_IPV6CP)) {
|
||||
fsm_Up(&ncp->ipv6cp.fsm);
|
||||
fsm_Open(&ncp->ipv6cp.fsm);
|
||||
res++;
|
||||
}
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
ncp_IfaceAddrAdded(struct ncp *ncp, const struct iface_addr *addr)
|
||||
{
|
||||
switch (ncprange_family(&addr->ifa)) {
|
||||
case AF_INET:
|
||||
ipcp_IfaceAddrAdded(&ncp->ipcp, addr);
|
||||
break;
|
||||
#ifndef NOINET6
|
||||
case AF_INET6:
|
||||
ipv6cp_IfaceAddrAdded(&ncp->ipv6cp, addr);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ncp_IfaceAddrDeleted(struct ncp *ncp, const struct iface_addr *addr)
|
||||
{
|
||||
if (ncprange_family(&addr->ifa) == AF_INET)
|
||||
ipcp_IfaceAddrDeleted(&ncp->ipcp, addr);
|
||||
}
|
||||
|
||||
void
|
||||
ncp_SetLink(struct ncp *ncp, struct link *l)
|
||||
{
|
||||
ipcp_SetLink(&ncp->ipcp, l);
|
||||
#ifndef NOINET6
|
||||
ipv6cp_SetLink(&ncp->ipv6cp, l);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Enqueue a packet of the given address family. Nothing will make it
|
||||
* down to the physical link level 'till ncp_FillPhysicalQueues() is used.
|
||||
*/
|
||||
void
|
||||
ncp_Enqueue(struct ncp *ncp, int af, int pri, char *ptr, int count)
|
||||
{
|
||||
#ifndef NOINET6
|
||||
struct ipv6cp *ipv6cp = &ncp->ipv6cp;
|
||||
#endif
|
||||
struct ipcp *ipcp = &ncp->ipcp;
|
||||
struct mbuf *bp;
|
||||
|
||||
/*
|
||||
* We allocate an extra 6 bytes, four at the front and two at the end.
|
||||
* This is an optimisation so that we need to do less work in
|
||||
* m_prepend() in acf_LayerPush() and proto_LayerPush() and
|
||||
* appending in hdlc_LayerPush().
|
||||
*/
|
||||
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
if (pri < 0 || pri >= IPCP_QUEUES(ipcp)) {
|
||||
log_Printf(LogERROR, "Can't store in ip queue %d\n", pri);
|
||||
break;
|
||||
}
|
||||
|
||||
bp = m_get(count + 6, MB_IPOUT);
|
||||
bp->m_offset += 4;
|
||||
bp->m_len -= 6;
|
||||
memcpy(MBUF_CTOP(bp), ptr, count);
|
||||
m_enqueue(ipcp->Queue + pri, bp);
|
||||
break;
|
||||
|
||||
#ifndef NOINET6
|
||||
case AF_INET6:
|
||||
if (pri < 0 || pri >= IPV6CP_QUEUES(ipcp)) {
|
||||
log_Printf(LogERROR, "Can't store in ipv6 queue %d\n", pri);
|
||||
break;
|
||||
}
|
||||
|
||||
bp = m_get(count + 6, MB_IPOUT);
|
||||
bp->m_offset += 4;
|
||||
bp->m_len -= 6;
|
||||
memcpy(MBUF_CTOP(bp), ptr, count);
|
||||
m_enqueue(ipv6cp->Queue + pri, bp);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
log_Printf(LogERROR, "Can't enqueue protocol family %d\n", af);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* How many packets are queued to go out ?
|
||||
*/
|
||||
size_t
|
||||
ncp_QueueLen(struct ncp *ncp)
|
||||
{
|
||||
size_t result;
|
||||
|
||||
result = ipcp_QueueLen(&ncp->ipcp);
|
||||
#ifndef NOINET6
|
||||
result += ipv6cp_QueueLen(&ncp->ipv6cp);
|
||||
#endif
|
||||
result += mp_QueueLen(&ncp->mp); /* Usually empty */
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ditch all queued packets. This is usually done after our choked timer
|
||||
* has fired - which happens because we couldn't send any traffic over
|
||||
* any links for some time.
|
||||
*/
|
||||
void
|
||||
ncp_DeleteQueues(struct ncp *ncp)
|
||||
{
|
||||
#ifndef NOINET6
|
||||
struct ipv6cp *ipv6cp = &ncp->ipv6cp;
|
||||
#endif
|
||||
struct ipcp *ipcp = &ncp->ipcp;
|
||||
struct mp *mp = &ncp->mp;
|
||||
struct mqueue *q;
|
||||
|
||||
for (q = ipcp->Queue; q < ipcp->Queue + IPCP_QUEUES(ipcp); q++)
|
||||
while (q->top)
|
||||
m_freem(m_dequeue(q));
|
||||
|
||||
#ifndef NOINET6
|
||||
for (q = ipv6cp->Queue; q < ipv6cp->Queue + IPV6CP_QUEUES(ipv6cp); q++)
|
||||
while (q->top)
|
||||
m_freem(m_dequeue(q));
|
||||
#endif
|
||||
|
||||
link_DeleteQueue(&mp->link); /* Usually empty anyway */
|
||||
}
|
||||
|
||||
/*
|
||||
* Arrange that each of our links has at least one packet. We keep the
|
||||
* number of packets queued at the link level to a minimum so that the
|
||||
* loss of a link in multi-link mode results in the minimum number of
|
||||
* dropped packets.
|
||||
*/
|
||||
size_t
|
||||
ncp_FillPhysicalQueues(struct ncp *ncp, struct bundle *bundle)
|
||||
{
|
||||
size_t total;
|
||||
|
||||
if (bundle->ncp.mp.active)
|
||||
total = mp_FillPhysicalQueues(bundle);
|
||||
else {
|
||||
struct datalink *dl;
|
||||
size_t add;
|
||||
|
||||
for (total = 0, dl = bundle->links; dl; dl = dl->next)
|
||||
if (dl->state == DATALINK_OPEN) {
|
||||
add = link_QueueLen(&dl->physical->link);
|
||||
if (add == 0 && dl->physical->out == NULL)
|
||||
add = ncp_PushPacket(ncp, &ncp->afq, &dl->physical->link);
|
||||
total += add;
|
||||
}
|
||||
}
|
||||
|
||||
return total + ncp_QueueLen(&bundle->ncp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Push a packet into the given link. ``af'' is used as a persistent record
|
||||
* of what is to be pushed next, coming either from mp->out or ncp->afq.
|
||||
*/
|
||||
int
|
||||
ncp_PushPacket(struct ncp *ncp, int *af, struct link *l)
|
||||
{
|
||||
struct bundle *bundle = l->lcp.fsm.bundle;
|
||||
int res;
|
||||
|
||||
#ifndef NOINET6
|
||||
if (*af == AF_INET) {
|
||||
if ((res = ipcp_PushPacket(&bundle->ncp.ipcp, l)))
|
||||
*af = AF_INET6;
|
||||
else
|
||||
res = ipv6cp_PushPacket(&bundle->ncp.ipv6cp, l);
|
||||
} else {
|
||||
if ((res = ipv6cp_PushPacket(&bundle->ncp.ipv6cp, l)))
|
||||
*af = AF_INET;
|
||||
else
|
||||
res = ipcp_PushPacket(&bundle->ncp.ipcp, l);
|
||||
}
|
||||
#else
|
||||
res = ipcp_PushPacket(&bundle->ncp.ipcp, l);
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
ncp_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
|
||||
ncp_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, "ncp_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
|
||||
ncp_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
|
||||
ncp_ClearUrgentPorts(struct port_range *range)
|
||||
{
|
||||
range->nports = 0;
|
||||
}
|
||||
|
||||
int
|
||||
ncp_Show(struct cmdargs const *arg)
|
||||
{
|
||||
struct ncp *ncp = &arg->bundle->ncp;
|
||||
int p;
|
||||
|
||||
#ifndef NOINET6
|
||||
prompt_Printf(arg->prompt, "Next queued AF: %s\n",
|
||||
ncp->afq == AF_INET6 ? "inet6" : "inet");
|
||||
#endif
|
||||
|
||||
if (ncp->route) {
|
||||
prompt_Printf(arg->prompt, "\n");
|
||||
route_ShowSticky(arg->prompt, ncp->route, "Sticky routes", 1);
|
||||
}
|
||||
|
||||
prompt_Printf(arg->prompt, "\nDefaults:\n");
|
||||
prompt_Printf(arg->prompt, " sendpipe: ");
|
||||
if (ncp->cfg.sendpipe > 0)
|
||||
prompt_Printf(arg->prompt, "%-20ld\n", ncp->cfg.sendpipe);
|
||||
else
|
||||
prompt_Printf(arg->prompt, "unspecified\n");
|
||||
prompt_Printf(arg->prompt, " recvpipe: ");
|
||||
if (ncp->cfg.recvpipe > 0)
|
||||
prompt_Printf(arg->prompt, "%ld\n", ncp->cfg.recvpipe);
|
||||
else
|
||||
prompt_Printf(arg->prompt, "unspecified\n");
|
||||
|
||||
prompt_Printf(arg->prompt, "\n Urgent ports\n");
|
||||
prompt_Printf(arg->prompt, " TCP: ");
|
||||
if (ncp->cfg.urgent.tcp.nports == 0)
|
||||
prompt_Printf(arg->prompt, "none");
|
||||
else
|
||||
for (p = 0; p < ncp->cfg.urgent.tcp.nports; p++) {
|
||||
if (p)
|
||||
prompt_Printf(arg->prompt, ", ");
|
||||
prompt_Printf(arg->prompt, "%u", ncp->cfg.urgent.tcp.port[p]);
|
||||
}
|
||||
|
||||
prompt_Printf(arg->prompt, "\n UDP: ");
|
||||
if (ncp->cfg.urgent.udp.nports == 0)
|
||||
prompt_Printf(arg->prompt, "none");
|
||||
else
|
||||
for (p = 0; p < ncp->cfg.urgent.udp.nports; p++) {
|
||||
if (p)
|
||||
prompt_Printf(arg->prompt, ", ");
|
||||
prompt_Printf(arg->prompt, "%u", ncp->cfg.urgent.udp.port[p]);
|
||||
}
|
||||
prompt_Printf(arg->prompt, "\n TOS: %s\n\n",
|
||||
ncp->cfg.urgent.tos ? "yes" : "no");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ncp_LayersOpen(struct ncp *ncp)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = !!(ncp->ipcp.fsm.state == ST_OPENED);
|
||||
#ifndef NOINET6
|
||||
n += !!(ncp->ipv6cp.fsm.state == ST_OPENED);
|
||||
#endif
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int
|
||||
ncp_LayersUnfinished(struct ncp *ncp)
|
||||
{
|
||||
int n = 0;
|
||||
|
||||
if (ncp->ipcp.fsm.state > ST_CLOSED ||
|
||||
ncp->ipcp.fsm.state == ST_STARTING)
|
||||
n++;
|
||||
|
||||
#ifndef NOINET6
|
||||
if (ncp->ipv6cp.fsm.state > ST_CLOSED ||
|
||||
ncp->ipv6cp.fsm.state == ST_STARTING)
|
||||
n++;
|
||||
#endif
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
void
|
||||
ncp_Close(struct ncp *ncp)
|
||||
{
|
||||
if (ncp->ipcp.fsm.state > ST_CLOSED ||
|
||||
ncp->ipcp.fsm.state == ST_STARTING)
|
||||
fsm_Close(&ncp->ipcp.fsm);
|
||||
|
||||
#ifndef NOINET6
|
||||
if (ncp->ipv6cp.fsm.state > ST_CLOSED ||
|
||||
ncp->ipv6cp.fsm.state == ST_STARTING)
|
||||
fsm_Close(&ncp->ipv6cp.fsm);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
ncp2initial(struct ncp *ncp)
|
||||
{
|
||||
fsm2initial(&ncp->ipcp.fsm);
|
||||
#ifndef NOINET6
|
||||
fsm2initial(&ncp->ipv6cp.fsm);
|
||||
#endif
|
||||
}
|
101
usr.sbin/ppp/ncp.h
Normal file
101
usr.sbin/ppp/ncp.h
Normal file
@ -0,0 +1,101 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Brian Somers <brian@Awfulhak.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
struct port_range {
|
||||
unsigned nports; /* How many ports */
|
||||
unsigned maxports; /* How many allocated (malloc) ports */
|
||||
u_short *port; /* The actual ports */
|
||||
};
|
||||
|
||||
struct ncp {
|
||||
struct {
|
||||
u_long sendpipe; /* route sendpipe size */
|
||||
u_long recvpipe; /* route recvpipe size */
|
||||
|
||||
struct {
|
||||
struct port_range tcp, udp; /* The range of urgent ports */
|
||||
unsigned tos : 1; /* Urgent IPTOS_LOWDELAY packets ? */
|
||||
} urgent;
|
||||
} cfg;
|
||||
|
||||
int afq; /* Next address family to queue */
|
||||
|
||||
struct sticky_route *route; /* List of dynamic routes */
|
||||
|
||||
struct ipcp ipcp; /* Our IPCP FSM */
|
||||
#ifndef NOINET6
|
||||
struct ipv6cp ipv6cp; /* Our IPV6CP FSM */
|
||||
#endif
|
||||
struct mp mp; /* Our MP */
|
||||
};
|
||||
|
||||
extern void ncp_Init(struct ncp *, struct bundle *);
|
||||
extern void ncp_Destroy(struct ncp *);
|
||||
extern int ncp_fsmStart(struct ncp *, struct bundle *);
|
||||
extern void ncp_IfaceAddrAdded(struct ncp *, const struct iface_addr *);
|
||||
extern void ncp_IfaceAddrDeleted(struct ncp *, const struct iface_addr *);
|
||||
extern void ncp_SetLink(struct ncp *, struct link *);
|
||||
extern void ncp_Enqueue(struct ncp *, int, int, char *, int);
|
||||
extern void ncp_DeleteQueues(struct ncp *);
|
||||
extern size_t ncp_QueueLen(struct ncp *);
|
||||
extern size_t ncp_FillPhysicalQueues(struct ncp *, struct bundle *);
|
||||
extern int ncp_PushPacket(struct ncp *, int *, struct link *);
|
||||
extern int ncp_IsUrgentPort(struct port_range *, u_short, u_short);
|
||||
extern void ncp_AddUrgentPort(struct port_range *, u_short);
|
||||
extern void ncp_RemoveUrgentPort(struct port_range *, u_short);
|
||||
extern void ncp_ClearUrgentPorts(struct port_range *);
|
||||
extern int ncp_Show(struct cmdargs const *);
|
||||
extern int ncp_LayersOpen(struct ncp *);
|
||||
extern int ncp_LayersUnfinished(struct ncp *);
|
||||
extern void ncp_Close(struct ncp *);
|
||||
extern void ncp2initial(struct ncp *);
|
||||
|
||||
#define ncp_IsUrgentTcpPort(ncp, p1, p2) \
|
||||
ncp_IsUrgentPort(&(ncp)->cfg.urgent.tcp, p1, p2)
|
||||
#define ncp_IsUrgentUdpPort(ncp, p1, p2) \
|
||||
ncp_IsUrgentPort(&(ncp)->cfg.urgent.udp, p1, p2)
|
||||
#define ncp_AddUrgentTcpPort(ncp, p) \
|
||||
ncp_AddUrgentPort(&(ncp)->cfg.urgent.tcp, p)
|
||||
#define ncp_AddUrgentUdpPort(ncp, p) \
|
||||
ncp_AddUrgentPort(&(ncp)->cfg.urgent.udp, p)
|
||||
#define ncp_RemoveUrgentTcpPort(ncp, p) \
|
||||
ncp_RemoveUrgentPort(&(ncp)->cfg.urgent.tcp, p)
|
||||
#define ncp_RemoveUrgentUdpPort(ncp, p) \
|
||||
ncp_RemoveUrgentPort(&(ncp)->cfg.urgent.udp, p)
|
||||
#define ncp_ClearUrgentTcpPorts(ncp) \
|
||||
ncp_ClearUrgentPorts(&(ncp)->cfg.urgent.tcp)
|
||||
#define ncp_ClearUrgentUdpPorts(ncp) \
|
||||
ncp_ClearUrgentPorts(&(ncp)->cfg.urgent.udp)
|
||||
#define ncp_ClearUrgentTOS(ncp) (ncp)->cfg.urgent.tos = 0;
|
||||
#define ncp_SetUrgentTOS(ncp) (ncp)->cfg.urgent.tos = 1;
|
||||
|
||||
#ifndef NOINET6
|
||||
#define isncp(proto) ((proto) == PROTO_IPCP || (proto) == PROTO_IPV6CP)
|
||||
#else
|
||||
#define isncp(proto) ((proto) == PROTO_IPCP)
|
||||
#endif
|
967
usr.sbin/ppp/ncpaddr.c
Normal file
967
usr.sbin/ppp/ncpaddr.c
Normal file
@ -0,0 +1,967 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Brian Somers <brian@Awfulhak.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "ncpaddr.h"
|
||||
#include "timer.h"
|
||||
#include "fsm.h"
|
||||
#include "defs.h"
|
||||
#include "slcompress.h"
|
||||
#include "iplist.h"
|
||||
#include "throughput.h"
|
||||
#include "mbuf.h"
|
||||
#include "ip.h"
|
||||
#include "ipcp.h"
|
||||
#include "filter.h"
|
||||
#include "descriptor.h"
|
||||
#include "route.h"
|
||||
#include "layer.h"
|
||||
#include "lqr.h"
|
||||
#include "hdlc.h"
|
||||
#include "lcp.h"
|
||||
#include "ccp.h"
|
||||
#include "link.h"
|
||||
#include "mp.h"
|
||||
#ifndef NORADIUS
|
||||
#include "radius.h"
|
||||
#endif
|
||||
#include "ipv6cp.h"
|
||||
#include "ncp.h"
|
||||
#include "bundle.h"
|
||||
|
||||
|
||||
#define ncprange_ip4addr u.ip4.ipaddr
|
||||
#define ncprange_ip4mask u.ip4.mask
|
||||
#define ncprange_ip4width u.ip4.width
|
||||
#define ncpaddr_ip4addr u.ip4addr
|
||||
#ifndef NOINET6
|
||||
#define ncprange_ip6addr u.ip6.ipaddr
|
||||
#define ncprange_ip6width u.ip6.width
|
||||
#define ncpaddr_ip6addr u.ip6addr
|
||||
#endif
|
||||
|
||||
#define NCP_ASCIIBUFFERSIZE 52
|
||||
|
||||
static struct in_addr
|
||||
bits2mask4(int bits)
|
||||
{
|
||||
struct in_addr result;
|
||||
u_int32_t bit = 0x80000000;
|
||||
|
||||
result.s_addr = 0;
|
||||
|
||||
while (bits) {
|
||||
result.s_addr |= bit;
|
||||
bit >>= 1;
|
||||
bits--;
|
||||
}
|
||||
|
||||
result.s_addr = htonl(result.s_addr);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
mask42bits(struct in_addr mask)
|
||||
{
|
||||
u_int32_t msk = ntohl(mask.s_addr);
|
||||
u_int32_t tst;
|
||||
int ret;
|
||||
|
||||
for (ret = 32, tst = 1; tst; ret--, tst <<= 1)
|
||||
if (msk & tst)
|
||||
break;
|
||||
|
||||
for (tst <<= 1; tst; tst <<= 1)
|
||||
if (!(msk & tst))
|
||||
break;
|
||||
|
||||
return tst ? -1 : ret;
|
||||
}
|
||||
|
||||
#ifndef NOINET6
|
||||
static struct in6_addr
|
||||
bits2mask6(int bits)
|
||||
{
|
||||
struct in6_addr result;
|
||||
u_int32_t bit = 0x80;
|
||||
u_char *c = result.s6_addr;
|
||||
|
||||
memset(&result, '\0', sizeof result);
|
||||
|
||||
while (bits) {
|
||||
if (bit == 0) {
|
||||
bit = 0x80;
|
||||
c++;
|
||||
}
|
||||
*c |= bit;
|
||||
bit >>= 1;
|
||||
bits--;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
mask62bits(const struct in6_addr *mask)
|
||||
{
|
||||
const u_char masks[] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe };
|
||||
const u_char *c, *p, *end;
|
||||
int masklen;
|
||||
|
||||
p = (const u_char *)mask;
|
||||
for (masklen = 0, end = p + 16; p < end && *p == 0xff; p++)
|
||||
masklen += 8;
|
||||
|
||||
if (p < end) {
|
||||
for (c = masks; c < masks + sizeof masks; c++)
|
||||
if (*c == *p) {
|
||||
masklen += c - masks;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return masklen;
|
||||
}
|
||||
|
||||
static void
|
||||
adjust_linklocal(struct sockaddr_in6 *sin6)
|
||||
{
|
||||
/* XXX: ?????!?!?!!!!! This is horrible ! */
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) ||
|
||||
IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr)) {
|
||||
sin6->sin6_scope_id =
|
||||
ntohs(*(u_short *)&sin6->sin6_addr.s6_addr[2]);
|
||||
*(u_short *)&sin6->sin6_addr.s6_addr[2] = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
ncpaddr_init(struct ncpaddr *addr)
|
||||
{
|
||||
addr->ncpaddr_family = AF_UNSPEC;
|
||||
}
|
||||
|
||||
int
|
||||
ncpaddr_isdefault(const struct ncpaddr *addr)
|
||||
{
|
||||
switch (addr->ncpaddr_family) {
|
||||
case AF_INET:
|
||||
if (addr->ncpaddr_ip4addr.s_addr == INADDR_ANY)
|
||||
return 1;
|
||||
break;
|
||||
|
||||
#ifndef NOINET6
|
||||
case AF_INET6:
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&addr->ncpaddr_ip6addr))
|
||||
return 1;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ncpaddr_equal(const struct ncpaddr *addr, const struct ncpaddr *cmp)
|
||||
{
|
||||
if (addr->ncpaddr_family != cmp->ncpaddr_family)
|
||||
return 0;
|
||||
|
||||
switch (addr->ncpaddr_family) {
|
||||
case AF_INET:
|
||||
return addr->ncpaddr_ip4addr.s_addr == cmp->ncpaddr_ip4addr.s_addr;
|
||||
|
||||
#ifndef NOINET6
|
||||
case AF_INET6:
|
||||
return !memcmp(&addr->ncpaddr_ip6addr, &cmp->ncpaddr_ip6addr,
|
||||
sizeof addr->ncpaddr_ip6addr);
|
||||
#endif
|
||||
|
||||
case AF_UNSPEC:
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ncpaddr_copy(struct ncpaddr *addr, const struct ncpaddr *from)
|
||||
{
|
||||
switch (from->ncpaddr_family) {
|
||||
case AF_INET:
|
||||
addr->ncpaddr_family = AF_INET;
|
||||
addr->ncpaddr_ip4addr = from->ncpaddr_ip4addr;
|
||||
break;
|
||||
#ifndef NOINET6
|
||||
case AF_INET6:
|
||||
addr->ncpaddr_family = AF_INET6;
|
||||
addr->ncpaddr_ip6addr = from->ncpaddr_ip6addr;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
addr->ncpaddr_family = AF_UNSPEC;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ncpaddr_setip4addr(struct ncpaddr *addr, u_int32_t ip)
|
||||
{
|
||||
addr->ncpaddr_family = AF_INET;
|
||||
addr->ncpaddr_ip4addr.s_addr = ip;
|
||||
}
|
||||
|
||||
int
|
||||
ncpaddr_getip4addr(const struct ncpaddr *addr, u_int32_t *ip)
|
||||
{
|
||||
if (addr->ncpaddr_family != AF_INET)
|
||||
return 0;
|
||||
*ip = addr->ncpaddr_ip4addr.s_addr;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
ncpaddr_setip4(struct ncpaddr *addr, struct in_addr ip)
|
||||
{
|
||||
addr->ncpaddr_family = AF_INET;
|
||||
addr->ncpaddr_ip4addr = ip;
|
||||
}
|
||||
|
||||
int
|
||||
ncpaddr_getip4(const struct ncpaddr *addr, struct in_addr *ip)
|
||||
{
|
||||
if (addr->ncpaddr_family != AF_INET)
|
||||
return 0;
|
||||
*ip = addr->ncpaddr_ip4addr;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef NOINET6
|
||||
void
|
||||
ncpaddr_setip6(struct ncpaddr *addr, const struct in6_addr *ip6)
|
||||
{
|
||||
addr->ncpaddr_family = AF_INET6;
|
||||
addr->ncpaddr_ip6addr = *ip6;
|
||||
}
|
||||
|
||||
int
|
||||
ncpaddr_getip6(const struct ncpaddr *addr, struct in6_addr *ip6)
|
||||
{
|
||||
if (addr->ncpaddr_family != AF_INET6)
|
||||
return 0;
|
||||
*ip6 = addr->ncpaddr_ip6addr;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
ncpaddr_getsa(const struct ncpaddr *addr, struct sockaddr_storage *host)
|
||||
{
|
||||
struct sockaddr_in *host4 = (struct sockaddr_in *)host;
|
||||
#ifndef NOINET6
|
||||
struct sockaddr_in6 *host6 = (struct sockaddr_in6 *)host;
|
||||
#endif
|
||||
|
||||
memset(host, '\0', sizeof(*host));
|
||||
|
||||
switch (addr->ncpaddr_family) {
|
||||
case AF_INET:
|
||||
host4->sin_family = AF_INET;
|
||||
host4->sin_len = sizeof(*host4);
|
||||
host4->sin_addr = addr->ncpaddr_ip4addr;
|
||||
break;
|
||||
|
||||
#ifndef NOINET6
|
||||
case AF_INET6:
|
||||
host6->sin6_family = AF_INET6;
|
||||
host6->sin6_len = sizeof(*host6);
|
||||
host6->sin6_addr = addr->ncpaddr_ip6addr;
|
||||
adjust_linklocal(host6);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
host->ss_family = AF_UNSPEC;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ncpaddr_setsa(struct ncpaddr *addr, const struct sockaddr *host)
|
||||
{
|
||||
const struct sockaddr_in *host4 = (const struct sockaddr_in *)host;
|
||||
#ifndef NOINET6
|
||||
const struct sockaddr_in6 *host6 = (const struct sockaddr_in6 *)host;
|
||||
#endif
|
||||
|
||||
switch (host->sa_family) {
|
||||
case AF_INET:
|
||||
addr->ncpaddr_family = AF_INET;
|
||||
addr->ncpaddr_ip4addr = host4->sin_addr;
|
||||
break;
|
||||
|
||||
#ifndef NOINET6
|
||||
case AF_INET6:
|
||||
if (IN6_IS_ADDR_V4MAPPED(&host6->sin6_addr)) {
|
||||
addr->ncpaddr_family = AF_INET;
|
||||
addr->ncpaddr_ip4addr.s_addr =
|
||||
*(const u_int32_t *)(host6->sin6_addr.s6_addr + 12);
|
||||
} else {
|
||||
addr->ncpaddr_family = AF_INET6;
|
||||
addr->ncpaddr_ip6addr = host6->sin6_addr;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
addr->ncpaddr_family = AF_UNSPEC;
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
ncpaddr_ntowa(const struct ncpaddr *addr)
|
||||
{
|
||||
static char res[NCP_ASCIIBUFFERSIZE];
|
||||
#ifndef NOINET6
|
||||
struct sockaddr_in6 sin6;
|
||||
#endif
|
||||
|
||||
switch (addr->ncpaddr_family) {
|
||||
case AF_INET:
|
||||
snprintf(res, sizeof res, "%s", inet_ntoa(addr->ncpaddr_ip4addr));
|
||||
return res;
|
||||
|
||||
#ifndef NOINET6
|
||||
case AF_INET6:
|
||||
memset(&sin6, '\0', sizeof(sin6));
|
||||
sin6.sin6_len = sizeof(sin6);
|
||||
sin6.sin6_family = AF_INET6;
|
||||
sin6.sin6_addr = addr->ncpaddr_ip6addr;
|
||||
adjust_linklocal(&sin6);
|
||||
if (getnameinfo((struct sockaddr *)&sin6, sizeof sin6, res, sizeof(res),
|
||||
NULL, 0, NI_WITHSCOPEID | NI_NUMERICHOST) != 0)
|
||||
break;
|
||||
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
snprintf(res, sizeof res, "<AF_UNSPEC>");
|
||||
return res;
|
||||
}
|
||||
|
||||
const char *
|
||||
ncpaddr_ntoa(const struct ncpaddr *addr)
|
||||
{
|
||||
return ncpaddr_ntowa(addr);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ncpaddr_aton(struct ncpaddr *addr, struct ncp *ncp, const char *data)
|
||||
{
|
||||
struct ncprange range;
|
||||
|
||||
if (!ncprange_aton(&range, ncp, data))
|
||||
return 0;
|
||||
|
||||
if (range.ncprange_family == AF_INET && range.ncprange_ip4width != 32) {
|
||||
log_Printf(LogWARN, "ncpaddr_aton: %s: Only 32 bits allowed\n", data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef NOINET6
|
||||
if (range.ncprange_family == AF_INET6 && range.ncprange_ip6width != 128) {
|
||||
log_Printf(LogWARN, "ncpaddr_aton: %s: Only 128 bits allowed\n", data);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (range.ncprange_family) {
|
||||
case AF_INET:
|
||||
addr->ncpaddr_family = range.ncprange_family;
|
||||
addr->ncpaddr_ip4addr = range.ncprange_ip4addr;
|
||||
return 1;
|
||||
|
||||
#ifndef NOINET6
|
||||
case AF_INET6:
|
||||
addr->ncpaddr_family = range.ncprange_family;
|
||||
addr->ncpaddr_ip6addr = range.ncprange_ip6addr;
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ncprange_init(struct ncprange *range)
|
||||
{
|
||||
range->ncprange_family = AF_UNSPEC;
|
||||
}
|
||||
|
||||
int
|
||||
ncprange_isset(const struct ncprange *range)
|
||||
{
|
||||
return range->ncprange_family != AF_UNSPEC;
|
||||
}
|
||||
|
||||
int
|
||||
ncprange_equal(const struct ncprange *range, const struct ncprange *cmp)
|
||||
{
|
||||
if (range->ncprange_family != cmp->ncprange_family)
|
||||
return 0;
|
||||
|
||||
switch (range->ncprange_family) {
|
||||
case AF_INET:
|
||||
if (range->ncprange_ip4addr.s_addr != cmp->ncprange_ip4addr.s_addr)
|
||||
return 0;
|
||||
return range->ncprange_ip4mask.s_addr == cmp->ncprange_ip4mask.s_addr;
|
||||
|
||||
#ifndef NOINET6
|
||||
case AF_INET6:
|
||||
if (range->ncprange_ip6width != cmp->ncprange_ip6width)
|
||||
return 0;
|
||||
return !memcmp(&range->ncprange_ip6addr, &cmp->ncprange_ip6addr,
|
||||
sizeof range->ncprange_ip6addr);
|
||||
#endif
|
||||
|
||||
case AF_UNSPEC:
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ncprange_isdefault(const struct ncprange *range)
|
||||
{
|
||||
switch (range->ncprange_family) {
|
||||
case AF_INET:
|
||||
if (range->ncprange_ip4addr.s_addr == INADDR_ANY)
|
||||
return 1;
|
||||
break;
|
||||
|
||||
#ifndef NOINET6
|
||||
case AF_INET6:
|
||||
if (range->ncprange_ip6width == 0 &&
|
||||
IN6_IS_ADDR_UNSPECIFIED(&range->ncprange_ip6addr))
|
||||
return 1;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ncprange_setdefault(struct ncprange *range, int af)
|
||||
{
|
||||
memset(range, '\0', sizeof *range);
|
||||
range->ncprange_family = af;
|
||||
}
|
||||
|
||||
int
|
||||
ncprange_contains(const struct ncprange *range, const struct ncpaddr *addr)
|
||||
{
|
||||
#ifndef NOINET6
|
||||
const u_char masks[] = { 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
|
||||
const u_char *addrp, *rangep;
|
||||
int bits;
|
||||
#endif
|
||||
|
||||
if (range->ncprange_family != addr->ncpaddr_family)
|
||||
return 0;
|
||||
|
||||
switch (range->ncprange_family) {
|
||||
case AF_INET:
|
||||
return !((addr->ncpaddr_ip4addr.s_addr ^ range->ncprange_ip4addr.s_addr) &
|
||||
range->ncprange_ip4mask.s_addr);
|
||||
|
||||
#ifndef NOINET6
|
||||
case AF_INET6:
|
||||
rangep = (const u_char *)range->ncprange_ip6addr.s6_addr;
|
||||
addrp = (const u_char *)addr->ncpaddr_ip6addr.s6_addr;
|
||||
|
||||
for (bits = range->ncprange_ip6width; bits > 0; bits -= 8)
|
||||
if ((*addrp++ ^ *rangep++) & masks[bits > 7 ? 7 : bits - 1])
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ncprange_containsip4(const struct ncprange *range, struct in_addr addr)
|
||||
{
|
||||
switch (range->ncprange_family) {
|
||||
case AF_INET:
|
||||
return !((addr.s_addr ^ range->ncprange_ip4addr.s_addr) &
|
||||
range->ncprange_ip4mask.s_addr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ncprange_copy(struct ncprange *range, const struct ncprange *from)
|
||||
{
|
||||
switch (from->ncprange_family) {
|
||||
case AF_INET:
|
||||
range->ncprange_family = AF_INET;
|
||||
range->ncprange_ip4addr = from->ncprange_ip4addr;
|
||||
range->ncprange_ip4mask = from->ncprange_ip4mask;
|
||||
range->ncprange_ip4width = from->ncprange_ip4width;
|
||||
break;
|
||||
|
||||
#ifndef NOINET6
|
||||
case AF_INET6:
|
||||
range->ncprange_family = AF_INET6;
|
||||
range->ncprange_ip6addr = from->ncprange_ip6addr;
|
||||
range->ncprange_ip6width = from->ncprange_ip6width;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
range->ncprange_family = AF_UNSPEC;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ncprange_set(struct ncprange *range, const struct ncpaddr *addr, int width)
|
||||
{
|
||||
ncprange_sethost(range, addr);
|
||||
ncprange_setwidth(range, width);
|
||||
}
|
||||
|
||||
void
|
||||
ncprange_sethost(struct ncprange *range, const struct ncpaddr *from)
|
||||
{
|
||||
switch (from->ncpaddr_family) {
|
||||
case AF_INET:
|
||||
range->ncprange_family = AF_INET;
|
||||
range->ncprange_ip4addr = from->ncpaddr_ip4addr;
|
||||
range->ncprange_ip4mask.s_addr = INADDR_BROADCAST;
|
||||
range->ncprange_ip4width = 32;
|
||||
break;
|
||||
|
||||
#ifndef NOINET6
|
||||
case AF_INET6:
|
||||
range->ncprange_family = AF_INET6;
|
||||
range->ncprange_ip6addr = from->ncpaddr_ip6addr;
|
||||
range->ncprange_ip6width = 128;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
range->ncprange_family = AF_UNSPEC;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ncprange_setwidth(struct ncprange *range, int width)
|
||||
{
|
||||
switch (range->ncprange_family) {
|
||||
case AF_INET:
|
||||
if (width < 0 || width > 32)
|
||||
break;
|
||||
range->ncprange_ip4width = width;
|
||||
range->ncprange_ip4mask = bits2mask4(width);
|
||||
break;
|
||||
|
||||
#ifndef NOINET6
|
||||
case AF_INET6:
|
||||
if (width < 0 || width > 128)
|
||||
break;
|
||||
range->ncprange_ip6width = width;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case AF_UNSPEC:
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ncprange_setip4host(struct ncprange *range, struct in_addr from)
|
||||
{
|
||||
range->ncprange_family = AF_INET;
|
||||
range->ncprange_ip4addr = from;
|
||||
range->ncprange_ip4mask.s_addr = INADDR_BROADCAST;
|
||||
range->ncprange_ip4width = 32;
|
||||
}
|
||||
|
||||
void
|
||||
ncprange_setip4(struct ncprange *range, struct in_addr from, struct in_addr msk)
|
||||
{
|
||||
range->ncprange_family = AF_INET;
|
||||
range->ncprange_ip4addr = from;
|
||||
range->ncprange_ip4mask = msk;
|
||||
range->ncprange_ip4width = mask42bits(msk);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ncprange_setip4mask(struct ncprange *range, struct in_addr mask)
|
||||
{
|
||||
if (range->ncprange_family != AF_INET)
|
||||
return 0;
|
||||
range->ncprange_ip4mask = mask;
|
||||
range->ncprange_ip4width = mask42bits(mask);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
ncprange_setsa(struct ncprange *range, const struct sockaddr *host,
|
||||
const struct sockaddr *mask)
|
||||
{
|
||||
const struct sockaddr_in *host4 = (const struct sockaddr_in *)host;
|
||||
const struct sockaddr_in *mask4 = (const struct sockaddr_in *)mask;
|
||||
#ifndef NOINET6
|
||||
const struct sockaddr_in6 *host6 = (const struct sockaddr_in6 *)host;
|
||||
const struct sockaddr_in6 *mask6 = (const struct sockaddr_in6 *)mask;
|
||||
#endif
|
||||
|
||||
switch (host->sa_family) {
|
||||
case AF_INET:
|
||||
range->ncprange_family = AF_INET;
|
||||
range->ncprange_ip4addr = host4->sin_addr;
|
||||
if (mask4) {
|
||||
range->ncprange_ip4mask.s_addr = mask4->sin_addr.s_addr;
|
||||
range->ncprange_ip4width = mask42bits(mask4->sin_addr);
|
||||
} else {
|
||||
range->ncprange_ip4mask.s_addr = INADDR_BROADCAST;
|
||||
range->ncprange_ip4width = 32;
|
||||
}
|
||||
break;
|
||||
|
||||
#ifndef NOINET6
|
||||
case AF_INET6:
|
||||
range->ncprange_family = AF_INET6;
|
||||
range->ncprange_ip6addr = host6->sin6_addr;
|
||||
range->ncprange_ip6width = mask6 ? mask62bits(&mask6->sin6_addr) : 128;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
range->ncprange_family = AF_UNSPEC;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ncprange_getsa(const struct ncprange *range, struct sockaddr_storage *host,
|
||||
struct sockaddr_storage *mask)
|
||||
{
|
||||
struct sockaddr_in *host4 = (struct sockaddr_in *)host;
|
||||
struct sockaddr_in *mask4 = (struct sockaddr_in *)mask;
|
||||
#ifndef NOINET6
|
||||
struct sockaddr_in6 *host6 = (struct sockaddr_in6 *)host;
|
||||
struct sockaddr_in6 *mask6 = (struct sockaddr_in6 *)mask;
|
||||
#endif
|
||||
|
||||
memset(host, '\0', sizeof(*host));
|
||||
if (mask)
|
||||
memset(mask, '\0', sizeof(*mask));
|
||||
|
||||
switch (range->ncprange_family) {
|
||||
case AF_INET:
|
||||
host4->sin_family = AF_INET;
|
||||
host4->sin_len = sizeof(*host4);
|
||||
host4->sin_addr = range->ncprange_ip4addr;
|
||||
if (mask4) {
|
||||
mask4->sin_family = AF_INET;
|
||||
mask4->sin_len = sizeof(*host4);
|
||||
mask4->sin_addr = bits2mask4(range->ncprange_ip4width);
|
||||
}
|
||||
break;
|
||||
|
||||
#ifndef NOINET6
|
||||
case AF_INET6:
|
||||
host6->sin6_family = AF_INET6;
|
||||
host6->sin6_len = sizeof(*host6);
|
||||
host6->sin6_addr = range->ncprange_ip6addr;
|
||||
adjust_linklocal(host6);
|
||||
if (mask6) {
|
||||
mask6->sin6_family = AF_INET6;
|
||||
mask6->sin6_len = sizeof(*host6);
|
||||
mask6->sin6_addr = bits2mask6(range->ncprange_ip6width);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
host->ss_family = AF_UNSPEC;
|
||||
if (mask)
|
||||
mask->ss_family = AF_UNSPEC;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ncprange_getaddr(const struct ncprange *range, struct ncpaddr *addr)
|
||||
{
|
||||
switch (range->ncprange_family) {
|
||||
case AF_INET:
|
||||
addr->ncpaddr_family = AF_INET;
|
||||
addr->ncpaddr_ip4addr = range->ncprange_ip4addr;
|
||||
return 1;
|
||||
#ifndef NOINET6
|
||||
case AF_INET6:
|
||||
addr->ncpaddr_family = AF_INET6;
|
||||
addr->ncpaddr_ip6addr = range->ncprange_ip6addr;
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ncprange_getip4addr(const struct ncprange *range, struct in_addr *addr)
|
||||
{
|
||||
if (range->ncprange_family != AF_INET)
|
||||
return 0;
|
||||
|
||||
*addr = range->ncprange_ip4addr;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
ncprange_getip4mask(const struct ncprange *range, struct in_addr *mask)
|
||||
{
|
||||
switch (range->ncprange_family) {
|
||||
case AF_INET:
|
||||
*mask = range->ncprange_ip4mask;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ncprange_getwidth(const struct ncprange *range, int *width)
|
||||
{
|
||||
switch (range->ncprange_family) {
|
||||
case AF_INET:
|
||||
*width = range->ncprange_ip4width;
|
||||
return 1;
|
||||
#ifndef NOINET6
|
||||
case AF_INET6:
|
||||
*width = range->ncprange_ip6width;
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *
|
||||
ncprange_ntoa(const struct ncprange *range)
|
||||
{
|
||||
char *res;
|
||||
struct ncpaddr addr;
|
||||
int len;
|
||||
|
||||
if (!ncprange_getaddr(range, &addr))
|
||||
return "<AF_UNSPEC>";
|
||||
|
||||
res = ncpaddr_ntowa(&addr);
|
||||
len = strlen(res);
|
||||
if (len >= NCP_ASCIIBUFFERSIZE - 1)
|
||||
return res;
|
||||
|
||||
switch (range->ncprange_family) {
|
||||
case AF_INET:
|
||||
if (range->ncprange_ip4width == -1) {
|
||||
/* A non-contiguous mask */
|
||||
for (; len >= 3; res[len -= 2] = '\0')
|
||||
if (strcmp(res + len - 2, ".0"))
|
||||
break;
|
||||
snprintf(res + len, sizeof res - len, "&0x%08lx",
|
||||
ntohl(range->ncprange_ip4mask.s_addr));
|
||||
} else if (range->ncprange_ip4width < 32)
|
||||
snprintf(res + len, sizeof res - len, "/%d", range->ncprange_ip4width);
|
||||
|
||||
return res;
|
||||
|
||||
#ifndef NOINET6
|
||||
case AF_INET6:
|
||||
if (range->ncprange_ip6width != 128)
|
||||
snprintf(res + len, sizeof res - len, "/%d", range->ncprange_ip6width);
|
||||
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
return "<AF_UNSPEC>";
|
||||
}
|
||||
|
||||
#ifndef NOINET6
|
||||
int
|
||||
ncprange_scopeid(const struct ncprange *range)
|
||||
{
|
||||
const struct in6_addr *sin6;
|
||||
int scopeid = -1;
|
||||
|
||||
if (range->ncprange_family == AF_INET6) {
|
||||
sin6 = &range->ncprange_ip6addr;
|
||||
if (IN6_IS_ADDR_LINKLOCAL(sin6) || IN6_IS_ADDR_MC_LINKLOCAL(sin6))
|
||||
if ((scopeid = ntohs(*(const u_short *)&sin6->s6_addr[2])) == 0)
|
||||
scopeid = -1;
|
||||
}
|
||||
|
||||
return scopeid;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
ncprange_aton(struct ncprange *range, struct ncp *ncp, const char *data)
|
||||
{
|
||||
int bits, len;
|
||||
char *wp;
|
||||
const char *cp;
|
||||
char *s;
|
||||
|
||||
len = strcspn(data, "/");
|
||||
|
||||
if (ncp && strncasecmp(data, "HISADDR", len) == 0) {
|
||||
range->ncprange_family = AF_INET;
|
||||
range->ncprange_ip4addr = ncp->ipcp.peer_ip;
|
||||
range->ncprange_ip4mask.s_addr = INADDR_BROADCAST;
|
||||
range->ncprange_ip4width = 32;
|
||||
return 1;
|
||||
#ifndef NOINET6
|
||||
} else if (ncp && strncasecmp(data, "HISADDR6", len) == 0) {
|
||||
ncprange_sethost(range, &ncp->ipv6cp.hisaddr);
|
||||
return 1;
|
||||
#endif
|
||||
} else if (ncp && strncasecmp(data, "MYADDR", len) == 0) {
|
||||
range->ncprange_family = AF_INET;
|
||||
range->ncprange_ip4addr = ncp->ipcp.my_ip;
|
||||
range->ncprange_ip4mask.s_addr = INADDR_BROADCAST;
|
||||
range->ncprange_ip4width = 32;
|
||||
return 1;
|
||||
#ifndef NOINET6
|
||||
} else if (ncp && strncasecmp(data, "MYADDR6", len) == 0) {
|
||||
ncprange_sethost(range, &ncp->ipv6cp.myaddr);
|
||||
return 1;
|
||||
#endif
|
||||
} else if (ncp && strncasecmp(data, "DNS0", len) == 0) {
|
||||
range->ncprange_family = AF_INET;
|
||||
range->ncprange_ip4addr = ncp->ipcp.ns.dns[0];
|
||||
range->ncprange_ip4mask.s_addr = INADDR_BROADCAST;
|
||||
range->ncprange_ip4width = 32;
|
||||
return 1;
|
||||
} else if (ncp && strncasecmp(data, "DNS1", len) == 0) {
|
||||
range->ncprange_family = AF_INET;
|
||||
range->ncprange_ip4addr = ncp->ipcp.ns.dns[1];
|
||||
range->ncprange_ip4mask.s_addr = INADDR_BROADCAST;
|
||||
range->ncprange_ip4width = 32;
|
||||
return 1;
|
||||
}
|
||||
|
||||
s = (char *)alloca(len + 1);
|
||||
strncpy(s, data, len);
|
||||
s[len] = '\0';
|
||||
bits = -1;
|
||||
|
||||
if (data[len] != '\0') {
|
||||
bits = strtol(data + len + 1, &wp, 0);
|
||||
if (*wp || wp == data + len + 1 || bits < 0 || bits > 128) {
|
||||
log_Printf(LogWARN, "ncprange_aton: bad mask width.\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ((cp = strchr(data, ':')) == NULL) {
|
||||
range->ncprange_family = AF_INET;
|
||||
|
||||
range->ncprange_ip4addr = GetIpAddr(s);
|
||||
|
||||
if (range->ncprange_ip4addr.s_addr == INADDR_NONE) {
|
||||
log_Printf(LogWARN, "ncprange_aton: %s: Bad address\n", s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (range->ncprange_ip4addr.s_addr == INADDR_ANY) {
|
||||
range->ncprange_ip4mask.s_addr = INADDR_ANY;
|
||||
range->ncprange_ip4width = 0;
|
||||
} else if (data[len] == '\0') {
|
||||
range->ncprange_ip4mask.s_addr = INADDR_BROADCAST;
|
||||
range->ncprange_ip4width = 32;
|
||||
} else {
|
||||
if (bits > 32) {
|
||||
log_Printf(LogWARN, "ncprange_aton: bad mask width.\n");
|
||||
return 0;
|
||||
}
|
||||
range->ncprange_ip4mask = bits2mask4(bits);
|
||||
range->ncprange_ip4width = bits;
|
||||
}
|
||||
|
||||
return 1;
|
||||
#ifndef NOINET6
|
||||
} else if (strchr(cp + 1, ':') != NULL) {
|
||||
range->ncprange_family = AF_INET6;
|
||||
|
||||
if (inet_pton(AF_INET6, s, &range->ncprange_ip6addr) != 1) {
|
||||
log_Printf(LogWARN, "ncprange_aton: %s: Bad address\n", s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&range->ncprange_ip6addr))
|
||||
range->ncprange_ip6width = 0;
|
||||
else
|
||||
range->ncprange_ip6width = (bits == -1) ? 128 : bits;
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
107
usr.sbin/ppp/ncpaddr.h
Normal file
107
usr.sbin/ppp/ncpaddr.h
Normal file
@ -0,0 +1,107 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Brian Somers <brian@Awfulhak.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* These structures should be treated as opaque.
|
||||
*/
|
||||
struct ncprange {
|
||||
sa_family_t ncprange_family;
|
||||
union {
|
||||
struct {
|
||||
struct in_addr ipaddr;
|
||||
struct in_addr mask;
|
||||
int width;
|
||||
} ip4;
|
||||
#ifndef NOINET6
|
||||
struct {
|
||||
struct in6_addr ipaddr;
|
||||
int width;
|
||||
} ip6;
|
||||
#endif
|
||||
} u;
|
||||
};
|
||||
|
||||
struct ncpaddr {
|
||||
sa_family_t ncpaddr_family;
|
||||
union {
|
||||
struct in_addr ip4addr;
|
||||
#ifndef NOINET6
|
||||
struct in6_addr ip6addr;
|
||||
#endif
|
||||
} u;
|
||||
};
|
||||
|
||||
struct ncp;
|
||||
|
||||
extern void ncpaddr_init(struct ncpaddr *);
|
||||
extern int ncpaddr_isdefault(const struct ncpaddr *);
|
||||
extern int ncpaddr_equal(const struct ncpaddr *, const struct ncpaddr *);
|
||||
extern void ncpaddr_copy(struct ncpaddr *, const struct ncpaddr *);
|
||||
extern void ncpaddr_setip4addr(struct ncpaddr *, u_int32_t);
|
||||
extern int ncpaddr_getip4addr(const struct ncpaddr *, u_int32_t *);
|
||||
extern void ncpaddr_setip4(struct ncpaddr *, struct in_addr);
|
||||
extern int ncpaddr_getip4(const struct ncpaddr *, struct in_addr *);
|
||||
#ifndef NOINET6
|
||||
extern void ncpaddr_setip6(struct ncpaddr *, const struct in6_addr *);
|
||||
extern int ncpaddr_getip6(const struct ncpaddr *, struct in6_addr *);
|
||||
#endif
|
||||
extern void ncpaddr_getsa(const struct ncpaddr *, struct sockaddr_storage *);
|
||||
extern void ncpaddr_setsa(struct ncpaddr *, const struct sockaddr *);
|
||||
extern const char *ncpaddr_ntoa(const struct ncpaddr *);
|
||||
extern int ncpaddr_aton(struct ncpaddr *, struct ncp *, const char *);
|
||||
|
||||
extern void ncprange_init(struct ncprange *);
|
||||
extern int ncprange_isset(const struct ncprange *);
|
||||
extern int ncprange_equal(const struct ncprange *, const struct ncprange *);
|
||||
extern int ncprange_isdefault(const struct ncprange *);
|
||||
extern void ncprange_setdefault(struct ncprange *, int);
|
||||
extern int ncprange_contains(const struct ncprange *, const struct ncpaddr *);
|
||||
extern int ncprange_containsip4(const struct ncprange *, struct in_addr);
|
||||
extern void ncprange_copy(struct ncprange *, const struct ncprange *);
|
||||
extern void ncprange_set(struct ncprange *, const struct ncpaddr *, int);
|
||||
extern void ncprange_sethost(struct ncprange *, const struct ncpaddr *);
|
||||
extern int ncprange_setwidth(struct ncprange *, int);
|
||||
extern void ncprange_setip4(struct ncprange *, struct in_addr, struct in_addr);
|
||||
extern void ncprange_setip4host(struct ncprange *, struct in_addr);
|
||||
extern int ncprange_setip4mask(struct ncprange *, struct in_addr);
|
||||
extern void ncprange_setsa(struct ncprange *, const struct sockaddr *,
|
||||
const struct sockaddr *);
|
||||
extern void ncprange_getsa(const struct ncprange *, struct sockaddr_storage *,
|
||||
struct sockaddr_storage *);
|
||||
extern int ncprange_getaddr(const struct ncprange *, struct ncpaddr *);
|
||||
extern int ncprange_getip4addr(const struct ncprange *, struct in_addr *);
|
||||
extern int ncprange_getip4mask(const struct ncprange *, struct in_addr *);
|
||||
extern int ncprange_getwidth(const struct ncprange *, int *);
|
||||
extern const char *ncprange_ntoa(const struct ncprange *);
|
||||
#ifndef NOINET6
|
||||
extern int ncprange_scopeid(const struct ncprange *);
|
||||
#endif
|
||||
extern int ncprange_aton(struct ncprange *, struct ncp *, const char *);
|
||||
|
||||
#define ncpaddr_family(a) ((a)->ncpaddr_family)
|
||||
#define ncprange_family(r) ((r)->ncprange_family)
|
@ -32,6 +32,7 @@
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
@ -58,12 +59,16 @@
|
||||
#include "physical.h"
|
||||
#include "iplist.h"
|
||||
#include "slcompress.h"
|
||||
#include "ncpaddr.h"
|
||||
#include "ip.h"
|
||||
#include "ipcp.h"
|
||||
#include "filter.h"
|
||||
#include "mp.h"
|
||||
#ifndef NORADIUS
|
||||
#include "radius.h"
|
||||
#endif
|
||||
#include "ipv6cp.h"
|
||||
#include "ncp.h"
|
||||
#include "bundle.h"
|
||||
#include "chat.h"
|
||||
#include "chap.h"
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <errno.h>
|
||||
@ -69,6 +70,8 @@
|
||||
#include "async.h"
|
||||
#include "iplist.h"
|
||||
#include "slcompress.h"
|
||||
#include "ncpaddr.h"
|
||||
#include "ip.h"
|
||||
#include "ipcp.h"
|
||||
#include "filter.h"
|
||||
#include "descriptor.h"
|
||||
@ -79,6 +82,8 @@
|
||||
#ifndef NORADIUS
|
||||
#include "radius.h"
|
||||
#endif
|
||||
#include "ipv6cp.h"
|
||||
#include "ncp.h"
|
||||
#include "bundle.h"
|
||||
#include "prompt.h"
|
||||
#include "chat.h"
|
||||
|
@ -396,6 +396,9 @@ For now,
|
||||
can only get encryption keys from CHAP 81 authentication.
|
||||
.Nm
|
||||
must be compiled with DES for MPPE to operate.
|
||||
.It Supports IPV6CP (rfc 2023).
|
||||
An IPv6 connection can be made in addition to or instead of the normal
|
||||
IPv4 connection.
|
||||
.El
|
||||
.Sh PERMISSIONS
|
||||
.Nm
|
||||
@ -719,6 +722,8 @@ PPP ON awfulhak> show lcp
|
||||
* LCP (line control) related information is shown here *
|
||||
PPP ON awfulhak> show ipcp
|
||||
* IPCP (IP) related information is shown here *
|
||||
PPP ON awfulhak> show ipv6cp
|
||||
* IPV6CP (IPv6) related information is shown here *
|
||||
PPP ON awfulhak> show link
|
||||
* Link (high level) related information is shown here *
|
||||
PPP ON awfulhak> show bundle
|
||||
@ -903,16 +908,15 @@ it was necessary to re-add routes such as the default route in the
|
||||
.Pa ppp.linkup
|
||||
file.
|
||||
.Nm
|
||||
now supports
|
||||
supports
|
||||
.Sq sticky routes ,
|
||||
where all routes that contain the
|
||||
.Dv HISADDR
|
||||
.Dv HISADDR ,
|
||||
.Dv MYADDR ,
|
||||
.Dv HISADDR6
|
||||
or
|
||||
.Dv MYADDR
|
||||
literals will automatically be updated when the values of
|
||||
.Dv HISADDR
|
||||
and/or
|
||||
.Dv MYADDR
|
||||
.Dv MYADDR6
|
||||
literals will automatically be updated when the values of these variables
|
||||
change.
|
||||
.Sh BACKGROUND DIALING
|
||||
If you want to establish a connection using
|
||||
@ -1502,7 +1506,7 @@ ui-gate:
|
||||
set device ui-gate:ppp-in/tcp
|
||||
set dial
|
||||
set timeout 30
|
||||
set log Phase Chat Connect hdlc LCP IPCP CCP tun
|
||||
set log Phase Chat Connect hdlc LCP IPCP IPV6CP CCP tun
|
||||
set ifaddr 10.0.4.2 10.0.4.1
|
||||
.Ed
|
||||
.Pp
|
||||
@ -1738,9 +1742,11 @@ Either
|
||||
or
|
||||
.Ar dst_addr
|
||||
may be given the values
|
||||
.Dv MYADDR
|
||||
.Dv MYADDR ,
|
||||
.Dv HISADDR ,
|
||||
.Dv MYADDR6
|
||||
or
|
||||
.Dv HISADDR
|
||||
.Dv HISADDR6
|
||||
(refer to the description of the
|
||||
.Dq bg
|
||||
command for a description of these values).
|
||||
@ -1751,14 +1757,8 @@ This is similar to the behaviour of the
|
||||
command below.
|
||||
.It
|
||||
.Ar Proto
|
||||
must be one of
|
||||
.Sq icmp ,
|
||||
.Sq igmp ,
|
||||
.Sq ipip ,
|
||||
.Sq ospf ,
|
||||
.Sq udp
|
||||
or
|
||||
.Sq tcp .
|
||||
may be any protocol from
|
||||
.Xr protocols 5 .
|
||||
.It
|
||||
.Ar Cmp
|
||||
is one of
|
||||
@ -1889,19 +1889,20 @@ to successfully negotiate DEFLATE with
|
||||
.Nm pppd
|
||||
version 2.3.*.
|
||||
.Sh CONTROLLING IP ADDRESS
|
||||
For IPv4,
|
||||
.Nm
|
||||
uses IPCP to negotiate IP addresses.
|
||||
Each side of the connection
|
||||
specifies the IP address that it's willing to use, and if the requested
|
||||
IP address is acceptable then
|
||||
.Nm
|
||||
returns ACK to the requester.
|
||||
returns an ACK to the requester.
|
||||
Otherwise,
|
||||
.Nm
|
||||
returns NAK to suggest that the peer use a different IP address.
|
||||
When
|
||||
both sides of the connection agree to accept the received request (and
|
||||
send ACK), IPCP is set to the open state and a network level connection
|
||||
send an ACK), IPCP is set to the open state and a network level connection
|
||||
is established.
|
||||
To control this IPCP behaviour, this implementation has the
|
||||
.Dq set ifaddr
|
||||
@ -1999,8 +2000,11 @@ When using zero, no routing table entries will be made until a connection
|
||||
is established.
|
||||
.It
|
||||
192.244.177.2/0 means that I'll accept/permit any IP address but I'll
|
||||
try to insist that 192.244.177.2 be used first.
|
||||
suggest that 192.244.177.2 be used first.
|
||||
.El
|
||||
.Pp
|
||||
When negotiating IPv6 addresses, no control is given to the user.
|
||||
IPV6CP negotiation is fully automatic.
|
||||
.Sh CONNECTING WITH YOUR INTERNET SERVICE PROVIDER
|
||||
The following steps should be taken when connecting to your ISP:
|
||||
.Bl -enum
|
||||
@ -2210,7 +2214,10 @@ add default HISADDR
|
||||
.Ed
|
||||
.Pp
|
||||
to
|
||||
.Pa /etc/ppp/ppp.conf .
|
||||
.Pa /etc/ppp/ppp.conf
|
||||
(or to
|
||||
.Pa /etc/ppp/ppp.linkup
|
||||
for setups that don't use -auto mode).
|
||||
.Pp
|
||||
This tells
|
||||
.Nm
|
||||
@ -2221,15 +2228,6 @@ This route is
|
||||
meaning that should the value of
|
||||
.Dv HISADDR
|
||||
change, the route will be updated accordingly.
|
||||
.Pp
|
||||
Previous versions of
|
||||
.Nm
|
||||
required a similar entry in the
|
||||
.Pa /etc/ppp/ppp.linkup
|
||||
file.
|
||||
Since the advent of
|
||||
.Sq sticky routes ,
|
||||
this is no longer required.
|
||||
.It
|
||||
If your provider requests that you use PAP/CHAP authentication methods, add
|
||||
the next lines to your
|
||||
@ -2948,6 +2946,43 @@ If
|
||||
is disabled,
|
||||
.Nm
|
||||
will ignore the identifier field.
|
||||
.It iface-alias
|
||||
Default: Enabled if
|
||||
.Fl nat
|
||||
is specified.
|
||||
This option simply tells
|
||||
.Nm
|
||||
to add new interface addresses to the interface rather than replacing them.
|
||||
The option can only be enabled if network address translation is enabled
|
||||
.Pq Dq nat enable yes .
|
||||
.Pp
|
||||
With this option enabled,
|
||||
.Nm
|
||||
will pass traffic for old interface addresses through the NAT
|
||||
ifdef({LOCALNAT},{engine,},{engine
|
||||
(see
|
||||
.Xr libalias 3 ) ,})
|
||||
resulting in the ability (in
|
||||
.Fl auto
|
||||
mode) to properly connect the process that caused the PPP link to
|
||||
come up in the first place.
|
||||
.Pp
|
||||
Disabling NAT with
|
||||
.Dq nat enable no
|
||||
will also disable
|
||||
.Sq iface-alias .
|
||||
.It ipcp
|
||||
Default: Enabled.
|
||||
This option allows
|
||||
.Nm
|
||||
to attempt to negotiate IP control protocol capabilities and if
|
||||
successful to exchange IP datagrams with the peer.
|
||||
.It ipv6cp
|
||||
Default: Enabled.
|
||||
This option allows
|
||||
.Nm
|
||||
to attempt to negotiate IPv6 control protocol capabilities and if
|
||||
successful to exchange IPv6 datagrams with the peer.
|
||||
.It keep-session
|
||||
Default: Disabled.
|
||||
When
|
||||
@ -3058,17 +3093,15 @@ Default: Enabled.
|
||||
When the
|
||||
.Dq add
|
||||
command is used with the
|
||||
.Dv HISADDR
|
||||
.Dv HISADDR ,
|
||||
.Dv MYADDR ,
|
||||
.Dv HISADDR6
|
||||
or
|
||||
.Dv MYADDR
|
||||
.Dv MYADDR6
|
||||
values, entries are stored in the
|
||||
.Sq stick route
|
||||
.Sq sticky route
|
||||
list.
|
||||
Each time
|
||||
.Dv HISADDR
|
||||
or
|
||||
.Dv MYADDR
|
||||
change, this list is re-applied to the routing table.
|
||||
Each time these variables change, this list is re-applied to the routing table.
|
||||
.Pp
|
||||
Disabling this option will prevent the re-application of sticky routes,
|
||||
although the
|
||||
@ -3111,31 +3144,6 @@ Disabling this option will tell
|
||||
not to make any utmp or wtmp entries.
|
||||
This is usually only necessary if
|
||||
you require the user to both login and authenticate themselves.
|
||||
.It iface-alias
|
||||
Default: Enabled if
|
||||
.Fl nat
|
||||
is specified.
|
||||
This option simply tells
|
||||
.Nm
|
||||
to add new interface addresses to the interface rather than replacing them.
|
||||
The option can only be enabled if network address translation is enabled
|
||||
.Pq Dq nat enable yes .
|
||||
.Pp
|
||||
With this option enabled,
|
||||
.Nm
|
||||
will pass traffic for old interface addresses through the NAT
|
||||
ifdef({LOCALNAT},{engine,},{engine
|
||||
(see
|
||||
.Xr libalias 3 ) ,})
|
||||
resulting in the ability (in
|
||||
.Fl auto
|
||||
mode) to properly connect the process that caused the PPP link to
|
||||
come up in the first place.
|
||||
.Pp
|
||||
Disabling NAT with
|
||||
.Dq nat enable no
|
||||
will also disable
|
||||
.Sq iface-alias .
|
||||
.El
|
||||
.Pp
|
||||
.It add Ns Xo
|
||||
@ -3167,17 +3175,25 @@ Refer to the
|
||||
command for further details.
|
||||
.Pp
|
||||
It is possible to use the symbolic names
|
||||
.Sq MYADDR
|
||||
.Sq MYADDR ,
|
||||
.Sq HISADDR ,
|
||||
.Sq MYADDR6
|
||||
or
|
||||
.Sq HISADDR
|
||||
.Sq HISADDR6
|
||||
as the destination, and
|
||||
.Sq HISADDR
|
||||
or
|
||||
.Sq HISADDR6
|
||||
as the
|
||||
.Ar gateway .
|
||||
.Sq MYADDR
|
||||
is replaced with the interface address and
|
||||
is replaced with the interface IP address,
|
||||
.Sq HISADDR
|
||||
is replaced with the interface destination (peer) address.
|
||||
is replaced with the interface IP destination (peer) address,
|
||||
.Sq MYADDR6
|
||||
is replaced with the interface IPv6 address, and
|
||||
.Sq HISADDR6
|
||||
is replaced with the interface IPv6 destination address,
|
||||
.Pp
|
||||
If the
|
||||
.Ar add!\&
|
||||
@ -3193,19 +3209,16 @@ for further details).
|
||||
Routes that contain the
|
||||
.Dq HISADDR ,
|
||||
.Dq MYADDR ,
|
||||
.Dq HISADDR6 ,
|
||||
.Dq MYADDR6 ,
|
||||
.Dq DNS0 ,
|
||||
or
|
||||
.Dq DNS1
|
||||
constants are considered
|
||||
.Sq sticky .
|
||||
They are stored in a list (use
|
||||
.Dq show ipcp
|
||||
to see the list), and each time the value of
|
||||
.Dv HISADDR ,
|
||||
.Dv MYADDR ,
|
||||
.Dv DNS0 ,
|
||||
or
|
||||
.Dv DNS1
|
||||
.Dq show ncp
|
||||
to see the list), and each time the value of one of these variables
|
||||
changes, the appropriate routing table entries are updated.
|
||||
This facility may be disabled using
|
||||
.Dq disable sroutes .
|
||||
@ -3500,6 +3513,8 @@ See the
|
||||
command below.
|
||||
.It Li HISADDR
|
||||
This is replaced with the peers IP number.
|
||||
.It Li HISADDR6
|
||||
This is replaced with the peers IPv6 number.
|
||||
.It Li INTERFACE
|
||||
This is replaced with the name of the interface that's in use.
|
||||
.It Li LABEL
|
||||
@ -3515,6 +3530,8 @@ commands and in the
|
||||
file.
|
||||
.It Li MYADDR
|
||||
This is replaced with the IP number assigned to the local interface.
|
||||
.It Li MYADDR6
|
||||
This is replaced with the IPv6 number assigned to the local interface.
|
||||
.It Li PEER_ENDDISC
|
||||
This is replaced with the value of the peers endpoint discriminator.
|
||||
.It Li PROCESSID
|
||||
@ -3538,11 +3555,12 @@ If you wish to pause
|
||||
while the command executes, use the
|
||||
.Dq shell
|
||||
command instead.
|
||||
.It clear physical|ipcp Op current|overall|peak...
|
||||
.It clear physical|ipcp|ipv6 Op current|overall|peak...
|
||||
Clear the specified throughput values at either the
|
||||
.Dq physical
|
||||
or
|
||||
.Dq physical ,
|
||||
.Dq ipcp
|
||||
or
|
||||
.Dq ipv6cp
|
||||
level.
|
||||
If
|
||||
.Dq physical
|
||||
@ -3712,12 +3730,12 @@ defaults to
|
||||
This address (the broadcast address) is the only duplicate peer address that
|
||||
.Nm
|
||||
allows.
|
||||
.It iface clear
|
||||
.It iface clear Op INET | INET6
|
||||
If this command is used while
|
||||
.Nm
|
||||
is in the OPENED state or while in
|
||||
.Fl auto
|
||||
mode, all addresses except for the IPCP negotiated address are deleted
|
||||
mode, all addresses except for the NCP negotiated address are deleted
|
||||
from the interface.
|
||||
If
|
||||
.Nm
|
||||
@ -3725,6 +3743,9 @@ is not in the OPENED state and is not in
|
||||
.Fl auto
|
||||
mode, all interface addresses are deleted.
|
||||
.Pp
|
||||
If the INET or INET6 arguments are used, only addresses for that address
|
||||
family are cleared.
|
||||
.Pp
|
||||
.It iface delete Ns Xo
|
||||
.Op !\& Ns
|
||||
.No |rm Ns Op !\&
|
||||
@ -4698,7 +4719,7 @@ as they travel across the link.
|
||||
.Oo Op host
|
||||
.Ar src_addr Ns Op / Ns Ar width
|
||||
.Op Ar dst_addr Ns Op / Ns Ar width
|
||||
.Oc [ tcp|udp|ospf|ipip|igmp|icmp Op src lt|eq|gt Ar port
|
||||
.Oc [ Ns Ar proto Op src lt|eq|gt Ar port
|
||||
.Op dst lt|eq|gt Ar port
|
||||
.Op estab
|
||||
.Op syn
|
||||
@ -5577,6 +5598,8 @@ Show a list of available logical links.
|
||||
Show the current log values.
|
||||
.It show mem
|
||||
Show current memory statistics.
|
||||
.It show ncp
|
||||
Show the current NCP statistics.
|
||||
.It show physical
|
||||
Show low level link information.
|
||||
.It show mp
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <errno.h>
|
||||
@ -57,6 +58,8 @@
|
||||
#include "lqr.h"
|
||||
#include "hdlc.h"
|
||||
#include "lcp.h"
|
||||
#include "ncpaddr.h"
|
||||
#include "ip.h"
|
||||
#include "ipcp.h"
|
||||
#include "filter.h"
|
||||
#include "async.h"
|
||||
@ -67,6 +70,8 @@
|
||||
#ifndef NORADIUS
|
||||
#include "radius.h"
|
||||
#endif
|
||||
#include "ipv6cp.h"
|
||||
#include "ncp.h"
|
||||
#include "bundle.h"
|
||||
#include "chat.h"
|
||||
#include "chap.h"
|
||||
|
@ -35,12 +35,18 @@
|
||||
#define PROTO_VJUNCOMP 0x002f /* VJ Uncompressed */
|
||||
#define PROTO_VJCOMP 0x002d /* VJ Compressed */
|
||||
#define PROTO_MP 0x003d /* Multilink fragment */
|
||||
#ifndef NOINET6
|
||||
#define PROTO_IPV6 0x0057 /* IPv6 */
|
||||
#endif
|
||||
#define PROTO_ICOMPD 0x00fb /* Individual link compressed */
|
||||
#define PROTO_COMPD 0x00fd /* Compressed datagram */
|
||||
|
||||
#define PROTO_COMPRESSIBLE(p) (((p) & 0xffe1) == 0x21)
|
||||
|
||||
#define PROTO_IPCP 0x8021
|
||||
#ifndef NOINET6
|
||||
#define PROTO_IPV6CP 0x8057
|
||||
#endif
|
||||
#define PROTO_ICCP 0x80fb
|
||||
#define PROTO_CCP 0x80fd
|
||||
|
||||
|
@ -65,7 +65,10 @@
|
||||
#include "lqr.h"
|
||||
#include "hdlc.h"
|
||||
#include "mbuf.h"
|
||||
#include "ncpaddr.h"
|
||||
#include "ip.h"
|
||||
#include "ipcp.h"
|
||||
#include "ipv6cp.h"
|
||||
#include "route.h"
|
||||
#include "command.h"
|
||||
#include "filter.h"
|
||||
@ -81,6 +84,7 @@
|
||||
#include "cbcp.h"
|
||||
#include "chap.h"
|
||||
#include "datalink.h"
|
||||
#include "ncp.h"
|
||||
#include "bundle.h"
|
||||
|
||||
/*
|
||||
@ -91,12 +95,14 @@ radius_Process(struct radius *r, int got)
|
||||
{
|
||||
char *argv[MAXARGS], *nuke;
|
||||
struct bundle *bundle;
|
||||
int argc, addrs;
|
||||
int argc, addrs, width;
|
||||
size_t len;
|
||||
struct in_range dest;
|
||||
struct in_addr gw;
|
||||
struct ncprange dest;
|
||||
struct ncpaddr gw;
|
||||
const void *data;
|
||||
const char *stype;
|
||||
u_int32_t ipaddr;
|
||||
struct in_addr ip;
|
||||
|
||||
r->cx.fd = -1; /* Stop select()ing */
|
||||
stype = r->cx.auth ? "auth" : "acct";
|
||||
@ -199,8 +205,8 @@ radius_Process(struct radius *r, int got)
|
||||
|
||||
log_Printf(LogPHASE, " Route: %s\n", nuke);
|
||||
bundle = r->cx.auth->physical->dl->bundle;
|
||||
dest.ipaddr.s_addr = dest.mask.s_addr = INADDR_ANY;
|
||||
dest.width = 0;
|
||||
ip.s_addr = INADDR_ANY;
|
||||
ncprange_setip4host(&dest, ip);
|
||||
argc = command_Interpret(nuke, strlen(nuke), argv);
|
||||
if (argc < 0)
|
||||
log_Printf(LogWARN, "radius: %s: Syntax error\n",
|
||||
@ -209,15 +215,17 @@ radius_Process(struct radius *r, int got)
|
||||
log_Printf(LogWARN, "radius: %s: Invalid route\n",
|
||||
argc == 1 ? argv[0] : "\"\"");
|
||||
else if ((strcasecmp(argv[0], "default") != 0 &&
|
||||
!ParseAddr(&bundle->ncp.ipcp, argv[0], &dest.ipaddr,
|
||||
&dest.mask, &dest.width)) ||
|
||||
!ParseAddr(&bundle->ncp.ipcp, argv[1], &gw, NULL, NULL))
|
||||
!ncprange_aton(&dest, &bundle->ncp, argv[0])) ||
|
||||
!ncpaddr_aton(&gw, &bundle->ncp, argv[1]))
|
||||
log_Printf(LogWARN, "radius: %s %s: Invalid route\n",
|
||||
argv[0], argv[1]);
|
||||
else {
|
||||
if (dest.width == 32 && strchr(argv[0], '/') == NULL)
|
||||
ncprange_getwidth(&dest, &width);
|
||||
if (width == 32 && strchr(argv[0], '/') == NULL) {
|
||||
/* No mask specified - use the natural mask */
|
||||
dest.mask = addr2mask(dest.ipaddr);
|
||||
ncprange_getip4addr(&dest, &ip);
|
||||
ncprange_setip4mask(&dest, addr2mask(ip));
|
||||
}
|
||||
addrs = 0;
|
||||
|
||||
if (!strncasecmp(argv[0], "HISADDR", 7))
|
||||
@ -225,13 +233,13 @@ radius_Process(struct radius *r, int got)
|
||||
else if (!strncasecmp(argv[0], "MYADDR", 6))
|
||||
addrs = ROUTE_DSTMYADDR;
|
||||
|
||||
if (gw.s_addr == INADDR_ANY) {
|
||||
if (ncpaddr_getip4addr(&gw, &ipaddr) && ipaddr == INADDR_ANY) {
|
||||
addrs |= ROUTE_GWHISADDR;
|
||||
gw = bundle->ncp.ipcp.peer_ip;
|
||||
ncpaddr_setip4(&gw, bundle->ncp.ipcp.peer_ip);
|
||||
} else if (strcasecmp(argv[1], "HISADDR") == 0)
|
||||
addrs |= ROUTE_GWHISADDR;
|
||||
|
||||
route_Add(&r->routes, addrs, dest.ipaddr, dest.mask, gw);
|
||||
route_Add(&r->routes, addrs, &dest, &gw);
|
||||
}
|
||||
free(nuke);
|
||||
break;
|
||||
|
@ -64,6 +64,8 @@
|
||||
#include "ccp.h"
|
||||
#include "link.h"
|
||||
#include "slcompress.h"
|
||||
#include "ncpaddr.h"
|
||||
#include "ip.h"
|
||||
#include "ipcp.h"
|
||||
#include "filter.h"
|
||||
#include "descriptor.h"
|
||||
@ -71,6 +73,8 @@
|
||||
#ifndef NORADIUS
|
||||
#include "radius.h"
|
||||
#endif
|
||||
#include "ipv6cp.h"
|
||||
#include "ncp.h"
|
||||
#include "bundle.h"
|
||||
#include "route.h"
|
||||
#include "prompt.h"
|
||||
@ -82,9 +86,8 @@ static void
|
||||
p_sockaddr(struct prompt *prompt, struct sockaddr *phost,
|
||||
struct sockaddr *pmask, int width)
|
||||
{
|
||||
struct ncprange range;
|
||||
char buf[29];
|
||||
struct sockaddr_in *ihost4 = (struct sockaddr_in *)phost;
|
||||
struct sockaddr_in *mask4 = (struct sockaddr_in *)pmask;
|
||||
struct sockaddr_dl *dl = (struct sockaddr_dl *)phost;
|
||||
|
||||
if (log_IsKept(LogDEBUG)) {
|
||||
@ -103,39 +106,15 @@ p_sockaddr(struct prompt *prompt, struct sockaddr *phost,
|
||||
|
||||
switch (phost->sa_family) {
|
||||
case AF_INET:
|
||||
if (!phost)
|
||||
buf[0] = '\0';
|
||||
else if (ihost4->sin_addr.s_addr == INADDR_ANY)
|
||||
strcpy(buf, "default");
|
||||
else if (!pmask)
|
||||
strcpy(buf, inet_ntoa(ihost4->sin_addr));
|
||||
else {
|
||||
u_int32_t msk = ntohl(mask4->sin_addr.s_addr);
|
||||
u_int32_t tst;
|
||||
int bits;
|
||||
int len;
|
||||
struct sockaddr_in net;
|
||||
|
||||
for (tst = 1, bits = 32; tst; tst <<= 1, bits--)
|
||||
if (msk & tst)
|
||||
break;
|
||||
|
||||
for (tst <<= 1; tst; tst <<= 1)
|
||||
if (!(msk & tst))
|
||||
break;
|
||||
|
||||
net.sin_addr.s_addr = ihost4->sin_addr.s_addr & mask4->sin_addr.s_addr;
|
||||
strcpy(buf, inet_ntoa(net.sin_addr));
|
||||
for (len = strlen(buf); len > 3; buf[len -= 2] = '\0')
|
||||
if (strcmp(buf + len - 2, ".0"))
|
||||
break;
|
||||
|
||||
if (tst) /* non-contiguous :-( */
|
||||
sprintf(buf + strlen(buf),"&0x%08lx", (u_long)msk);
|
||||
else
|
||||
sprintf(buf + strlen(buf), "/%d", bits);
|
||||
}
|
||||
break;
|
||||
#ifndef NOINET6
|
||||
case AF_INET6:
|
||||
#endif
|
||||
ncprange_setsa(&range, phost, pmask);
|
||||
if (ncprange_isdefault(&range))
|
||||
prompt_Printf(prompt, "%-*s ", width - 1, "default");
|
||||
else
|
||||
prompt_Printf(prompt, "%-*s ", width - 1, ncprange_ntoa(&range));
|
||||
return;
|
||||
|
||||
case AF_LINK:
|
||||
if (dl->sdl_nlen)
|
||||
@ -160,55 +139,6 @@ p_sockaddr(struct prompt *prompt, struct sockaddr *phost,
|
||||
sprintf(buf, "link#%d", dl->sdl_index);
|
||||
break;
|
||||
|
||||
#ifndef NOINET6
|
||||
case AF_INET6:
|
||||
if (!phost)
|
||||
buf[0] = '\0';
|
||||
else {
|
||||
const u_char masks[] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe };
|
||||
struct sockaddr_in6 *ihost6 = (struct sockaddr_in6 *)phost;
|
||||
struct sockaddr_in6 *mask6 = (struct sockaddr_in6 *)pmask;
|
||||
int masklen, len;
|
||||
const u_char *c;
|
||||
|
||||
/* XXX: ?????!?!?!!!!! This is horrible ! */
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&ihost6->sin6_addr) ||
|
||||
IN6_IS_ADDR_MC_LINKLOCAL(&ihost6->sin6_addr)) {
|
||||
ihost6->sin6_scope_id =
|
||||
ntohs(*(u_short *)&ihost6->sin6_addr.s6_addr[2]);
|
||||
*(u_short *)&ihost6->sin6_addr.s6_addr[2] = 0;
|
||||
}
|
||||
|
||||
if (mask6) {
|
||||
const u_char *p, *end;
|
||||
|
||||
p = (const u_char *)&mask6->sin6_addr;
|
||||
end = p + 16;
|
||||
for (masklen = 0, end = p + 16; p < end && *p == 0xff; p++)
|
||||
masklen += 8;
|
||||
|
||||
if (p < end) {
|
||||
for (c = masks; c < masks + sizeof masks; c++)
|
||||
if (*c == *p) {
|
||||
masklen += c - masks;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else
|
||||
masklen = 128;
|
||||
|
||||
if (masklen == 0 && IN6_IS_ADDR_UNSPECIFIED(&ihost6->sin6_addr))
|
||||
snprintf(buf, sizeof buf, "default");
|
||||
else {
|
||||
getnameinfo(phost, ihost6->sin6_len, buf, sizeof buf,
|
||||
NULL, 0, NI_WITHSCOPEID | NI_NUMERICHOST);
|
||||
if (mask6 && (len = strlen(buf)) < sizeof buf - 1)
|
||||
snprintf(buf + len, sizeof buf - len, "/%d", masklen);
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
sprintf(buf, "<AF type %d>", phost->sa_family);
|
||||
break;
|
||||
@ -448,16 +378,13 @@ route_IfDelete(struct bundle *bundle, int all)
|
||||
{
|
||||
struct rt_msghdr *rtm;
|
||||
struct sockaddr *sa[RTAX_MAX];
|
||||
struct sockaddr_in **in;
|
||||
struct in_addr sa_none;
|
||||
struct ncprange range;
|
||||
int pass;
|
||||
size_t needed;
|
||||
char *sp, *cp, *ep;
|
||||
int mib[6];
|
||||
|
||||
log_Printf(LogDEBUG, "route_IfDelete (%d)\n", bundle->iface->index);
|
||||
sa_none.s_addr = INADDR_ANY;
|
||||
in = (struct sockaddr_in **)sa;
|
||||
|
||||
mib[0] = CTL_NET;
|
||||
mib[1] = PF_ROUTE;
|
||||
@ -497,28 +424,37 @@ route_IfDelete(struct bundle *bundle, int all)
|
||||
for (cp = sp; cp < ep; cp += rtm->rtm_msglen) {
|
||||
rtm = (struct rt_msghdr *)cp;
|
||||
route_ParseHdr(rtm, sa);
|
||||
if (sa[RTAX_DST] && sa[RTAX_DST]->sa_family == AF_INET) {
|
||||
log_Printf(LogDEBUG, "route_IfDelete: addrs: %x, Netif: %d (%s),"
|
||||
" flags: %x, dst: %s ?\n", rtm->rtm_addrs, rtm->rtm_index,
|
||||
Index2Nam(rtm->rtm_index), rtm->rtm_flags,
|
||||
inet_ntoa(((struct sockaddr_in *)sa[RTAX_DST])->sin_addr));
|
||||
if (sa[RTAX_GATEWAY] && rtm->rtm_index == bundle->iface->index &&
|
||||
(all || (rtm->rtm_flags & RTF_GATEWAY))) {
|
||||
if (sa[RTAX_GATEWAY]->sa_family == AF_INET ||
|
||||
sa[RTAX_GATEWAY]->sa_family == AF_LINK) {
|
||||
if ((pass == 0 && (rtm->rtm_flags & RTF_WASCLONED)) ||
|
||||
(pass == 1 && !(rtm->rtm_flags & RTF_WASCLONED))) {
|
||||
log_Printf(LogDEBUG, "route_IfDelete: Remove it (pass %d)\n",
|
||||
pass);
|
||||
rt_Set(bundle, RTM_DELETE, in[RTAX_DST]->sin_addr,
|
||||
sa_none, sa_none, 0, 0);
|
||||
} else
|
||||
log_Printf(LogDEBUG, "route_IfDelete: Skip it (pass %d)\n", pass);
|
||||
} else
|
||||
log_Printf(LogDEBUG,
|
||||
"route_IfDelete: Can't remove routes of %d family !\n",
|
||||
sa[RTAX_GATEWAY]->sa_family);
|
||||
if (rtm->rtm_index == bundle->iface->index &&
|
||||
sa[RTAX_DST] && sa[RTAX_GATEWAY] &&
|
||||
(sa[RTAX_DST]->sa_family == AF_INET
|
||||
#ifndef NOINET6
|
||||
|| sa[RTAX_DST]->sa_family == AF_INET6
|
||||
#endif
|
||||
) &&
|
||||
(all || (rtm->rtm_flags & RTF_GATEWAY))) {
|
||||
if (log_IsKept(LogDEBUG)) {
|
||||
char gwstr[41];
|
||||
struct ncpaddr gw;
|
||||
ncprange_setsa(&range, sa[RTAX_DST], sa[RTAX_NETMASK]);
|
||||
ncpaddr_setsa(&gw, sa[RTAX_GATEWAY]);
|
||||
snprintf(gwstr, sizeof gwstr, "%s", ncpaddr_ntoa(&gw));
|
||||
log_Printf(LogDEBUG, "Found %s %s\n", ncprange_ntoa(&range), gwstr);
|
||||
}
|
||||
if (sa[RTAX_GATEWAY]->sa_family == AF_INET ||
|
||||
#ifndef NOINET6
|
||||
sa[RTAX_GATEWAY]->sa_family == AF_INET6 ||
|
||||
#endif
|
||||
sa[RTAX_GATEWAY]->sa_family == AF_LINK) {
|
||||
if ((pass == 0 && (rtm->rtm_flags & RTF_WASCLONED)) ||
|
||||
(pass == 1 && !(rtm->rtm_flags & RTF_WASCLONED))) {
|
||||
ncprange_setsa(&range, sa[RTAX_DST], sa[RTAX_NETMASK]);
|
||||
rt_Set(bundle, RTM_DELETE, &range, NULL, 0, 0);
|
||||
} else
|
||||
log_Printf(LogDEBUG, "route_IfDelete: Skip it (pass %d)\n", pass);
|
||||
} else
|
||||
log_Printf(LogDEBUG,
|
||||
"route_IfDelete: Can't remove routes for family %d\n",
|
||||
sa[RTAX_GATEWAY]->sa_family);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -534,13 +470,12 @@ route_UpdateMTU(struct bundle *bundle)
|
||||
{
|
||||
struct rt_msghdr *rtm;
|
||||
struct sockaddr *sa[RTAX_MAX];
|
||||
struct sockaddr_in **in;
|
||||
struct ncprange dst;
|
||||
size_t needed;
|
||||
char *sp, *cp, *ep;
|
||||
int mib[6];
|
||||
|
||||
log_Printf(LogDEBUG, "route_UpdateMTU (%d)\n", bundle->iface->index);
|
||||
in = (struct sockaddr_in **)sa;
|
||||
|
||||
mib[0] = CTL_NET;
|
||||
mib[1] = PF_ROUTE;
|
||||
@ -578,7 +513,8 @@ route_UpdateMTU(struct bundle *bundle)
|
||||
rtm->rtm_index, Index2Nam(rtm->rtm_index),
|
||||
inet_ntoa(((struct sockaddr_in *)sa[RTAX_DST])->sin_addr),
|
||||
bundle->iface->mtu);
|
||||
rt_Update(bundle, in[RTAX_DST]->sin_addr, in[RTAX_GATEWAY]->sin_addr);
|
||||
ncprange_setsa(&dst, sa[RTAX_DST], sa[RTAX_NETMASK]);
|
||||
rt_Update(bundle, &dst);
|
||||
}
|
||||
}
|
||||
|
||||
@ -602,45 +538,60 @@ GetIfIndex(char *name)
|
||||
|
||||
void
|
||||
route_Change(struct bundle *bundle, struct sticky_route *r,
|
||||
struct in_addr me, struct in_addr peer, struct in_addr dns[2])
|
||||
const struct ncpaddr *me, const struct ncpaddr *peer)
|
||||
{
|
||||
struct in_addr none, del;
|
||||
struct ncpaddr dst;
|
||||
|
||||
none.s_addr = INADDR_ANY;
|
||||
for (; r; r = r->next) {
|
||||
if ((r->type & ROUTE_DSTMYADDR) && r->dst.s_addr != me.s_addr) {
|
||||
del.s_addr = r->dst.s_addr & r->mask.s_addr;
|
||||
rt_Set(bundle, RTM_DELETE, del, none, none, 1, 0);
|
||||
r->dst = me;
|
||||
if (r->type & ROUTE_GWHISADDR)
|
||||
r->gw = peer;
|
||||
} else if ((r->type & ROUTE_DSTHISADDR) && r->dst.s_addr != peer.s_addr) {
|
||||
del.s_addr = r->dst.s_addr & r->mask.s_addr;
|
||||
rt_Set(bundle, RTM_DELETE, del, none, none, 1, 0);
|
||||
r->dst = peer;
|
||||
if (r->type & ROUTE_GWHISADDR)
|
||||
r->gw = peer;
|
||||
} else if ((r->type & ROUTE_DSTDNS0) && r->dst.s_addr != peer.s_addr) {
|
||||
del.s_addr = r->dst.s_addr & r->mask.s_addr;
|
||||
rt_Set(bundle, RTM_DELETE, del, none, none, 1, 0);
|
||||
r->dst = dns[0];
|
||||
if (r->type & ROUTE_GWHISADDR)
|
||||
r->gw = peer;
|
||||
} else if ((r->type & ROUTE_DSTDNS1) && r->dst.s_addr != peer.s_addr) {
|
||||
del.s_addr = r->dst.s_addr & r->mask.s_addr;
|
||||
rt_Set(bundle, RTM_DELETE, del, none, none, 1, 0);
|
||||
r->dst = dns[1];
|
||||
if (r->type & ROUTE_GWHISADDR)
|
||||
r->gw = peer;
|
||||
} else if ((r->type & ROUTE_GWHISADDR) && r->gw.s_addr != peer.s_addr)
|
||||
r->gw = peer;
|
||||
rt_Set(bundle, RTM_ADD, r->dst, r->gw, r->mask, 1, 0);
|
||||
ncprange_getaddr(&r->dst, &dst);
|
||||
if (ncpaddr_family(me) == AF_INET) {
|
||||
if ((r->type & ROUTE_DSTMYADDR) && !ncpaddr_equal(&dst, me)) {
|
||||
rt_Set(bundle, RTM_DELETE, &r->dst, NULL, 1, 0);
|
||||
ncprange_sethost(&r->dst, me);
|
||||
if (r->type & ROUTE_GWHISADDR)
|
||||
ncpaddr_copy(&r->gw, peer);
|
||||
} else if ((r->type & ROUTE_DSTHISADDR) && !ncpaddr_equal(&dst, peer)) {
|
||||
rt_Set(bundle, RTM_DELETE, &r->dst, NULL, 1, 0);
|
||||
ncprange_sethost(&r->dst, peer);
|
||||
if (r->type & ROUTE_GWHISADDR)
|
||||
ncpaddr_copy(&r->gw, peer);
|
||||
} else if ((r->type & ROUTE_DSTDNS0) && !ncpaddr_equal(&dst, peer)) {
|
||||
if (bundle->ncp.ipcp.ns.dns[0].s_addr == INADDR_NONE)
|
||||
continue;
|
||||
rt_Set(bundle, RTM_DELETE, &r->dst, NULL, 1, 0);
|
||||
if (r->type & ROUTE_GWHISADDR)
|
||||
ncpaddr_copy(&r->gw, peer);
|
||||
} else if ((r->type & ROUTE_DSTDNS1) && !ncpaddr_equal(&dst, peer)) {
|
||||
if (bundle->ncp.ipcp.ns.dns[1].s_addr == INADDR_NONE)
|
||||
continue;
|
||||
rt_Set(bundle, RTM_DELETE, &r->dst, NULL, 1, 0);
|
||||
if (r->type & ROUTE_GWHISADDR)
|
||||
ncpaddr_copy(&r->gw, peer);
|
||||
} else if ((r->type & ROUTE_GWHISADDR) && !ncpaddr_equal(&r->gw, peer))
|
||||
ncpaddr_copy(&r->gw, peer);
|
||||
#ifndef NOINET6
|
||||
} else if (ncpaddr_family(me) == AF_INET6) {
|
||||
if ((r->type & ROUTE_DSTMYADDR6) && !ncpaddr_equal(&dst, me)) {
|
||||
rt_Set(bundle, RTM_DELETE, &r->dst, NULL, 1, 0);
|
||||
ncprange_sethost(&r->dst, me);
|
||||
if (r->type & ROUTE_GWHISADDR)
|
||||
ncpaddr_copy(&r->gw, peer);
|
||||
} else if ((r->type & ROUTE_DSTHISADDR6) && !ncpaddr_equal(&dst, peer)) {
|
||||
rt_Set(bundle, RTM_DELETE, &r->dst, NULL, 1, 0);
|
||||
ncprange_sethost(&r->dst, peer);
|
||||
if (r->type & ROUTE_GWHISADDR)
|
||||
ncpaddr_copy(&r->gw, peer);
|
||||
} else if ((r->type & ROUTE_GWHISADDR6) && !ncpaddr_equal(&r->gw, peer))
|
||||
ncpaddr_copy(&r->gw, peer);
|
||||
#endif
|
||||
}
|
||||
rt_Set(bundle, RTM_ADD, &r->dst, &r->gw, 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
route_Add(struct sticky_route **rp, int type, struct in_addr dst,
|
||||
struct in_addr mask, struct in_addr gw)
|
||||
route_Add(struct sticky_route **rp, int type, const struct ncprange *dst,
|
||||
const struct ncpaddr *gw)
|
||||
{
|
||||
struct sticky_route *r;
|
||||
int dsttype = type & ROUTE_DSTANY;
|
||||
@ -648,7 +599,7 @@ route_Add(struct sticky_route **rp, int type, struct in_addr dst,
|
||||
r = NULL;
|
||||
while (*rp) {
|
||||
if ((dsttype && dsttype == ((*rp)->type & ROUTE_DSTANY)) ||
|
||||
(!dsttype && (*rp)->dst.s_addr == dst.s_addr)) {
|
||||
(!dsttype && ncprange_equal(&(*rp)->dst, dst))) {
|
||||
/* Oops, we already have this route - unlink it */
|
||||
free(r); /* impossible really */
|
||||
r = *rp;
|
||||
@ -661,21 +612,19 @@ route_Add(struct sticky_route **rp, int type, struct in_addr dst,
|
||||
r = (struct sticky_route *)malloc(sizeof(struct sticky_route));
|
||||
r->type = type;
|
||||
r->next = NULL;
|
||||
r->dst = dst;
|
||||
r->mask = mask;
|
||||
r->gw = gw;
|
||||
*rp = r;
|
||||
ncprange_copy(&r->dst, dst);
|
||||
ncpaddr_copy(&r->gw, gw);
|
||||
}
|
||||
|
||||
void
|
||||
route_Delete(struct sticky_route **rp, int type, struct in_addr dst)
|
||||
route_Delete(struct sticky_route **rp, int type, const struct ncprange *dst)
|
||||
{
|
||||
struct sticky_route *r;
|
||||
int dsttype = type & ROUTE_DSTANY;
|
||||
|
||||
for (; *rp; rp = &(*rp)->next) {
|
||||
if ((dsttype && dsttype == ((*rp)->type & ROUTE_DSTANY)) ||
|
||||
(!dsttype && dst.s_addr == ((*rp)->dst.s_addr & (*rp)->mask.s_addr))) {
|
||||
(!dsttype && ncprange_equal(dst, &(*rp)->dst))) {
|
||||
r = *rp;
|
||||
*rp = r->next;
|
||||
free(r);
|
||||
@ -700,7 +649,6 @@ void
|
||||
route_ShowSticky(struct prompt *p, struct sticky_route *r, const char *tag,
|
||||
int indent)
|
||||
{
|
||||
int def;
|
||||
int tlen = strlen(tag);
|
||||
|
||||
if (tlen + 2 > indent)
|
||||
@ -709,47 +657,48 @@ route_ShowSticky(struct prompt *p, struct sticky_route *r, const char *tag,
|
||||
prompt_Printf(p, "%s:%*s", tag, indent - tlen - 1, "");
|
||||
|
||||
for (; r; r = r->next) {
|
||||
def = r->dst.s_addr == INADDR_ANY && r->mask.s_addr == INADDR_ANY;
|
||||
|
||||
prompt_Printf(p, "%*sadd ", tlen ? 0 : indent, "");
|
||||
tlen = 0;
|
||||
if (r->type & ROUTE_DSTMYADDR)
|
||||
prompt_Printf(p, "MYADDR");
|
||||
else if (r->type & ROUTE_DSTMYADDR6)
|
||||
prompt_Printf(p, "MYADDR6");
|
||||
else if (r->type & ROUTE_DSTHISADDR)
|
||||
prompt_Printf(p, "HISADDR");
|
||||
else if (r->type & ROUTE_DSTHISADDR6)
|
||||
prompt_Printf(p, "HISADDR6");
|
||||
else if (r->type & ROUTE_DSTDNS0)
|
||||
prompt_Printf(p, "DNS0");
|
||||
else if (r->type & ROUTE_DSTDNS1)
|
||||
prompt_Printf(p, "DNS1");
|
||||
else if (!def)
|
||||
prompt_Printf(p, "%s", inet_ntoa(r->dst));
|
||||
|
||||
if (def)
|
||||
prompt_Printf(p, "default ");
|
||||
else if (ncprange_isdefault(&r->dst))
|
||||
prompt_Printf(p, "default");
|
||||
else
|
||||
prompt_Printf(p, " %s ", inet_ntoa(r->mask));
|
||||
prompt_Printf(p, "%s", ncprange_ntoa(&r->dst));
|
||||
|
||||
if (r->type & ROUTE_GWHISADDR)
|
||||
prompt_Printf(p, "HISADDR\n");
|
||||
prompt_Printf(p, " HISADDR\n");
|
||||
else if (r->type & ROUTE_GWHISADDR6)
|
||||
prompt_Printf(p, " HISADDR6\n");
|
||||
else
|
||||
prompt_Printf(p, "%s\n", inet_ntoa(r->gw));
|
||||
prompt_Printf(p, " %s\n", ncpaddr_ntoa(&r->gw));
|
||||
}
|
||||
}
|
||||
|
||||
struct rtmsg {
|
||||
struct rt_msghdr m_rtm;
|
||||
char m_space[64];
|
||||
char m_space[256];
|
||||
};
|
||||
|
||||
int
|
||||
rt_Set(struct bundle *bundle, int cmd, struct in_addr dst,
|
||||
struct in_addr gateway, struct in_addr mask, int bang, int ssh)
|
||||
rt_Set(struct bundle *bundle, int cmd, const struct ncprange *dst,
|
||||
const struct ncpaddr *gw, int bang, int quiet)
|
||||
{
|
||||
struct rtmsg rtmes;
|
||||
int s, nb, wb;
|
||||
int domask, s, nb, wb, width;
|
||||
char *cp;
|
||||
const char *cmdstr;
|
||||
struct sockaddr_in rtdata;
|
||||
struct sockaddr_storage sadst, samask, sagw;
|
||||
int result = 1;
|
||||
|
||||
if (bang)
|
||||
@ -770,47 +719,50 @@ rt_Set(struct bundle *bundle, int cmd, struct in_addr dst,
|
||||
rtmes.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
|
||||
|
||||
if (cmd == RTM_ADD) {
|
||||
if (bundle->ncp.ipcp.cfg.sendpipe > 0) {
|
||||
rtmes.m_rtm.rtm_rmx.rmx_sendpipe = bundle->ncp.ipcp.cfg.sendpipe;
|
||||
if (bundle->ncp.cfg.sendpipe > 0) {
|
||||
rtmes.m_rtm.rtm_rmx.rmx_sendpipe = bundle->ncp.cfg.sendpipe;
|
||||
rtmes.m_rtm.rtm_inits |= RTV_SPIPE;
|
||||
}
|
||||
if (bundle->ncp.ipcp.cfg.recvpipe > 0) {
|
||||
rtmes.m_rtm.rtm_rmx.rmx_recvpipe = bundle->ncp.ipcp.cfg.recvpipe;
|
||||
if (bundle->ncp.cfg.recvpipe > 0) {
|
||||
rtmes.m_rtm.rtm_rmx.rmx_recvpipe = bundle->ncp.cfg.recvpipe;
|
||||
rtmes.m_rtm.rtm_inits |= RTV_RPIPE;
|
||||
}
|
||||
}
|
||||
|
||||
memset(&rtdata, '\0', sizeof rtdata);
|
||||
rtdata.sin_len = sizeof rtdata;
|
||||
rtdata.sin_family = AF_INET;
|
||||
rtdata.sin_port = 0;
|
||||
rtdata.sin_addr = dst;
|
||||
ncprange_getsa(dst, &sadst, &samask);
|
||||
|
||||
cp = rtmes.m_space;
|
||||
memcpy(cp, &rtdata, rtdata.sin_len);
|
||||
cp += rtdata.sin_len;
|
||||
memcpy(cp, &sadst, sadst.ss_len);
|
||||
cp += sadst.ss_len;
|
||||
if (cmd == RTM_ADD) {
|
||||
if (gateway.s_addr == INADDR_ANY) {
|
||||
if (!ssh)
|
||||
if (gw == NULL) {
|
||||
log_Printf(LogERROR, "rt_Set: Program error\n");
|
||||
close(s);
|
||||
return result;
|
||||
}
|
||||
ncpaddr_getsa(gw, &sagw);
|
||||
if (ncpaddr_isdefault(gw)) {
|
||||
if (!quiet)
|
||||
log_Printf(LogERROR, "rt_Set: Cannot add a route with"
|
||||
" destination 0.0.0.0\n");
|
||||
close(s);
|
||||
return result;
|
||||
} else {
|
||||
rtdata.sin_addr = gateway;
|
||||
memcpy(cp, &rtdata, rtdata.sin_len);
|
||||
cp += rtdata.sin_len;
|
||||
memcpy(cp, &sagw, sagw.ss_len);
|
||||
cp += sagw.ss_len;
|
||||
rtmes.m_rtm.rtm_addrs |= RTA_GATEWAY;
|
||||
}
|
||||
}
|
||||
|
||||
if (dst.s_addr == INADDR_ANY)
|
||||
mask.s_addr = INADDR_ANY;
|
||||
|
||||
if (cmd == RTM_ADD || dst.s_addr == INADDR_ANY) {
|
||||
rtdata.sin_addr = mask;
|
||||
memcpy(cp, &rtdata, rtdata.sin_len);
|
||||
cp += rtdata.sin_len;
|
||||
domask = 1;
|
||||
if (ncprange_family(dst) == AF_INET) {
|
||||
ncprange_getwidth(dst, &width);
|
||||
if (width == 32)
|
||||
domask = 0;
|
||||
}
|
||||
if (domask) {
|
||||
memcpy(cp, &samask, samask.ss_len);
|
||||
cp += samask.ss_len;
|
||||
rtmes.m_rtm.rtm_addrs |= RTA_NETMASK;
|
||||
}
|
||||
|
||||
@ -820,16 +772,15 @@ rt_Set(struct bundle *bundle, int cmd, struct in_addr dst,
|
||||
if (wb < 0) {
|
||||
log_Printf(LogTCPIP, "rt_Set failure:\n");
|
||||
log_Printf(LogTCPIP, "rt_Set: Cmd = %s\n", cmdstr);
|
||||
log_Printf(LogTCPIP, "rt_Set: Dst = %s\n", inet_ntoa(dst));
|
||||
log_Printf(LogTCPIP, "rt_Set: Gateway = %s\n",
|
||||
inet_ntoa(gateway));
|
||||
log_Printf(LogTCPIP, "rt_Set: Mask = %s\n", inet_ntoa(mask));
|
||||
log_Printf(LogTCPIP, "rt_Set: Dst = %s\n", ncprange_ntoa(dst));
|
||||
if (gw != NULL)
|
||||
log_Printf(LogTCPIP, "rt_Set: Gateway = %s\n", ncpaddr_ntoa(gw));
|
||||
failed:
|
||||
if (cmd == RTM_ADD && (rtmes.m_rtm.rtm_errno == EEXIST ||
|
||||
(rtmes.m_rtm.rtm_errno == 0 && errno == EEXIST))) {
|
||||
if (!bang) {
|
||||
log_Printf(LogWARN, "Add route failed: %s already exists\n",
|
||||
dst.s_addr == 0 ? "default" : inet_ntoa(dst));
|
||||
ncprange_ntoa(dst));
|
||||
result = 0; /* Don't add to our dynamic list */
|
||||
} else {
|
||||
rtmes.m_rtm.rtm_type = cmd = RTM_CHANGE;
|
||||
@ -841,29 +792,37 @@ rt_Set(struct bundle *bundle, int cmd, struct in_addr dst,
|
||||
(rtmes.m_rtm.rtm_errno == 0 && errno == ESRCH))) {
|
||||
if (!bang)
|
||||
log_Printf(LogWARN, "Del route failed: %s: Non-existent\n",
|
||||
inet_ntoa(dst));
|
||||
ncprange_ntoa(dst));
|
||||
} else if (rtmes.m_rtm.rtm_errno == 0) {
|
||||
if (!ssh || errno != ENETUNREACH)
|
||||
if (!quiet || errno != ENETUNREACH)
|
||||
log_Printf(LogWARN, "%s route failed: %s: errno: %s\n", cmdstr,
|
||||
inet_ntoa(dst), strerror(errno));
|
||||
ncprange_ntoa(dst), strerror(errno));
|
||||
} else
|
||||
log_Printf(LogWARN, "%s route failed: %s: %s\n",
|
||||
cmdstr, inet_ntoa(dst), strerror(rtmes.m_rtm.rtm_errno));
|
||||
cmdstr, ncprange_ntoa(dst), strerror(rtmes.m_rtm.rtm_errno));
|
||||
}
|
||||
|
||||
log_Printf(LogDEBUG, "wrote %d: cmd = %s, dst = %x, gateway = %x\n",
|
||||
wb, cmdstr, (unsigned)dst.s_addr, (unsigned)gateway.s_addr);
|
||||
if (log_IsKept(LogDEBUG)) {
|
||||
char gwstr[40];
|
||||
|
||||
if (gw)
|
||||
snprintf(gwstr, sizeof gwstr, "%s", ncpaddr_ntoa(gw));
|
||||
else
|
||||
snprintf(gwstr, sizeof gwstr, "<none>");
|
||||
log_Printf(LogDEBUG, "wrote %d: cmd = %s, dst = %s, gateway = %s\n",
|
||||
wb, cmdstr, ncprange_ntoa(dst), gwstr);
|
||||
}
|
||||
close(s);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
rt_Update(struct bundle *bundle, struct in_addr dst, struct in_addr gw)
|
||||
rt_Update(struct bundle *bundle, const struct ncprange *dst)
|
||||
{
|
||||
struct rtmsg rtmes;
|
||||
int s, wb;
|
||||
struct sockaddr_in rtdata;
|
||||
struct sockaddr_storage sadst, samask;
|
||||
|
||||
s = ID0socket(PF_ROUTE, SOCK_RAW, 0);
|
||||
if (s < 0) {
|
||||
@ -879,42 +838,39 @@ rt_Update(struct bundle *bundle, struct in_addr dst, struct in_addr gw)
|
||||
rtmes.m_rtm.rtm_pid = getpid();
|
||||
rtmes.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
|
||||
|
||||
if (bundle->ncp.ipcp.cfg.sendpipe > 0) {
|
||||
rtmes.m_rtm.rtm_rmx.rmx_sendpipe = bundle->ncp.ipcp.cfg.sendpipe;
|
||||
if (bundle->ncp.cfg.sendpipe > 0) {
|
||||
rtmes.m_rtm.rtm_rmx.rmx_sendpipe = bundle->ncp.cfg.sendpipe;
|
||||
rtmes.m_rtm.rtm_inits |= RTV_SPIPE;
|
||||
}
|
||||
|
||||
if (bundle->ncp.ipcp.cfg.recvpipe > 0) {
|
||||
rtmes.m_rtm.rtm_rmx.rmx_recvpipe = bundle->ncp.ipcp.cfg.recvpipe;
|
||||
if (bundle->ncp.cfg.recvpipe > 0) {
|
||||
rtmes.m_rtm.rtm_rmx.rmx_recvpipe = bundle->ncp.cfg.recvpipe;
|
||||
rtmes.m_rtm.rtm_inits |= RTV_RPIPE;
|
||||
}
|
||||
|
||||
rtmes.m_rtm.rtm_rmx.rmx_mtu = bundle->iface->mtu;
|
||||
rtmes.m_rtm.rtm_inits |= RTV_MTU;
|
||||
|
||||
memset(&rtdata, '\0', sizeof rtdata);
|
||||
rtdata.sin_len = sizeof rtdata;
|
||||
rtdata.sin_family = AF_INET;
|
||||
rtdata.sin_port = 0;
|
||||
rtdata.sin_addr = dst;
|
||||
ncprange_getsa(dst, &sadst, &samask);
|
||||
|
||||
memcpy(rtmes.m_space, &rtdata, rtdata.sin_len);
|
||||
rtmes.m_rtm.rtm_msglen = rtmes.m_space + rtdata.sin_len - (char *)&rtmes;
|
||||
memcpy(rtmes.m_space, &sadst, sadst.ss_len);
|
||||
memcpy(rtmes.m_space + sadst.ss_len, &samask, samask.ss_len);
|
||||
rtmes.m_rtm.rtm_msglen = rtmes.m_space - (char *)&rtmes;
|
||||
rtmes.m_rtm.rtm_msglen+= sadst.ss_len + samask.ss_len;
|
||||
|
||||
wb = ID0write(s, &rtmes, rtmes.m_rtm.rtm_msglen);
|
||||
if (wb < 0) {
|
||||
log_Printf(LogTCPIP, "rt_Update failure:\n");
|
||||
log_Printf(LogTCPIP, "rt_Update: Dst = %s\n", inet_ntoa(dst));
|
||||
log_Printf(LogTCPIP, "rt_Update: Gateway = %s\n", inet_ntoa(gw));
|
||||
log_Printf(LogTCPIP, "rt_Update: Dst = %s\n", ncprange_ntoa(dst));
|
||||
|
||||
if (rtmes.m_rtm.rtm_errno == 0)
|
||||
log_Printf(LogWARN, "%s: Change route failed: errno: %s\n",
|
||||
inet_ntoa(dst), strerror(errno));
|
||||
ncprange_ntoa(dst), strerror(errno));
|
||||
else
|
||||
log_Printf(LogWARN, "%s: Change route failed: %s\n",
|
||||
inet_ntoa(dst), strerror(rtmes.m_rtm.rtm_errno));
|
||||
ncprange_ntoa(dst), strerror(rtmes.m_rtm.rtm_errno));
|
||||
}
|
||||
log_Printf(LogDEBUG, "wrote %d: cmd = Change, dst = %x, gateway = %x\n",
|
||||
wb, (unsigned)dst.s_addr, (unsigned)gw.s_addr);
|
||||
log_Printf(LogDEBUG, "wrote %d: cmd = Change, dst = %s\n",
|
||||
wb, ncprange_ntoa(dst));
|
||||
close(s);
|
||||
}
|
||||
|
@ -33,21 +33,23 @@ struct cmdargs;
|
||||
struct rt_msghdr;
|
||||
struct sockaddr;
|
||||
|
||||
#define ROUTE_STATIC 0x00
|
||||
#define ROUTE_DSTMYADDR 0x01
|
||||
#define ROUTE_DSTHISADDR 0x02
|
||||
#define ROUTE_DSTDNS0 0x04
|
||||
#define ROUTE_DSTDNS1 0x08
|
||||
#define ROUTE_DSTANY 0x0f
|
||||
#define ROUTE_GWHISADDR 0x10 /* May be ORd with DST_* */
|
||||
#define ROUTE_STATIC 0x0000
|
||||
#define ROUTE_DSTMYADDR 0x0001
|
||||
#define ROUTE_DSTMYADDR6 0x0002
|
||||
#define ROUTE_DSTHISADDR 0x0004
|
||||
#define ROUTE_DSTHISADDR6 0x0008
|
||||
#define ROUTE_DSTDNS0 0x0010
|
||||
#define ROUTE_DSTDNS1 0x0020
|
||||
#define ROUTE_DSTANY 0x0040
|
||||
#define ROUTE_GWHISADDR 0x0080 /* May be ORd with DST_* */
|
||||
#define ROUTE_GWHISADDR6 0x0100 /* May be ORd with DST_* */
|
||||
|
||||
struct sticky_route {
|
||||
int type; /* ROUTE_* value (not _STATIC) */
|
||||
struct sticky_route *next; /* next in list */
|
||||
|
||||
struct in_addr dst;
|
||||
struct in_addr mask;
|
||||
struct in_addr gw;
|
||||
struct ncprange dst;
|
||||
struct ncpaddr gw;
|
||||
};
|
||||
|
||||
extern int GetIfIndex(char *);
|
||||
@ -56,15 +58,15 @@ extern void route_IfDelete(struct bundle *, int);
|
||||
extern void route_UpdateMTU(struct bundle *);
|
||||
extern const char *Index2Nam(int);
|
||||
extern void route_Change(struct bundle *, struct sticky_route *,
|
||||
struct in_addr, struct in_addr, struct in_addr[2]);
|
||||
extern void route_Add(struct sticky_route **, int, struct in_addr,
|
||||
struct in_addr, struct in_addr);
|
||||
extern void route_Delete(struct sticky_route **, int, struct in_addr);
|
||||
const struct ncpaddr *, const struct ncpaddr *);
|
||||
extern void route_Add(struct sticky_route **, int, const struct ncprange *,
|
||||
const struct ncpaddr *);
|
||||
extern void route_Delete(struct sticky_route **, int, const struct ncprange *);
|
||||
extern void route_DeleteAll(struct sticky_route **);
|
||||
extern void route_Clean(struct bundle *, struct sticky_route *);
|
||||
extern void route_ShowSticky(struct prompt *, struct sticky_route *,
|
||||
const char *, int);
|
||||
extern void route_ParseHdr(struct rt_msghdr *, struct sockaddr *[RTAX_MAX]);
|
||||
extern int rt_Set(struct bundle *, int, struct in_addr,
|
||||
struct in_addr, struct in_addr, int, int);
|
||||
extern void rt_Update(struct bundle *, struct in_addr, struct in_addr);
|
||||
extern int rt_Set(struct bundle *, int, const struct ncprange *,
|
||||
const struct ncpaddr *, int, int);
|
||||
extern void rt_Update(struct bundle *, const struct ncprange *);
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "server.h"
|
||||
#include "id.h"
|
||||
#include "prompt.h"
|
||||
#include "ncpaddr.h"
|
||||
|
||||
static int
|
||||
server_UpdateSet(struct fdescriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n)
|
||||
@ -84,19 +85,19 @@ server_IsSet(struct fdescriptor *d, const fd_set *fdset)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define IN_SIZE sizeof(struct sockaddr_in)
|
||||
#define UN_SIZE sizeof(struct sockaddr_un)
|
||||
#define ADDRSZ (IN_SIZE > UN_SIZE ? IN_SIZE : UN_SIZE)
|
||||
|
||||
static void
|
||||
server_Read(struct fdescriptor *d, struct bundle *bundle, const fd_set *fdset)
|
||||
{
|
||||
struct server *s = descriptor2server(d);
|
||||
char hisaddr[ADDRSZ];
|
||||
struct sockaddr *sa = (struct sockaddr *)hisaddr;
|
||||
struct sockaddr_in *in = (struct sockaddr_in *)hisaddr;
|
||||
int ssize = ADDRSZ, wfd;
|
||||
struct sockaddr_storage ss;
|
||||
struct sockaddr *sa = (struct sockaddr *)&ss;
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *)&ss;
|
||||
#ifndef NOINET6
|
||||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss;
|
||||
#endif
|
||||
int ssize = sizeof ss, wfd;
|
||||
struct prompt *p;
|
||||
struct ncpaddr addr;
|
||||
|
||||
if (s->fd >= 0 && FD_ISSET(s->fd, fdset)) {
|
||||
wfd = accept(s->fd, sa, &ssize);
|
||||
@ -116,18 +117,35 @@ server_Read(struct fdescriptor *d, struct bundle *bundle, const fd_set *fdset)
|
||||
break;
|
||||
|
||||
case AF_INET:
|
||||
if (ntohs(in->sin_port) < 1024) {
|
||||
ncpaddr_setsa(&addr, sa);
|
||||
if (ntohs(sin->sin_port) < 1024) {
|
||||
log_Printf(LogALERT, "Rejected client connection from %s:%u"
|
||||
"(invalid port number) !\n",
|
||||
inet_ntoa(in->sin_addr), ntohs(in->sin_port));
|
||||
ncpaddr_ntoa(&addr), ntohs(sin->sin_port));
|
||||
close(wfd);
|
||||
wfd = -1;
|
||||
break;
|
||||
}
|
||||
log_Printf(LogPHASE, "Connected to client from %s:%u\n",
|
||||
inet_ntoa(in->sin_addr), in->sin_port);
|
||||
ncpaddr_ntoa(&addr), ntohs(sin->sin_port));
|
||||
break;
|
||||
|
||||
#ifndef NOINET6
|
||||
case AF_INET6:
|
||||
ncpaddr_setsa(&addr, sa);
|
||||
if (ntohs(sin6->sin6_port) < 1024) {
|
||||
log_Printf(LogALERT, "Rejected client connection from %s:%u"
|
||||
"(invalid port number) !\n",
|
||||
ncpaddr_ntoa(&addr), ntohs(sin6->sin6_port));
|
||||
close(wfd);
|
||||
wfd = -1;
|
||||
break;
|
||||
}
|
||||
log_Printf(LogPHASE, "Connected to client from %s:%u\n",
|
||||
ncpaddr_ntoa(&addr), ntohs(sin6->sin6_port));
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
write(wfd, "Unrecognised access !\n", 22);
|
||||
close(wfd);
|
||||
@ -147,10 +165,17 @@ server_Read(struct fdescriptor *d, struct bundle *bundle, const fd_set *fdset)
|
||||
p->src.from[sizeof p->src.from - 1] = '\0';
|
||||
break;
|
||||
case AF_INET:
|
||||
p->src.type = "tcp";
|
||||
p->src.type = "ip";
|
||||
snprintf(p->src.from, sizeof p->src.from, "%s:%u",
|
||||
inet_ntoa(in->sin_addr), in->sin_port);
|
||||
ncpaddr_ntoa(&addr), ntohs(sin->sin_port));
|
||||
break;
|
||||
#ifndef NOINET6
|
||||
case AF_INET6:
|
||||
p->src.type = "ip6";
|
||||
snprintf(p->src.from, sizeof p->src.from, "%s:%u",
|
||||
ncpaddr_ntoa(&addr), ntohs(sin6->sin6_port));
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
prompt_TtyCommandMode(p);
|
||||
prompt_Required(p);
|
||||
@ -282,8 +307,13 @@ server_LocalOpen(struct bundle *bundle, const char *name, mode_t mask)
|
||||
enum server_stat
|
||||
server_TcpOpen(struct bundle *bundle, u_short port)
|
||||
{
|
||||
struct sockaddr_in ifsin;
|
||||
int s;
|
||||
struct sockaddr_storage ss;
|
||||
#ifdef NOINET6
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *)&ss;
|
||||
#else
|
||||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss;
|
||||
#endif
|
||||
int s, sz;
|
||||
|
||||
if (server.cfg.port == port)
|
||||
server_Close(bundle);
|
||||
@ -291,17 +321,28 @@ server_TcpOpen(struct bundle *bundle, u_short port)
|
||||
if (port == 0)
|
||||
return SERVER_INVALID;
|
||||
|
||||
memset(&ss, '\0', sizeof ss);
|
||||
#ifdef NOINET6
|
||||
sin->sin_family = AF_INET;
|
||||
sin->sin_port = htons(port);
|
||||
sin->sin_len = sizeof ss;
|
||||
sin->sin_addr.s_addr = INADDR_ANY;
|
||||
sz = sizeof *sin;
|
||||
s = socket(PF_INET, SOCK_STREAM, 0);
|
||||
#else
|
||||
sin6->sin6_family = AF_INET6;
|
||||
sin6->sin6_port = htons(port);
|
||||
sin6->sin6_len = sizeof ss;
|
||||
sz = sizeof *sin6;
|
||||
s = socket(PF_INET6, SOCK_STREAM, 0);
|
||||
#endif
|
||||
if (s < 0) {
|
||||
log_Printf(LogERROR, "Tcp: socket: %s\n", strerror(errno));
|
||||
goto failed;
|
||||
}
|
||||
memset(&ifsin, '\0', sizeof ifsin);
|
||||
ifsin.sin_family = AF_INET;
|
||||
ifsin.sin_addr.s_addr = INADDR_ANY;
|
||||
ifsin.sin_port = htons(port);
|
||||
|
||||
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s);
|
||||
if (bind(s, (struct sockaddr *)&ifsin, sizeof ifsin) < 0) {
|
||||
if (bind(s, (struct sockaddr *)&ss, sz) < 0) {
|
||||
log_Printf(LogWARN, "Tcp: bind: %s\n", strerror(errno));
|
||||
close(s);
|
||||
goto failed;
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <stdio.h>
|
||||
@ -48,6 +49,8 @@
|
||||
#include "iplist.h"
|
||||
#include "lqr.h"
|
||||
#include "hdlc.h"
|
||||
#include "ncpaddr.h"
|
||||
#include "ip.h"
|
||||
#include "ipcp.h"
|
||||
#include "filter.h"
|
||||
#include "lcp.h"
|
||||
@ -57,6 +60,8 @@
|
||||
#ifndef NORADIUS
|
||||
#include "radius.h"
|
||||
#endif
|
||||
#include "ipv6cp.h"
|
||||
#include "ncp.h"
|
||||
#include "bundle.h"
|
||||
|
||||
void
|
||||
|
@ -52,6 +52,8 @@
|
||||
#include "link.h"
|
||||
#include "iplist.h"
|
||||
#include "slcompress.h"
|
||||
#include "ncpaddr.h"
|
||||
#include "ip.h"
|
||||
#include "ipcp.h"
|
||||
#include "filter.h"
|
||||
#include "descriptor.h"
|
||||
@ -60,6 +62,8 @@
|
||||
#ifndef NORADIUS
|
||||
#include "radius.h"
|
||||
#endif
|
||||
#include "ipv6cp.h"
|
||||
#include "ncp.h"
|
||||
#include "bundle.h"
|
||||
|
||||
|
||||
|
@ -63,6 +63,8 @@
|
||||
#include "throughput.h"
|
||||
#include "iplist.h"
|
||||
#include "slcompress.h"
|
||||
#include "ncpaddr.h"
|
||||
#include "ip.h"
|
||||
#include "ipcp.h"
|
||||
#include "filter.h"
|
||||
#include "descriptor.h"
|
||||
@ -74,6 +76,8 @@
|
||||
#ifndef NORADIUS
|
||||
#include "radius.h"
|
||||
#endif
|
||||
#include "ipv6cp.h"
|
||||
#include "ncp.h"
|
||||
#include "bundle.h"
|
||||
#include "tun.h"
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <stdio.h>
|
||||
@ -50,6 +51,8 @@
|
||||
#include "defs.h"
|
||||
#include "iplist.h"
|
||||
#include "throughput.h"
|
||||
#include "ncpaddr.h"
|
||||
#include "ip.h"
|
||||
#include "ipcp.h"
|
||||
#include "lcp.h"
|
||||
#include "ccp.h"
|
||||
@ -60,6 +63,8 @@
|
||||
#ifndef NORADIUS
|
||||
#include "radius.h"
|
||||
#endif
|
||||
#include "ipv6cp.h"
|
||||
#include "ncp.h"
|
||||
#include "bundle.h"
|
||||
#include "vjcomp.h"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user