Skip to content

Instantly share code, notes, and snippets.

@jlyo
Created September 21, 2012 21:28
Show Gist options
  • Save jlyo/3764025 to your computer and use it in GitHub Desktop.
Save jlyo/3764025 to your computer and use it in GitHub Desktop.
Ragel IPv4/6 address validator
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netdb.h>
%%{
machine isip;
octet4 = [0-9]{1,2}
| [0-1] . [0-9]{2}
| '2' . [0-4] . [0-9]
| '2' . '5' . [0-5];
netmask = [0-9]
| [0-2] . [0-9]
| '3' . [0-2];
zero = '0'{1,3};
dqnetmaskoctet = '255'
| '254'
| '252'
| '248'
| '240'
| '224'
| '192'
| '128'
| zero;
dqnetmask = '255.'{3} dqnetmaskoctet
| '255.'{2} dqnetmaskoctet ('.' zero){1}
| '255.'{1} dqnetmaskoctet ('.' zero){2}
| dqnetmaskoctet ('.' zero){3};
ipv4 = (octet4 '.'){3} octet4; #('/' (netmask | dqnetmask))?;
short6 = xdigit{1,4};
prefix = '/' ( [0-9]{1,2}
| '1' . [0-1] . [0-9]
| '12' . [0-8]);
ipv6 = ( (short6 ':'){7} short6
| (short6 ':'){7} ':' short6?
| (short6 ':'){6} ':' ((short6 ':'){0,1} short6)?
| (short6 ':'){5} ':' ((short6 ':'){0,2} short6)?
| (short6 ':'){4} ':' ((short6 ':'){0,3} short6)?
| (short6 ':'){3} ':' ((short6 ':'){0,4} short6)?
| (short6 ':'){2} ':' ((short6 ':'){0,5} short6)?
| (short6 ':'){1} ':' ((short6 ':'){0,6} short6)?
| '::' ((short6 ':'){0,7} short6)?); # prefix?;
main := ( ipv4
| ipv6
) ; #| '[' ipv6 ']');
}%%
%%write data;
static bool isip(const char *const s, const size_t len)
{
const char *p = s;
const char *const pe = s + len;
int cs;
%%{
write init;
write exec;
}%%
return cs != isip_error;
}
/**
* Get a canonical IP address
*/
static int canonical_ip(const char *s, char *const host, size_t *const host_len)
{
struct addrinfo *res;
int err = 0;
static const struct addrinfo HINTS = {
AI_V4MAPPED | AI_ADDRCONFIG | AI_NUMERICHOST,
AF_UNSPEC,
0,
0,
0,
NULL,
NULL,
NULL
};
if ((err = getaddrinfo(s, NULL, &HINTS, &res)) != 0) { goto err0; }
if ((err = getnameinfo(res->ai_addr, res->ai_addrlen, host, *host_len,
NULL, 0, NI_NUMERICHOST)) != 0) { goto err1; }
*host_len = strlen(host);
freeaddrinfo(res); res = NULL;
return 0;
err1:
freeaddrinfo(res); res = NULL;
err0:
return err;
}
int main(const int argc, const char *argv[])
{
int i;
char *host = NULL;
size_t host_len = NI_MAXHOST;
for (i = 1; i < argc; ++i) {
host_len = NI_MAXHOST;
if ( (isip(argv[i], strlen(argv[i])))
&& ((host = malloc(NI_MAXHOST)) != NULL)
&& (canonical_ip(argv[i], host, &host_len) == 0))
{
fwrite(host, 1, host_len, stdout);
printf("\n");
free(host); host = NULL;
} else {
exit(1);
}
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment