#include "defs.h"
#define LONG_ALIGN(n) roundup2(n, sizeof(long))
static void load_client_broadcast_tags(tag_t tag, const char *tagName);
void
doClient(void)
{
int done = 0;
tag_t tag;
chdir(WorkDir);
for (tag = AddrBase; tag && !done; tag = tag->next) {
struct sockaddr_in sain;
struct sockaddr_in rsin;
char *tagName;
char *host = NULL;
char *res = NULL;
char *buf = NULL;
int len;
int ufd = -1;
FILE *fi = NULL;
FILE *fo = NULL;
int rc;
bzero(&sain, sizeof(sain));
if (tag->name == NULL) {
load_client_broadcast_tags(tag, "auto");
continue;
}
if (tag->name[0] == ':') {
load_client_broadcast_tags(tag, tag->name + 1);
continue;
}
host = strdup(tag->name);
if ((tagName = strchr(host, ':')) != NULL) {
*tagName++ = 0;
tagName = strdup(tagName);
} else {
tagName = strdup("auto");
}
if (inet_aton(host, &sain.sin_addr) == 0) {
struct hostent *hp;
if ((hp = gethostbyname2(host, AF_INET)) == NULL) {
fprintf(stderr, "Unable to resolve %s\n", host);
exit(1);
}
bcopy(hp->h_addr_list[0], &sain.sin_addr, hp->h_length);
free(host);
host = strdup(hp->h_name);
endhostent();
}
sain.sin_port = htons(257);
sain.sin_len = sizeof(sain);
sain.sin_family = AF_INET;
printf("%s:%s - ", host, tagName);
fflush(stdout);
rc = udp_transact(&sain, &rsin, &ufd, &res, &len, "TAG %s\r\n", tagName);
if (rc != 101 || res == NULL) {
printf("NO LUCK %s\n", (res ? res : ""));
} else {
printf("%s -", res);
fflush(stdout);
rc = tcp_transact(&rsin, &fi, &fo, &buf, &len, "TAG %s\r\n", tagName);
if (rc == 201 && buf) {
int ffd;
char *path;
asprintf(&path, "%s/%s.sh", WorkDir, tagName);
ffd = open(path, O_CREAT|O_TRUNC|O_RDWR, 0755);
if (ffd >= 0 && write(ffd, buf, len) == len) {
printf("running %s [%d] in", path, len);
close(ffd);
ffd = -1;
for (rc = 5; rc > 0; --rc) {
printf(" %d", rc);
fflush(stdout);
sleep(1);
}
printf(" 0\n");
fflush(stdout);
rc = system(path);
if (rc)
printf("rconfig script exit code %d\n", rc);
done = 1;
} else {
if (ffd >= 0) {
remove(path);
close(ffd);
ffd = -1;
}
printf(" unable to create %s [%d] - DOWNLOAD FAILED\n",
path, len);
}
} else {
printf(" DOWNLOAD FAILED\n");
}
}
if (ufd >= 0) {
close(ufd);
ufd = -1;
}
if (fi != NULL) {
fclose(fi);
fi = NULL;
}
if (fo != NULL) {
fclose(fo);
fo = NULL;
}
if (buf)
free(buf);
if (res)
free(res);
free(host);
free(tagName);
}
}
static
void
load_client_broadcast_tags(tag_t tag, const char *tagName)
{
struct sockaddr_dl *sdl;
struct if_msghdr *ifm;
int mib[6];
char *buf;
size_t bytes;
int i;
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[2] = 0;
mib[3] = AF_INET;
mib[4] = NET_RT_IFLIST;
mib[5] = 0;
if (sysctl(mib, 6, NULL, &bytes, NULL, 0) < 0) {
printf("no interfaces!\n");
exit(1);
}
buf = malloc(bytes);
if (sysctl(mib, 6, buf, &bytes, NULL, 0) < 0) {
printf("no interfaces!\n");
exit(1);
}
ifm = (void *)buf;
sdl = NULL;
while ((char *)ifm < buf + bytes && ifm->ifm_msglen) {
switch(ifm->ifm_type) {
case RTM_IFINFO:
if (ifm->ifm_flags & IFF_UP) {
sdl = (void *)(ifm + 1);
} else {
sdl = NULL;
}
break;
case RTM_NEWADDR:
if (sdl) {
struct sockaddr_in *sain;
struct ifa_msghdr *ifam;
char *scan;
char *name;
tag_t ntag;
ifam = (void *)ifm;
scan = (char *)(ifam + 1);
for (i = 0; i < RTAX_MAX; ++i) {
if ((1 << i) & ifam->ifam_addrs) {
sain = (void *)scan;
if (i == RTAX_BRD) {
asprintf(&name, "%s:%s",
inet_ntoa(sain->sin_addr), tagName);
ntag = calloc(1, sizeof(struct tag));
ntag->name = name;
ntag->flags = 0;
ntag->next = tag->next;
tag->next = ntag;
tag = ntag;
if (VerboseOpt)
printf("add: %s (%s)\n", sdl->sdl_data, tag->name);
}
scan = scan + LONG_ALIGN(sain->sin_len);
}
}
}
break;
}
ifm = (void *)((char *)ifm + ifm->ifm_msglen);
}
}