bcc332bdb0
Validate the peers suggested IP by attempting to make a routing table entry. Give up IPCP negotiation if the peer NAKs us with an unusable IP. Always SIOCDIFADDR then SIOCAIFADDR when configuring the tun device. Using SIOCSIFDSTADDR allows duplicate dst addresses (which we don't want)!!! Allow up to 200 interface names (was 50) (now that ppp can play server properly). Up the version number (1.5 -> 1.6). Cosmetic: Log unexpected CCP packets in the CCP log rather than the ERROR log. Log unexpected Config Reqs in the appropriate LCP/IPCP/CCP log rather than the ERROR log. Log failed route additions and deletions with WARN, not TCPIP. Log the option id and length for unrecognised IPCP options. Change some .Sq to .Ar in the man page.
201 lines
4.1 KiB
C
201 lines
4.1 KiB
C
/*
|
|
* $Id:$
|
|
*/
|
|
|
|
#include <sys/types.h>
|
|
#include <netinet/in.h>
|
|
#include <arpa/inet.h>
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "command.h"
|
|
#include "mbuf.h"
|
|
#include "log.h"
|
|
#include "defs.h"
|
|
#include "iplist.h"
|
|
|
|
static int
|
|
do_inet_aton(const char *start, const char *end, struct in_addr *ip)
|
|
{
|
|
static char ipstr[16];
|
|
|
|
if (end - start > 15) {
|
|
LogPrintf(LogWARN, "%.*s: Invalid IP address\n", end-start, start);
|
|
return 0;
|
|
}
|
|
strncpy(ipstr, start, end-start);
|
|
ipstr[end-start] = '\0';
|
|
return inet_aton(ipstr, ip);
|
|
}
|
|
|
|
static void
|
|
iplist_first(struct iplist *list)
|
|
{
|
|
list->cur.pos = -1;
|
|
}
|
|
|
|
static int
|
|
iplist_setrange(struct iplist *list, char *range)
|
|
{
|
|
char *ptr, *to;
|
|
|
|
if ((ptr = strpbrk(range, ",-")) == NULL) {
|
|
if (!inet_aton(range, &list->cur.ip))
|
|
return 0;
|
|
list->cur.lstart = ntohl(list->cur.ip.s_addr);
|
|
list->cur.nItems = 1;
|
|
} else {
|
|
if (!do_inet_aton(range, ptr, &list->cur.ip))
|
|
return 0;
|
|
if (*ptr == ',') {
|
|
list->cur.lstart = ntohl(list->cur.ip.s_addr);
|
|
list->cur.nItems = 1;
|
|
} else {
|
|
struct in_addr endip;
|
|
|
|
to = ptr+1;
|
|
if ((ptr = strpbrk(to, ",-")) == NULL)
|
|
ptr = to + strlen(to);
|
|
if (*to == '-')
|
|
return 0;
|
|
if (!do_inet_aton(to, ptr, &endip))
|
|
return 0;
|
|
list->cur.lstart = ntohl(list->cur.ip.s_addr);
|
|
list->cur.nItems = ntohl(endip.s_addr) - list->cur.lstart + 1;
|
|
if (list->cur.nItems < 1)
|
|
return 0;
|
|
}
|
|
}
|
|
list->cur.srcitem = 0;
|
|
list->cur.srcptr = range;
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
iplist_nextrange(struct iplist *list)
|
|
{
|
|
char *ptr, *to, *end;
|
|
|
|
ptr = list->cur.srcptr;
|
|
if (ptr != NULL && (ptr = strchr(ptr, ',')) != NULL)
|
|
ptr++;
|
|
else
|
|
ptr = list->src;
|
|
|
|
while (*ptr != '\0' && !iplist_setrange(list, ptr)) {
|
|
if ((end = strchr(ptr, ',')) == NULL)
|
|
end = ptr + strlen(ptr);
|
|
if (end == ptr)
|
|
return 0;
|
|
LogPrintf(LogWARN, "%.*s: Invalid IP range (skipping)\n", end - ptr, ptr);
|
|
to = ptr;
|
|
do
|
|
*to = *end++;
|
|
while (*to++ != '\0');
|
|
if (*ptr == '\0')
|
|
ptr = list->src;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
struct in_addr
|
|
iplist_next(struct iplist *list)
|
|
{
|
|
if (list->cur.pos == -1) {
|
|
list->cur.srcptr = NULL;
|
|
if (!iplist_nextrange(list)) {
|
|
list->cur.ip.s_addr = INADDR_ANY;
|
|
return list->cur.ip;
|
|
}
|
|
} else if (++list->cur.srcitem == list->cur.nItems) {
|
|
if (!iplist_nextrange(list)) {
|
|
list->cur.ip.s_addr = INADDR_ANY;
|
|
list->cur.pos = -1;
|
|
return list->cur.ip;
|
|
}
|
|
} else
|
|
list->cur.ip.s_addr = htonl(list->cur.lstart + list->cur.srcitem);
|
|
list->cur.pos++;
|
|
|
|
return list->cur.ip;
|
|
}
|
|
|
|
int
|
|
iplist_setsrc(struct iplist *list, const char *src)
|
|
{
|
|
strncpy(list->src, src, sizeof(list->src));
|
|
list->src[sizeof(list->src)-1] = '\0';
|
|
list->cur.srcptr = list->src;
|
|
do {
|
|
if (iplist_nextrange(list))
|
|
list->nItems += list->cur.nItems;
|
|
else
|
|
return 0;
|
|
} while (list->cur.srcptr != list->src);
|
|
return 1;
|
|
}
|
|
|
|
void
|
|
iplist_reset(struct iplist *list)
|
|
{
|
|
list->src[0] = '\0';
|
|
list->nItems = 0;
|
|
list->cur.pos = -1;
|
|
}
|
|
|
|
struct in_addr
|
|
iplist_setcurpos(struct iplist *list, int pos)
|
|
{
|
|
if (pos < 0 || pos >= list->nItems) {
|
|
list->cur.pos = -1;
|
|
list->cur.ip.s_addr = INADDR_ANY;
|
|
return list->cur.ip;
|
|
}
|
|
|
|
list->cur.srcptr = NULL;
|
|
list->cur.pos = 0;
|
|
while (1) {
|
|
iplist_nextrange(list);
|
|
if (pos < list->cur.nItems) {
|
|
if (pos) {
|
|
list->cur.srcitem = pos;
|
|
list->cur.pos += pos;
|
|
list->cur.ip.s_addr = htonl(list->cur.lstart + list->cur.srcitem);
|
|
}
|
|
break;
|
|
}
|
|
pos -= list->cur.nItems;
|
|
list->cur.pos += list->cur.nItems;
|
|
}
|
|
|
|
return list->cur.ip;
|
|
}
|
|
|
|
struct in_addr
|
|
iplist_setrandpos(struct iplist *list)
|
|
{
|
|
randinit();
|
|
return iplist_setcurpos(list, random() % list->nItems);
|
|
}
|
|
|
|
int
|
|
iplist_ip2pos(struct iplist *list, struct in_addr ip)
|
|
{
|
|
struct iplist_cur cur;
|
|
int f, result;
|
|
|
|
result = -1;
|
|
memcpy(&cur, &list->cur, sizeof(cur));
|
|
|
|
for (iplist_first(list), f = 0; f < list->nItems; f++)
|
|
if (iplist_next(list).s_addr == ip.s_addr) {
|
|
result = list->cur.pos;
|
|
break;
|
|
}
|
|
|
|
memcpy(&list->cur, &cur, sizeof(list->cur));
|
|
return result;
|
|
}
|