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