/* This file is part of Eclat.
Copyright (C) 2013-2015 Sergey Poznyakoff.
Eclat is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
Eclat is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Eclat. If not, see . */
#include "eclat.h"
#include
#include
#include
#include "sg.h"
struct groupkw groupkw[] = {
{ "GroupId", MAP_GROUPID },
{ "GroupName", MAP_GROUPNAME }
};
static struct ec2_request *request;
static char *command;
static int list_option;
static int dest_n = GROUP_ID;
static char *proto = "tcp";
static int rule_n = 1;
static char *user;
struct group_arg {
int type;
char *str;
char *usr;
};
static struct grecs_list *group_list;
static struct grecs_list *source_list;
static char *from_port, *to_port;
static char *bufptr = NULL;
static size_t bufsize = 0;
static int
add_source_cidr(char *str, int i)
{
char *p;
struct in_addr addr;
unsigned long n;
char masklen[3];
char cidrbuf[19];
struct addrinfo hints, *res, *ap;
struct protoent *pe;
p = strchr(str, '/');
if (p) {
char *q;
*p++ = 0;
errno = 0;
n = strtoul(p, &q, 10);
if (*q == 0) {
if (errno || n > 32) {
p[-1] = '/';
die(EX_USAGE, "invalid network mask in %s",
str);
}
strcpy(masklen, p);
} else {
int j;
if (inet_aton(p, &addr) == 0) {
p[-1] = '/';
die(EX_USAGE, "invalid network mask in %s",
str);
}
n = addr.s_addr;
for (j = 0; j < 32 && (n & 1); j++, n >>= 1)
;
if (n) {
p[-1] = '/';
die(EX_USAGE, "invalid network mask in %s",
str);
}
masklen[0] = j/10 + '0';
masklen[1] = j%10 + '0';
masklen[2] = 0;
}
} else
strcpy(masklen, "32");
memset(&hints, 0, sizeof(hints));
pe = getprotobyname(proto);
if (pe)
hints.ai_protocol = pe->p_proto;
else {
char *q;
errno = 0;
n = strtoul(proto, &q, 0);
if (errno || *q)
die(EX_USAGE, "%s: unrecognized protocol");
hints.ai_protocol = n;
}
hints.ai_family = AF_INET;
if (getaddrinfo(str, NULL, &hints, &res)) {
if (p) p[-1] = '/';
die(EX_USAGE, "invalid network address in %s", str);
}
for (ap = res; ap; ap = ap->ai_next) {
struct sockaddr_in *sp = (struct sockaddr_in *) ap->ai_addr;
char *s = inet_ntoa(sp->sin_addr);
if (s) {
snprintf(cidrbuf, sizeof cidrbuf,
"%s/%s", s, masklen);
grecs_asprintf(&bufptr, &bufsize,
"IpPermissions.%d.IpRanges.%d.CidrIp",
rule_n, i);
eclat_request_add_param(request, bufptr, cidrbuf);
i++;
}
}
freeaddrinfo(res);
return i;
}
static char *
str2port(const char *str, char **pbuf, size_t *psize)
{
long n;
struct servent *p;
char *end;
p = getservbyname(str, proto);
if (p) {
grecs_asprintf(pbuf, psize, "%d", (int) ntohs(p->s_port));
return *pbuf;
}
errno = 0;
n = strtol(str, &end, 10);
if (errno)
die(EX_USAGE, "%s: invalid port: %s", str, strerror(errno));
if (*end)
die(EX_USAGE, "%s: invalid port", str);
if (n < -1 || n > USHRT_MAX)
die(EX_USAGE, "%s: port number out of range", str);
return (char *) str;
}
static void
flush_rule()
{
int i;
struct grecs_list_entry *ep;
grecs_asprintf(&bufptr, &bufsize, "IpPermissions.%d.IpProtocol",
rule_n);
eclat_request_add_param(request, bufptr, proto);
if (group_list) {
for (i = 1, ep = group_list->head; ep; ep = ep->next, i++) {
struct group_arg *a = ep->data;
grecs_asprintf(&bufptr, &bufsize,
"IpPermissions.%d.Groups.%d.%s",
rule_n, i,
groupkw[a->type].resid);
eclat_request_add_param(request, bufptr, a->str);
if (a->usr) {
grecs_asprintf(&bufptr, &bufsize,
"IpPermissions.%d.Groups.%d.UserId",
rule_n, i);
eclat_request_add_param(request, bufptr, a->usr);
}
}
grecs_list_clear(group_list);
}
if (source_list) {
int j = 1;
for (i = 1, ep = source_list->head; ep; ep = ep->next, i++)
j = add_source_cidr((char*) ep->data, j);
grecs_list_clear(source_list);
} else if (!group_list) {
grecs_asprintf(&bufptr, &bufsize,
"IpPermissions.%d.IpRanges.1.CidrIp",
rule_n);
eclat_request_add_param(request, bufptr, "0.0.0.0/0");
}
if (from_port) {
char *pbuf = NULL;
size_t psize = 0;
grecs_asprintf(&bufptr, &bufsize, "IpPermissions.%d.FromPort",
rule_n);
eclat_request_add_param(request, bufptr,
str2port(from_port, &pbuf, &psize));
grecs_asprintf(&bufptr, &bufsize, "IpPermissions.%d.ToPort",
rule_n);
eclat_request_add_param(request, bufptr,
str2port(to_port, &pbuf, &psize));
free(pbuf);
}
from_port = to_port = NULL;
++rule_n;
}
#include "sg-cl.h"
int
eclat_sg(eclat_command_env_t *env, int argc, char **argv)
{
request = env->request;
parse_options(env, argc, argv);
return 0;
}