freebsd-skq/usr.sbin/ppp/iplist.c
Brian Somers bcc332bdb0 Allow random IP number allocation to peer.
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.
1997-12-13 02:37:33 +00:00

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;
}