1 /* 2 * RCONFIG/CLIENT.C 3 * 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: 12 * 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. 22 * 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. 35 */ 36 37 #include "defs.h" 38 39 #define LONG_ALIGN(n) roundup2(n, sizeof(long)) 40 41 static void load_client_broadcast_tags(tag_t tag, const char *tagName); 42 43 void 44 doClient(void) 45 { 46 int done = 0; 47 tag_t tag; 48 49 /* 50 * The server list is in the form host[:tag] 51 */ 52 chdir(WorkDir); 53 for (tag = AddrBase; tag && !done; tag = tag->next) { 54 struct sockaddr_in sain; 55 struct sockaddr_in rsin; 56 char *tagName; 57 char *host = NULL; 58 char *res = NULL; 59 char *buf = NULL; 60 int len; 61 int ufd = -1; 62 FILE *fi = NULL; 63 FILE *fo = NULL; 64 int rc; 65 66 bzero(&sain, sizeof(sain)); 67 if (tag->name == NULL) { 68 load_client_broadcast_tags(tag, "auto"); 69 continue; 70 } 71 if (tag->name[0] == ':') { 72 load_client_broadcast_tags(tag, tag->name + 1); 73 continue; 74 } 75 host = strdup(tag->name); 76 if ((tagName = strchr(host, ':')) != NULL) { 77 *tagName++ = 0; 78 tagName = strdup(tagName); 79 } else { 80 tagName = strdup("auto"); 81 } 82 if (inet_aton(host, &sain.sin_addr) == 0) { 83 struct hostent *hp; 84 if ((hp = gethostbyname2(host, AF_INET)) == NULL) { 85 fprintf(stderr, "Unable to resolve %s\n", host); 86 exit(1); 87 } 88 bcopy(hp->h_addr_list[0], &sain.sin_addr, hp->h_length); 89 free(host); 90 host = strdup(hp->h_name); 91 endhostent(); 92 } 93 sain.sin_port = htons(257); 94 sain.sin_len = sizeof(sain); 95 sain.sin_family = AF_INET; 96 97 /* 98 * Do a couple of UDP transactions to locate the tag on the server. 99 */ 100 printf("%s:%s - ", host, tagName); 101 fflush(stdout); 102 rc = udp_transact(&sain, &rsin, &ufd, &res, &len, "TAG %s\r\n", tagName); 103 if (rc != 101 || res == NULL) { 104 printf("NO LUCK %s\n", (res ? res : "")); 105 } else { 106 printf("%s -", res); 107 fflush(stdout); 108 rc = tcp_transact(&rsin, &fi, &fo, &buf, &len, "TAG %s\r\n", tagName); 109 if (rc == 201 && buf) { 110 int ffd; 111 char *path; 112 113 asprintf(&path, "%s/%s.sh", WorkDir, tagName); 114 ffd = open(path, O_CREAT|O_TRUNC|O_RDWR, 0755); 115 if (ffd >= 0 && write(ffd, buf, len) == len) { 116 printf("running %s [%d] in", path, len); 117 close(ffd); 118 ffd = -1; 119 for (rc = 5; rc > 0; --rc) { 120 printf(" %d", rc); 121 fflush(stdout); 122 sleep(1); 123 } 124 printf(" 0\n"); 125 fflush(stdout); 126 rc = system(path); 127 if (rc) 128 printf("rconfig script exit code %d\n", rc); 129 done = 1; 130 } else { 131 if (ffd >= 0) { 132 remove(path); 133 close(ffd); 134 ffd = -1; 135 } 136 printf(" unable to create %s [%d] - DOWNLOAD FAILED\n", 137 path, len); 138 } 139 } else { 140 printf(" DOWNLOAD FAILED\n"); 141 } 142 } 143 if (ufd >= 0) { 144 close(ufd); 145 ufd = -1; 146 } 147 if (fi != NULL) { 148 fclose(fi); 149 fi = NULL; 150 } 151 if (fo != NULL) { 152 fclose(fo); 153 fo = NULL; 154 } 155 if (buf) 156 free(buf); 157 if (res) 158 free(res); 159 free(host); 160 free(tagName); 161 } 162 } 163 164 static 165 void 166 load_client_broadcast_tags(tag_t tag, const char *tagName) 167 { 168 struct sockaddr_dl *sdl; 169 struct if_msghdr *ifm; 170 int mib[6]; 171 char *buf; 172 size_t bytes; 173 int i; 174 175 mib[0] = CTL_NET; 176 mib[1] = PF_ROUTE; 177 mib[2] = 0; 178 mib[3] = AF_INET; 179 mib[4] = NET_RT_IFLIST; 180 mib[5] = 0; 181 182 if (sysctl(mib, 6, NULL, &bytes, NULL, 0) < 0) { 183 printf("no interfaces!\n"); 184 exit(1); 185 } 186 buf = malloc(bytes); 187 if (sysctl(mib, 6, buf, &bytes, NULL, 0) < 0) { 188 printf("no interfaces!\n"); 189 exit(1); 190 } 191 ifm = (void *)buf; 192 sdl = NULL; 193 while ((char *)ifm < buf + bytes && ifm->ifm_msglen) { 194 switch(ifm->ifm_type) { 195 case RTM_IFINFO: 196 if (ifm->ifm_flags & IFF_UP) { 197 sdl = (void *)(ifm + 1); 198 } else { 199 sdl = NULL; 200 } 201 break; 202 case RTM_NEWADDR: 203 if (sdl) { 204 struct sockaddr_in *sain; 205 struct ifa_msghdr *ifam; 206 char *scan; 207 char *name; 208 tag_t ntag; 209 210 ifam = (void *)ifm; 211 scan = (char *)(ifam + 1); 212 for (i = 0; i < RTAX_MAX; ++i) { 213 if ((1 << i) & ifam->ifam_addrs) { 214 sain = (void *)scan; 215 if (i == RTAX_BRD) { 216 asprintf(&name, "%s:%s", 217 inet_ntoa(sain->sin_addr), tagName); 218 ntag = calloc(sizeof(struct tag), 1); 219 ntag->name = name; 220 ntag->flags = 0; 221 ntag->next = tag->next; 222 tag->next = ntag; 223 tag = ntag; 224 if (VerboseOpt) 225 printf("add: %s (%s)\n", sdl->sdl_data, tag->name); 226 } 227 scan = scan + LONG_ALIGN(sain->sin_len); 228 } 229 } 230 } 231 break; 232 } 233 ifm = (void *)((char *)ifm + ifm->ifm_msglen); 234 } 235 } 236 237