da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner* Copyright (c) 1985-2010 AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* and is licensed under the *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Common Public License, Version 1.0 *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin* by AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* http://www.opensource.org/licenses/cpl1.0.txt *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Glenn Fowler <gsf@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Phong Vo <kpv@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#pragma prototyped
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <ast.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <ctype.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * convert string to 4 byte local byte order ip address
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * with optional prefix bits
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * pointer to first unused char placed in *e, even on error
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * return 0:ok <0:error
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * valid addresses match the egrep RE:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * [0-9]{1,3}(\.[0-9]{1,3})*|0[xX][0-9a-fA-Z]+
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * valid bits/masks match the egrep RE:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * (/([0-9]+|[0-9]{1,3}(\.[0-9]{1,3})*))?
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * if pbits!=0 and no bits/mask specified then trailing 0's in addr
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * are used to compute the mask
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstrtoip4(register const char* s, char** e, uint32_t* paddr, unsigned char* pbits)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned int n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register uint32_t addr;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int part;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned char bits;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin uint32_t z;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int old;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int r;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin const char* b;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin r = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (isspace(*s))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin s++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin b = s;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin addr = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin bits = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin part = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin do
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while ((c = *s++) >= '0' && c <= '9')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = n * 10 + (c - '0');
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((c == 'x' || c == 'X') && !part)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin addr = n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (;;)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((c = *s++) >= '0' && c <= '9')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin c -= '0';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (c >= 'a' && c <= 'f')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin c -= 'a' - 10;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (c >= 'A' && c <= 'F')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin c -= 'F' - 10;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin addr = addr * 16 + c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin part = 4;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (n > 0xff)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin addr = (addr << 8) | n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin part++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin } while (c == '.');
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((s - b) == 1 && c != '/' || part > 4)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (old = part < 4)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (part++ < 4)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin addr <<= 8;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (pbits)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c == '/')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin part = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin z = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (;;)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while ((c = *s++) >= '0' && c <= '9')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = n * 10 + (c - '0');
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin z = (z << 8) | n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin part++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c != '.')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin old = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (part > 4)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin goto done;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (z <= 32 && (!old || part < 2))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin bits = z;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (z)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (part == 4 && (z & 0x8000001) == 1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin z = ~z;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (!(z & 1))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin z >>= 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (z & 1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin z >>= 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin bits++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if ((z = (addr >> 24)) < 128)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin bits = 8;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (z < 192)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin bits = 16;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin bits = 24;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*pbits = bits)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin addr &= ~((((uint32_t)1)<<(32-bits))-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin addr = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (paddr)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *paddr = addr;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin r = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin done:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (e)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *e = (char*)(s - 1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return r;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}