xref: /dflybsd-src/sbin/rconfig/client.c (revision 965b839fa3b6a8029b586326f283ad2260a4871c)
186ed60a6SMatthew Dillon /*
286ed60a6SMatthew Dillon  * RCONFIG/CLIENT.C
386ed60a6SMatthew Dillon  *
47a25b4e0SMatthew Dillon  * Copyright (c) 2003,2004 The DragonFly Project.  All rights reserved.
57a25b4e0SMatthew Dillon  *
67a25b4e0SMatthew Dillon  * This code is derived from software contributed to The DragonFly Project
77a25b4e0SMatthew Dillon  * by Matthew Dillon <dillon@backplane.com>
87a25b4e0SMatthew Dillon  *
97a25b4e0SMatthew Dillon  * Redistribution and use in source and binary forms, with or without
107a25b4e0SMatthew Dillon  * modification, are permitted provided that the following conditions
117a25b4e0SMatthew Dillon  * are met:
127a25b4e0SMatthew Dillon  *
137a25b4e0SMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
147a25b4e0SMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
157a25b4e0SMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
167a25b4e0SMatthew Dillon  *    notice, this list of conditions and the following disclaimer in
177a25b4e0SMatthew Dillon  *    the documentation and/or other materials provided with the
187a25b4e0SMatthew Dillon  *    distribution.
197a25b4e0SMatthew Dillon  * 3. Neither the name of The DragonFly Project nor the names of its
207a25b4e0SMatthew Dillon  *    contributors may be used to endorse or promote products derived
217a25b4e0SMatthew Dillon  *    from this software without specific, prior written permission.
227a25b4e0SMatthew Dillon  *
237a25b4e0SMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
247a25b4e0SMatthew Dillon  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
257a25b4e0SMatthew Dillon  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
267a25b4e0SMatthew Dillon  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
277a25b4e0SMatthew Dillon  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
287a25b4e0SMatthew Dillon  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
297a25b4e0SMatthew Dillon  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
307a25b4e0SMatthew Dillon  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
317a25b4e0SMatthew Dillon  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
327a25b4e0SMatthew Dillon  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
337a25b4e0SMatthew Dillon  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
347a25b4e0SMatthew Dillon  * SUCH DAMAGE.
3586ed60a6SMatthew Dillon  */
3686ed60a6SMatthew Dillon 
3786ed60a6SMatthew Dillon #include "defs.h"
3886ed60a6SMatthew Dillon 
39*965b839fSSascha Wildner #define LONG_ALIGN(n)	roundup2(n, sizeof(long))
4086ed60a6SMatthew Dillon 
4186ed60a6SMatthew Dillon static void load_client_broadcast_tags(tag_t tag, const char *tagName);
4286ed60a6SMatthew Dillon 
4386ed60a6SMatthew Dillon void
doClient(void)4486ed60a6SMatthew Dillon doClient(void)
4586ed60a6SMatthew Dillon {
4686ed60a6SMatthew Dillon     int done = 0;
4786ed60a6SMatthew Dillon     tag_t tag;
4886ed60a6SMatthew Dillon 
4986ed60a6SMatthew Dillon     /*
5086ed60a6SMatthew Dillon      * The server list is in the form host[:tag]
5186ed60a6SMatthew Dillon      */
52b942d70cSMatthew Dillon     chdir(WorkDir);
5386ed60a6SMatthew Dillon     for (tag = AddrBase; tag && !done; tag = tag->next) {
5486ed60a6SMatthew Dillon 	struct sockaddr_in sain;
5586ed60a6SMatthew Dillon 	struct sockaddr_in rsin;
5686ed60a6SMatthew Dillon 	char *tagName;
5786ed60a6SMatthew Dillon 	char *host = NULL;
5886ed60a6SMatthew Dillon 	char *res = NULL;
5986ed60a6SMatthew Dillon 	char *buf = NULL;
6086ed60a6SMatthew Dillon 	int len;
6186ed60a6SMatthew Dillon 	int ufd = -1;
6286ed60a6SMatthew Dillon 	FILE *fi = NULL;
6386ed60a6SMatthew Dillon 	FILE *fo = NULL;
6486ed60a6SMatthew Dillon 	int rc;
6586ed60a6SMatthew Dillon 
6686ed60a6SMatthew Dillon 	bzero(&sain, sizeof(sain));
6786ed60a6SMatthew Dillon 	if (tag->name == NULL) {
6886ed60a6SMatthew Dillon 	    load_client_broadcast_tags(tag, "auto");
6986ed60a6SMatthew Dillon 	    continue;
7086ed60a6SMatthew Dillon 	}
7186ed60a6SMatthew Dillon 	if (tag->name[0] == ':') {
7286ed60a6SMatthew Dillon 	    load_client_broadcast_tags(tag, tag->name + 1);
7386ed60a6SMatthew Dillon 	    continue;
7486ed60a6SMatthew Dillon 	}
7586ed60a6SMatthew Dillon 	host = strdup(tag->name);
761213fdc4SMatthew Dillon 	if ((tagName = strchr(host, ':')) != NULL) {
7786ed60a6SMatthew Dillon 	    *tagName++ = 0;
7886ed60a6SMatthew Dillon 	    tagName = strdup(tagName);
791213fdc4SMatthew Dillon 	} else {
801213fdc4SMatthew Dillon 	    tagName = strdup("auto");
811213fdc4SMatthew Dillon 	}
8286ed60a6SMatthew Dillon 	if (inet_aton(host, &sain.sin_addr) == 0) {
8386ed60a6SMatthew Dillon 	    struct hostent *hp;
8486ed60a6SMatthew Dillon 	    if ((hp = gethostbyname2(host, AF_INET)) == NULL) {
8586ed60a6SMatthew Dillon 		fprintf(stderr, "Unable to resolve %s\n", host);
8686ed60a6SMatthew Dillon 		exit(1);
8786ed60a6SMatthew Dillon 	    }
8886ed60a6SMatthew Dillon 	    bcopy(hp->h_addr_list[0], &sain.sin_addr, hp->h_length);
8986ed60a6SMatthew Dillon 	    free(host);
9086ed60a6SMatthew Dillon 	    host = strdup(hp->h_name);
9186ed60a6SMatthew Dillon 	    endhostent();
9286ed60a6SMatthew Dillon 	}
9386ed60a6SMatthew Dillon 	sain.sin_port = htons(257);
9486ed60a6SMatthew Dillon 	sain.sin_len = sizeof(sain);
9586ed60a6SMatthew Dillon 	sain.sin_family = AF_INET;
9686ed60a6SMatthew Dillon 
9786ed60a6SMatthew Dillon 	/*
9886ed60a6SMatthew Dillon 	 * Do a couple of UDP transactions to locate the tag on the server.
9986ed60a6SMatthew Dillon 	 */
10086ed60a6SMatthew Dillon 	printf("%s:%s - ", host, tagName);
10186ed60a6SMatthew Dillon 	fflush(stdout);
10286ed60a6SMatthew Dillon 	rc = udp_transact(&sain, &rsin, &ufd, &res, &len, "TAG %s\r\n", tagName);
10386ed60a6SMatthew Dillon 	if (rc != 101 || res == NULL) {
10486ed60a6SMatthew Dillon 	    printf("NO LUCK %s\n", (res ? res : ""));
10586ed60a6SMatthew Dillon 	} else {
10686ed60a6SMatthew Dillon 	    printf("%s -", res);
10786ed60a6SMatthew Dillon 	    fflush(stdout);
10886ed60a6SMatthew Dillon 	    rc = tcp_transact(&rsin, &fi, &fo, &buf, &len, "TAG %s\r\n", tagName);
10986ed60a6SMatthew Dillon 	    if (rc == 201 && buf) {
11086ed60a6SMatthew Dillon 		int ffd;
11186ed60a6SMatthew Dillon 		char *path;
11286ed60a6SMatthew Dillon 
11386ed60a6SMatthew Dillon 		asprintf(&path, "%s/%s.sh", WorkDir, tagName);
11486ed60a6SMatthew Dillon 		ffd = open(path, O_CREAT|O_TRUNC|O_RDWR, 0755);
11586ed60a6SMatthew Dillon 		if (ffd >= 0 && write(ffd, buf, len) == len) {
11686ed60a6SMatthew Dillon 		    printf("running %s [%d] in", path, len);
11786ed60a6SMatthew Dillon 		    close(ffd);
11886ed60a6SMatthew Dillon 		    ffd = -1;
11986ed60a6SMatthew Dillon 		    for (rc = 5; rc > 0; --rc) {
12086ed60a6SMatthew Dillon 			printf(" %d", rc);
12186ed60a6SMatthew Dillon 			fflush(stdout);
12286ed60a6SMatthew Dillon 			sleep(1);
12386ed60a6SMatthew Dillon 		    }
12486ed60a6SMatthew Dillon 		    printf(" 0\n");
12586ed60a6SMatthew Dillon 		    fflush(stdout);
12686ed60a6SMatthew Dillon 		    rc = system(path);
12786ed60a6SMatthew Dillon 		    if (rc)
12886ed60a6SMatthew Dillon 			printf("rconfig script exit code %d\n", rc);
12986ed60a6SMatthew Dillon 		    done = 1;
13086ed60a6SMatthew Dillon 		} else {
13186ed60a6SMatthew Dillon 		    if (ffd >= 0) {
13286ed60a6SMatthew Dillon 			remove(path);
13386ed60a6SMatthew Dillon 			close(ffd);
13486ed60a6SMatthew Dillon 			ffd = -1;
13586ed60a6SMatthew Dillon 		    }
13686ed60a6SMatthew Dillon 		    printf(" unable to create %s [%d] - DOWNLOAD FAILED\n",
13786ed60a6SMatthew Dillon 			    path, len);
13886ed60a6SMatthew Dillon 		}
13986ed60a6SMatthew Dillon 	    } else {
14086ed60a6SMatthew Dillon 		printf(" DOWNLOAD FAILED\n");
14186ed60a6SMatthew Dillon 	    }
14286ed60a6SMatthew Dillon 	}
14386ed60a6SMatthew Dillon 	if (ufd >= 0) {
14486ed60a6SMatthew Dillon 	    close(ufd);
14586ed60a6SMatthew Dillon 	    ufd = -1;
14686ed60a6SMatthew Dillon 	}
14786ed60a6SMatthew Dillon 	if (fi != NULL) {
14886ed60a6SMatthew Dillon 	    fclose(fi);
14986ed60a6SMatthew Dillon 	    fi = NULL;
15086ed60a6SMatthew Dillon 	}
15186ed60a6SMatthew Dillon 	if (fo != NULL) {
15286ed60a6SMatthew Dillon 	    fclose(fo);
15386ed60a6SMatthew Dillon 	    fo = NULL;
15486ed60a6SMatthew Dillon 	}
15586ed60a6SMatthew Dillon 	if (buf)
15686ed60a6SMatthew Dillon 	    free(buf);
15786ed60a6SMatthew Dillon 	if (res)
15886ed60a6SMatthew Dillon 	    free(res);
15986ed60a6SMatthew Dillon 	free(host);
16086ed60a6SMatthew Dillon 	free(tagName);
16186ed60a6SMatthew Dillon     }
16286ed60a6SMatthew Dillon }
16386ed60a6SMatthew Dillon 
16486ed60a6SMatthew Dillon static
16586ed60a6SMatthew Dillon void
load_client_broadcast_tags(tag_t tag,const char * tagName)16686ed60a6SMatthew Dillon load_client_broadcast_tags(tag_t tag, const char *tagName)
16786ed60a6SMatthew Dillon {
16886ed60a6SMatthew Dillon     struct sockaddr_dl *sdl;
16986ed60a6SMatthew Dillon     struct if_msghdr *ifm;
17086ed60a6SMatthew Dillon     int mib[6];
17186ed60a6SMatthew Dillon     char *buf;
1729dda8cf6SSascha Wildner     size_t bytes;
17386ed60a6SMatthew Dillon     int i;
17486ed60a6SMatthew Dillon 
17586ed60a6SMatthew Dillon     mib[0] = CTL_NET;
17686ed60a6SMatthew Dillon     mib[1] = PF_ROUTE;
17786ed60a6SMatthew Dillon     mib[2] = 0;
17886ed60a6SMatthew Dillon     mib[3] = AF_INET;
17986ed60a6SMatthew Dillon     mib[4] = NET_RT_IFLIST;
18086ed60a6SMatthew Dillon     mib[5] = 0;
18186ed60a6SMatthew Dillon 
18286ed60a6SMatthew Dillon     if (sysctl(mib, 6, NULL, &bytes, NULL, 0) < 0) {
18386ed60a6SMatthew Dillon 	printf("no interfaces!\n");
18486ed60a6SMatthew Dillon 	exit(1);
18586ed60a6SMatthew Dillon     }
18686ed60a6SMatthew Dillon     buf = malloc(bytes);
18786ed60a6SMatthew Dillon     if (sysctl(mib, 6, buf, &bytes, NULL, 0) < 0) {
18886ed60a6SMatthew Dillon 	printf("no interfaces!\n");
18986ed60a6SMatthew Dillon 	exit(1);
19086ed60a6SMatthew Dillon     }
19186ed60a6SMatthew Dillon     ifm = (void *)buf;
19286ed60a6SMatthew Dillon     sdl = NULL;
19386ed60a6SMatthew Dillon     while ((char *)ifm < buf + bytes && ifm->ifm_msglen) {
19486ed60a6SMatthew Dillon 	switch(ifm->ifm_type) {
19586ed60a6SMatthew Dillon 	case RTM_IFINFO:
19686ed60a6SMatthew Dillon 	    if (ifm->ifm_flags & IFF_UP) {
19786ed60a6SMatthew Dillon 		sdl = (void *)(ifm + 1);
19886ed60a6SMatthew Dillon 	    } else {
19986ed60a6SMatthew Dillon 		sdl = NULL;
20086ed60a6SMatthew Dillon 	    }
20186ed60a6SMatthew Dillon 	    break;
20286ed60a6SMatthew Dillon 	case RTM_NEWADDR:
20386ed60a6SMatthew Dillon 	    if (sdl) {
20486ed60a6SMatthew Dillon 		struct sockaddr_in *sain;
20586ed60a6SMatthew Dillon 		struct ifa_msghdr *ifam;
20686ed60a6SMatthew Dillon 		char *scan;
20786ed60a6SMatthew Dillon 		char *name;
20886ed60a6SMatthew Dillon 		tag_t ntag;
20986ed60a6SMatthew Dillon 
21086ed60a6SMatthew Dillon 		ifam = (void *)ifm;
21186ed60a6SMatthew Dillon 		scan = (char *)(ifam + 1);
21286ed60a6SMatthew Dillon 		for (i = 0; i < RTAX_MAX; ++i) {
21386ed60a6SMatthew Dillon 		    if ((1 << i) & ifam->ifam_addrs) {
21486ed60a6SMatthew Dillon 			sain = (void *)scan;
21586ed60a6SMatthew Dillon 			if (i == RTAX_BRD) {
21686ed60a6SMatthew Dillon 			    asprintf(&name, "%s:%s",
21786ed60a6SMatthew Dillon 				    inet_ntoa(sain->sin_addr), tagName);
21886ed60a6SMatthew Dillon 			    ntag = calloc(sizeof(struct tag), 1);
21986ed60a6SMatthew Dillon 			    ntag->name = name;
22086ed60a6SMatthew Dillon 			    ntag->flags = 0;
22186ed60a6SMatthew Dillon 			    ntag->next = tag->next;
22286ed60a6SMatthew Dillon 			    tag->next = ntag;
22386ed60a6SMatthew Dillon 			    tag = ntag;
22486ed60a6SMatthew Dillon 			    if (VerboseOpt)
22586ed60a6SMatthew Dillon 				printf("add: %s (%s)\n", sdl->sdl_data, tag->name);
22686ed60a6SMatthew Dillon 			}
22786ed60a6SMatthew Dillon 			scan = scan + LONG_ALIGN(sain->sin_len);
22886ed60a6SMatthew Dillon 		    }
22986ed60a6SMatthew Dillon 		}
23086ed60a6SMatthew Dillon 	    }
23186ed60a6SMatthew Dillon 	    break;
23286ed60a6SMatthew Dillon 	}
23386ed60a6SMatthew Dillon 	ifm = (void *)((char *)ifm + ifm->ifm_msglen);
23486ed60a6SMatthew Dillon     }
23586ed60a6SMatthew Dillon }
23686ed60a6SMatthew Dillon 
237