/* This file is part of Eclat. Copyright (C) 2013-2014 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 "sg.h" struct groupkw groupkw[] = { { "GroupId", MAP_GROUPID }, { "GroupName", MAP_GROUPNAME } }; static struct ec2_query *query; 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; n = strtoul(p, &q, 10); if (*q == 0) { if (n <= 0 || 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 { errno = 0; n = strtoul(proto, &p, 0); if (errno || *p) die(EX_USAGE, "%s: unrecognized protocol"); hints.ai_protocol = n; } hints.ai_family = AF_INET; if (getaddrinfo(str, NULL, &hints, &res)) { 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_query_add_param(query, bufptr, cidrbuf); i++; } } freeaddrinfo(res); return i; } static char * str2port(const char *str, char **pbuf, size_t *psize) { unsigned 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 = strtoul(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 > 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_query_add_param(query, 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_query_add_param(query, bufptr, a->str); if (a->usr) { grecs_asprintf(&bufptr, &bufsize, "IpPermissions.%d.Groups.%d.UserId", rule_n, i); eclat_query_add_param(query, 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_query_add_param(query, 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_query_add_param(query, bufptr, str2port(from_port, &pbuf, &psize)); grecs_asprintf(&bufptr, &bufsize, "IpPermissions.%d.ToPort", rule_n); eclat_query_add_param(query, 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) { query = env->query; parse_options(env, argc, argv); return 0; }