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.4 2005/04/02 22:15:20 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 tagName = strdup(tagName); 81 } else { 82 tagName = strdup("auto"); 83 } 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); 89 } 90 bcopy(hp->h_addr_list[0], &sain.sin_addr, hp->h_length); 91 free(host); 92 host = strdup(hp->h_name); 93 endhostent(); 94 } 95 sain.sin_port = htons(257); 96 sain.sin_len = sizeof(sain); 97 sain.sin_family = AF_INET; 98 99 /* 100 * Do a couple of UDP transactions to locate the tag on the server. 101 */ 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; 114 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); 125 } 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; 137 } 138 printf(" unable to create %s [%d] - DOWNLOAD FAILED\n", 139 path, len); 140 } 141 } else { 142 printf(" DOWNLOAD FAILED\n"); 143 } 144 } 145 if (ufd >= 0) { 146 close(ufd); 147 ufd = -1; 148 } 149 if (fi != NULL) { 150 fclose(fi); 151 fi = NULL; 152 } 153 if (fo != NULL) { 154 fclose(fo); 155 fo = NULL; 156 } 157 if (buf) 158 free(buf); 159 if (res) 160 free(res); 161 free(host); 162 free(tagName); 163 } 164 } 165 166 static 167 void 168 load_client_broadcast_tags(tag_t tag, const char *tagName) 169 { 170 struct sockaddr_dl *sdl; 171 struct if_msghdr *ifm; 172 int mib[6]; 173 char *buf; 174 size_t bytes; 175 int i; 176 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; 183 184 if (sysctl(mib, 6, NULL, &bytes, NULL, 0) < 0) { 185 printf("no interfaces!\n"); 186 exit(1); 187 } 188 buf = malloc(bytes); 189 if (sysctl(mib, 6, buf, &bytes, NULL, 0) < 0) { 190 printf("no interfaces!\n"); 191 exit(1); 192 } 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; 202 } 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; 211 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); 228 } 229 scan = scan + LONG_ALIGN(sain->sin_len); 230 } 231 } 232 } 233 break; 234 } 235 ifm = (void *)((char *)ifm + ifm->ifm_msglen); 236 } 237 } 238 239