|
|||||||||||
|
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
Comments are still very much welcome.
Henry Spencer
henry@spsystems.net
(henry@zoo.toronto.edu)
#! /bin/sh
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 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 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'; 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",
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 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<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 |
||||||||||
|
|||||||||||