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