Pantek Library
Hosting Provided By
CybrHost
High Speed Hosting

Re: linux-ipsec: apps/utils/libs that parse IP/netbits

From: Henry Spencer <henry(at)spsystems.net>
Date: Fri Jul 17 1998 - 12:22:06 EDT


Enclosed, for your enjoyment or otherwise :-), is the latest in the saga of atosubnet() and friends. It's been mutating somewhat in the last few days. It now has a manual page, and facilities for building a proper library; this is very likely to become a new "lib" subdirectory of the FreeS/WAN distribution, and some of the filenames have been chosen with that in mind.

Comments are still very much welcome.

                                                          Henry Spencer
                                                       henry@spsystems.net
                                                     (henry@zoo.toronto.edu)

#! /bin/sh
echo 'Makefile':
sed 's/^X//' >'Makefile' <<'!'
X# FreeS/WAN library
XOBJS=atosubnet.o subnettoa.o
XLIB=libfreeswan.a
XCFLAGS=-O3 -fomit-frame-pointer
XARFLAGS=crvs
X
XSHELL=/bin/sh
X
Xall: $(LIB)
X

X$(LIB):	$(OBJS)
X	ar $(ARFLAGS) $(LIB) $(OBJS)
X
X$(OBJS):	freeswan.h internal.h

X
Xclean:
X rm -f $(LIB) *.o try try.? core *.core X
X
X
X# developer-only stuff
Xl:
X	$(MAKE) $(LIB) ARFLAGS=crv CFLAGS=-O
X	ranlib $(LIB)
X
Xsnt:	$(LIB)
X	cp atosubnet.c try.c
X	cc -DATOSUBNET_MAIN try.c $(LIB) -o try
X	./try -r

!

echo 'atosubnet.3':
sed 's/^X//' >'atosubnet.3' <<'!'
X.TH ATOSUBNET 3 "17 July 1998"
X.SH NAME
Xatosubnet, atoaddrmask, subnettoa \- convert net/mask ASCII form to and from addresses
X.SH SYNOPSIS
X.B "#include "
X.br
X.B "#include "
X.br
X.B "#include 
X.sp
X.B "int atosubnet(const char *src, size_t srclen, struct in_addr *addr, struct in_addr *mask);"
X.br
X.B "int atoaddrmask(char *src, struct in_addr *addr, struct in_addr *mask);"
X.br
X.B "int subnettoa(struct in_addr addr, struct in_addr mask, char *dst, size_t dstlen);"
X.SH DESCRIPTION
X.I Atosubnet

Xconverts a network specification (network number and subnet mask) Xfrom an ASCII string to a binary address and mask (in network Xbyte order).
X.I Atoaddrmask
Xdoes the same thing, with a more restrictive interface and a bit less Xhelpfulness.
X.I Subnettoa
Xdoes the reverse conversion, back to a human-readable form. X.PP
XA network specification is of the form \fInetwork\fB/\fImask\fR. XThe \fInetwork\fR can be a four-component dotted-quad address (e.g. X.BR 1.2.3.4 )
Xor a DNS name to be looked up via
X.IR gethostbyname (3)
X(the
X.I h_addr
Xvalue returned by that function is used). XThe \fImask\fR can be either of those two forms, Xor a decimal integer giving a bit count, in which case Xit stands for a mask with that number of high bits on and all others off X(e.g.,
X.B 24
Xmeans
X.BR 255.255.255.0 ).
X.PP
XThe
X.I srclen
Xparameter of
X.I atosubnet
Xspecifies the length of the ASCII string pointed to by X.IR src ,
Xnot including any terminating NUL.
XAs a convenience for cases where an entire NUL-terminated string is Xto be converted,
Xa
X.I srclen
Xvalue of
X.B 0
Xis taken to mean
X.BR strlen(src) .
X.I Atosubnet
XANDs the mask with the address before returning, Xso that any non-network bits in the address are turned off. X.PP
X.I Atoaddrmask
Xprovides a more primitive interface to the same conversion. XThe string pointed to by its
X.I src
Xparameter must be NUL-terminated and in writable memory, and is destroyed by X.IR atoaddrmask .
X.I Atoaddrmask
Xdoes not do the ANDing of the mask with the address, Xso the two can be unrelated (should you be so perverse as to want Xsuch a thing).
X.PP
XThe
X.I dstlen
Xparameter of
X.I subnettoa
Xspecifies the size of its
X.I dst
Xparameter;
Xunder no circumstances are more than
X.I dstlen
Xbytes written to
X.IR dst .
XIt is an error for there not to be enough room. XThe
X.I freeswan.h
Xheader file defines a constant,
X.BR SUBNETTOA_BUF ,
Xwhich is the size of a buffer just large enough for a worst-case result. X.PP
X.I Subnettoa
Xdoes not attempt to do DNS reverse lookups; Xits results are always numeric.
XIt uses the decimal-integer-bit-count
Xform of the mask unless the mask does not fit that form X(i.e. its on bits are not contiguous).
X.PP
XAll these functions return
X.B 0
Xfor success and
X.B \-1
Xfor failure (see DIAGNOSTICS).
X.SH SEE ALSO
Xinet(3)
X.SH DIAGNOSTICS
XFatal errors in
X.I atosubnet
Xare:
Xno
X.B /
Xin
X.IR src ;
Xunable to convert a numeric address or look up a non-numeric one; Xbit-count mask too big;
Xunable to allocate adequate temporary storage for a copy of a long input. XFatal errors in
X.I atoaddrmask
Xare the same except that no temporary storage is ever allocated. XThe only fatal error in
X.I subnettoa
Xis running out of room in
X.IR dst .
X.SH HISTORY
XWritten for the FreeS/WAN project by Henry Spencer. X.SH BUGS
XArguably,
X.I atosubnet
Xand
X.I atoaddrmask
Xshould accept (e.g.)
X.B 10/24
Xas synonymous with
X.BR 10.0.0.0/24 ,
Xbut that creates difficulties,
Xbecause the
X.IR inet (3)
Xfunctions used for the actual conversion think that X.B 10
Xmeans
X.B 0.0.0.10
Xinstead.
X.PP
XMore detailed error reporting would be nice.
!

echo 'atosubnet.c':
sed 's/^X//' >'atosubnet.c' <<'!'
X#include 
X#include 
X#include 
X#include 
X#include 
X#include "freeswan.h"
X#include "internal.h"

X
X/*
X - atosubnet - convert ASCII "addr/mask" to address and mask
X * Mask can be either dotted quad or integer bit count.
X * Results are in network byte order.
X */
Xint				/* 0 success, -1 failure */

Xatosubnet(src, srclen, addrp, maskp)
Xconst char *src;
Xsize_t srclen; /* 0 means "apply strlen" */ Xstruct in_addr *addrp;
Xstruct in_addr *maskp;
X{
X	int i;
X#	ifndef SAVESIZE
X#	define	SAVESIZE	100	/* should usually be enough */
X#	endif
X	char buf[SAVESIZE];	
X	char *p = buf;
X
X	if (srclen == 0)
X		srclen = strlen(src);
X
X	if (srclen+1 > sizeof(buf)) {
X		p = (char *)MALLOC(srclen+1);
X		if (p == NULL)
X			return -1;
X	}
X
X	strncpy(p, src, srclen);
X	p[srclen] = '\0';
X
X	i = atoaddrmask(p, addrp, maskp);
X	addrp->s_addr &= maskp->s_addr;
X
X	if (p != buf)
X		FREE((void *)p);
X
X	return i;

X}
X
X/*
X - atoaddrmask - like atosubnet, more restrictive interface, doesn't do ANDs X */
Xint /* 0 success, -1 failure */
Xatoaddrmask(s, addrp, maskp)
Xchar *s; /* destroyed */
Xstruct in_addr *addrp;
Xstruct in_addr *maskp;
X{
X	char *slash;
X	char *mask;
X	unsigned long m;
X	int n;
X	struct hostent *h;
X	char *p;
X
X	slash = strchr(s, '/');
X	if (slash == NULL)
X		return -1;
X	mask = slash + 1;
X	*slash = '\0';
Do you need help?X
X X if (*(s + strspn(s, "1234567890.")) == '\0') { X n = 0; X for (p = s; *p != '\0'; p++) /* count dots */ X if (*p == '.') X n++; X if (n != 3 || inet_aton(s, addrp) == 0) X return -1; X } else { X h = gethostbyname(s); X if (h == NULL) X return -1; X memcpy(&addrp->s_addr, h->h_addr, sizeof(addrp->s_addr)); X } X X if (*(mask + strspn(mask, "1234567890")) != '\0') { X if (*(mask + strspn(mask, "1234567890.")) == '\0') { X n = 0; X for (p = mask; *p != '\0'; p++) /* count dots */ X if (*p == '.') X n++; X if (n != 3 || inet_aton(mask, maskp) == 0) X return -1; X } else { X h = gethostbyname(mask); X if (h == NULL) X return -1; X memcpy(&maskp->s_addr, h->h_addr, sizeof(maskp->s_addr)); X } X return 0; X } X X /* uh-oh, mask must be a bit count */ X n = atoi(mask); X if (n > ABITS) X return -1; X m = 0; X m--; /* all 1s */ X m <<= ABITS - n; X maskp->s_addr = htonl(m); X X return 0;

X}
X
X
X
X#ifdef ATOSUBNET_MAIN
X
X#include <stdio.h>
X
Xvoid regress();
X
Xint
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	struct in_addr a;
X	struct in_addr m;
X	char buf[100];
X
X	if (argc < 2) {
X		fprintf(stderr, "Usage: %s {addr/mask|-r}\n", argv[0]);
X		exit(2);
X	}
X
X	if (strcmp(argv[1], "-r") == 0) {
X		regress();
X		fprintf(stderr, "regress() returned?!?\n");
X		exit(1);
X	}
X
X	if (atosubnet(argv[1], 0, &a, &m) < 0) {
X		fprintf(stderr, "%s: conversion failed\n", argv[0]);
X		exit(1);
X	}
X	if (subnettoa(a, m, buf, sizeof(buf)) < 0) {
X		fprintf(stderr, "%s: reverse conversion failed: ", argv[0]);
X		fprintf(stderr, "%s/", inet_ntoa(a));
X		fprintf(stderr, "%s\n", inet_ntoa(m));
X		exit(1);
X	}
X	printf("%s\n", buf);
X
X	exit(0);

X}
X
Xstruct rtab {
X	char *input;
X	char *output;			/* NULL means error expected */
X} rtab[] = {
X	"1.2.3.0/255.255.255.0",	"1.2.3.0/24",
X	"1.2.3.0/24",			"1.2.3.0/24",
X	"1.2.3.1/24",			"1.2.3.0/24",
X	"1.2.3.1/32",			"1.2.3.1/32",
X	"1.2.3.1/255.255.127.0",	"1.2.3.0/255.255.127.0",
Do you need more help?X
X "_", NULL, X "_/_", NULL, X "1.2.3.1", NULL, X "1.2.3.1/_", NULL, X "1.2.3.1/24._", NULL, X "1.2.3.1/99", NULL, X "localhost./32", "127.0.0.1/32", X NULL, NULL

X};
X
Xvoid
Xregress()
X{
X	struct rtab *r;
X	int status = 0;
X	struct in_addr a;
X	struct in_addr m;
X	char in[100];
X	char buf[100];
X	int i;
X
X	for (r = rtab; r->input != NULL; r++) {
X		strcpy(in, r->input);
X		i = atosubnet(in, 0, &a, &m);
X		if (i < 0 && r->output == NULL)
X			{}		/* okay, error expected */
X		else if (i < 0) {
X			printf("`%s' atosubnet failed\n", r->input);
X			status = 1;
X		} else if (r->output == NULL) {
X			printf("`%s' atosubnet succeeded unexpectedly\n",
X								r->input);
X			status = 1;
X		} else {
X			i = subnettoa(a, m, buf, sizeof(buf));
X			if (i < 0) {
X				printf("`%s' subnettoa failed\n", r->input);
X				status = 1;
X			} else if (strcmp(r->output, buf) != 0) {
X				printf("`%s' gave `%s', expected `%s'\n",
X						r->input, buf, r->output);
X				status = 1;
X			}
X		}
X	}
X	exit(status);

X}
X
X#endif /* ATOSUBNET_MAIN */
!

echo 'freeswan.h':
sed 's/^X//' >'freeswan.h' <<'!'
X#ifndef _FREESWAN_H
X#define _FREESWAN_H /* seen it, no need to see it again */ X
X/* FreeS/WAN library routines */
X
X/* subnet ASCII/binary conversions */
Xint /* 0 success, <0 failure */
Xatosubnet(
X	const char *src,
X	size_t srclen,		/* 0 means strlen(src) */
X	struct in_addr *addr,
X	struct in_addr *mask
X);
Xint				/* 0 success, <0 failure */
Xatoaddrmask(
X	char *src,		/* destroyed */
X	struct in_addr *addr,
X	struct in_addr *mask
X);
Xint				/* 0 success, <0 failure */
Xsubnettoa(
X	struct in_addr addr,
X	struct in_addr mask,
X	char *dst,
X	size_t dstlen		/* not large enough is an error */
X);
X#define	SUBNETTOA_BUF	32	/* large enough for worst case result */
X
X#endif /* _FREESWAN_H */
!

echo 'internal.h':
sed 's/^X//' >'internal.h' <<'!'
X/*
X * Internal definitions for use within the library.
X * Do not export this header file.
X */

X
X#ifndef ABITS
X#define	ABITS	32	/* bits in an Internet address */
X#endif

X
X#ifndef MALLOC
X/* to prevent use of dynamic allocation, define this as NULL */ X#define MALLOC(n) malloc(n)
X#endif
X
X#ifndef FREE
X#define	FREE(p)	free(p)
X#endif

!

echo 'subnettoa.c':
sed 's/^X//' >'subnettoa.c' <<'!'
X#include 
X#include 
X#include 
Can we help you?X
X#include X#include X#include "freeswan.h" X#include "internal.h"

X
X/*
X - subnettoa - convert address and mask to ASCII "addr/mask"
X * Inputs are in network byte order.  Note that they're structs, not
X * pointers to structs.
X * Output expresses the mask as a bit count if possible, else dotted quad.
X * It is an error for there not to be enough room.
X */
Xint				/* 0 success, -1 failure */

Xsubnettoa(addr, mask, dst, dstlen)
Xstruct in_addr addr;
Xstruct in_addr mask;
Xchar *dst;			/* where to put the ASCII */
Xsize_t dstlen;			/* how big dst is */
X{
X	unsigned long m;
X	int n;
X	char *p;
X	char c;
X	char *stop = dst + dstlen;
X	char buf[5];
X
X	p = inet_ntoa(addr);
X	while ((c = *p++) != '\0') {
X		if (dst >= stop)
X			return -1;
X		*dst++ = c;
X	}
X	if (dst >= stop)
X		return -1;
X	*dst++ = '/';
X
X	m = 0;
X	m--;				/* all 1s */
X	for (n = 0; n <= ABITS && htonl(m<= 100)		/* extreme paranoia */
X			*p++ = '0' + n/100;
X		if (n >= 10)
X			*p++ = '0' + n/10;
X		*p++ = '0' + n%10;
X		*p++ = '\0';
X		p = buf;
X	} else
X		p = inet_ntoa(mask);
X
X	while ((c = *p++) != '\0') {
X		if (dst >= stop)
X			return -1;
X		*dst++ = c;
X	}
X	if (dst >= stop)
X		return -1;
X	*dst++ = '\0';
X	return 0;

X}
!

echo done Received on Fri Jul 17 18:10:58 1998

This archive was generated by hypermail 2.1.8 : Wed Aug 23 2006 - 12:59:24 EDT


Contact Us  Legal Notices  Order Services Online 
Pantek Home  Privacy Policy  IT news  Site Map  Pantek Library