Merge branch 'master' of ssh://crater.dragonflybsd.org/repository/git/dragonfly
[dragonfly.git] / sbin / rconfig / client.c
blobdba0ad6b85e5b2f2f4930c941f26d78b7b9980fa
1 /*
2 * RCONFIG/CLIENT.C
4 * Copyright (c) 2003,2004 The DragonFly Project. All rights reserved.
5 *
6 * This code is derived from software contributed to The DragonFly Project
7 * by Matthew Dillon <dillon@backplane.com>
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 * 3. Neither the name of The DragonFly Project nor the names of its
20 * contributors may be used to endorse or promote products derived
21 * from this software without specific, prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
31 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
36 * $DragonFly: src/sbin/rconfig/client.c,v 1.4 2005/04/02 22:15:20 dillon Exp $
39 #include "defs.h"
41 #define LONG_ALIGN(n) (((n) + (sizeof(long) - 1)) & ~(sizeof(long) - 1))
43 static void load_client_broadcast_tags(tag_t tag, const char *tagName);
45 void
46 doClient(void)
48 int done = 0;
49 tag_t tag;
52 * The server list is in the form host[:tag]
54 chdir(WorkDir);
55 for (tag = AddrBase; tag && !done; tag = tag->next) {
56 struct sockaddr_in sain;
57 struct sockaddr_in rsin;
58 char *tagName;
59 char *host = NULL;
60 char *res = NULL;
61 char *buf = NULL;
62 int len;
63 int ufd = -1;
64 FILE *fi = NULL;
65 FILE *fo = NULL;
66 int rc;
68 bzero(&sain, sizeof(sain));
69 if (tag->name == NULL) {
70 load_client_broadcast_tags(tag, "auto");
71 continue;
73 if (tag->name[0] == ':') {
74 load_client_broadcast_tags(tag, tag->name + 1);
75 continue;
77 host = strdup(tag->name);
78 if ((tagName = strchr(host, ':')) != NULL) {
79 *tagName++ = 0;
80 tagName = strdup(tagName);
81 } else {
82 tagName = strdup("auto");
84 if (inet_aton(host, &sain.sin_addr) == 0) {
85 struct hostent *hp;
86 if ((hp = gethostbyname2(host, AF_INET)) == NULL) {
87 fprintf(stderr, "Unable to resolve %s\n", host);
88 exit(1);
90 bcopy(hp->h_addr_list[0], &sain.sin_addr, hp->h_length);
91 free(host);
92 host = strdup(hp->h_name);
93 endhostent();
95 sain.sin_port = htons(257);
96 sain.sin_len = sizeof(sain);
97 sain.sin_family = AF_INET;
100 * Do a couple of UDP transactions to locate the tag on the server.
102 printf("%s:%s - ", host, tagName);
103 fflush(stdout);
104 rc = udp_transact(&sain, &rsin, &ufd, &res, &len, "TAG %s\r\n", tagName);
105 if (rc != 101 || res == NULL) {
106 printf("NO LUCK %s\n", (res ? res : ""));
107 } else {
108 printf("%s -", res);
109 fflush(stdout);
110 rc = tcp_transact(&rsin, &fi, &fo, &buf, &len, "TAG %s\r\n", tagName);
111 if (rc == 201 && buf) {
112 int ffd;
113 char *path;
115 asprintf(&path, "%s/%s.sh", WorkDir, tagName);
116 ffd = open(path, O_CREAT|O_TRUNC|O_RDWR, 0755);
117 if (ffd >= 0 && write(ffd, buf, len) == len) {
118 printf("running %s [%d] in", path, len);
119 close(ffd);
120 ffd = -1;
121 for (rc = 5; rc > 0; --rc) {
122 printf(" %d", rc);
123 fflush(stdout);
124 sleep(1);
126 printf(" 0\n");
127 fflush(stdout);
128 rc = system(path);
129 if (rc)
130 printf("rconfig script exit code %d\n", rc);
131 done = 1;
132 } else {
133 if (ffd >= 0) {
134 remove(path);
135 close(ffd);
136 ffd = -1;
138 printf(" unable to create %s [%d] - DOWNLOAD FAILED\n",
139 path, len);
141 } else {
142 printf(" DOWNLOAD FAILED\n");
145 if (ufd >= 0) {
146 close(ufd);
147 ufd = -1;
149 if (fi != NULL) {
150 fclose(fi);
151 fi = NULL;
153 if (fo != NULL) {
154 fclose(fo);
155 fo = NULL;
157 if (buf)
158 free(buf);
159 if (res)
160 free(res);
161 free(host);
162 free(tagName);
166 static
167 void
168 load_client_broadcast_tags(tag_t tag, const char *tagName)
170 struct sockaddr_dl *sdl;
171 struct if_msghdr *ifm;
172 int mib[6];
173 char *buf;
174 size_t bytes;
175 int i;
177 mib[0] = CTL_NET;
178 mib[1] = PF_ROUTE;
179 mib[2] = 0;
180 mib[3] = AF_INET;
181 mib[4] = NET_RT_IFLIST;
182 mib[5] = 0;
184 if (sysctl(mib, 6, NULL, &bytes, NULL, 0) < 0) {
185 printf("no interfaces!\n");
186 exit(1);
188 buf = malloc(bytes);
189 if (sysctl(mib, 6, buf, &bytes, NULL, 0) < 0) {
190 printf("no interfaces!\n");
191 exit(1);
193 ifm = (void *)buf;
194 sdl = NULL;
195 while ((char *)ifm < buf + bytes && ifm->ifm_msglen) {
196 switch(ifm->ifm_type) {
197 case RTM_IFINFO:
198 if (ifm->ifm_flags & IFF_UP) {
199 sdl = (void *)(ifm + 1);
200 } else {
201 sdl = NULL;
203 break;
204 case RTM_NEWADDR:
205 if (sdl) {
206 struct sockaddr_in *sain;
207 struct ifa_msghdr *ifam;
208 char *scan;
209 char *name;
210 tag_t ntag;
212 ifam = (void *)ifm;
213 scan = (char *)(ifam + 1);
214 for (i = 0; i < RTAX_MAX; ++i) {
215 if ((1 << i) & ifam->ifam_addrs) {
216 sain = (void *)scan;
217 if (i == RTAX_BRD) {
218 asprintf(&name, "%s:%s",
219 inet_ntoa(sain->sin_addr), tagName);
220 ntag = calloc(sizeof(struct tag), 1);
221 ntag->name = name;
222 ntag->flags = 0;
223 ntag->next = tag->next;
224 tag->next = ntag;
225 tag = ntag;
226 if (VerboseOpt)
227 printf("add: %s (%s)\n", sdl->sdl_data, tag->name);
229 scan = scan + LONG_ALIGN(sain->sin_len);
233 break;
235 ifm = (void *)((char *)ifm + ifm->ifm_msglen);