1 /*
2 * Copyright (c) 1999
3 * Philipp Mergenthaler <philipp.mergenthaler@stud.uni-karlsruhe.de>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 * $FreeBSD: stable/9/usr.sbin/sysinstall/httpdirect.c 248313 2013-03-15 05:00:51Z dteske $
28 */
29
30 #include "sysinstall.h"
31 #include <sys/socket.h>
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
34 #include <sys/param.h>
35 #include <netdb.h>
36
37 extern const char *ftp_dirs[]; /* defined in ftp.c */
38
39 Boolean
mediaInitHTTPDirect(Device * dev)40 mediaInitHTTPDirect(Device *dev)
41 {
42 bool found=FALSE; /* end of header line */
43 char *rel, req[BUFSIZ];
44 int fdir;
45
46 /*
47 * First verify basic access
48 */
49 checkAccess(TRUE, FALSE);
50 while (variable_get(VAR_HTTP_HOST) == NULL) {
51 if (DITEM_STATUS(mediaSetHTTPDirect(NULL)) == DITEM_FAILURE)
52 return FALSE;
53 checkAccess(TRUE, FALSE);
54 }
55 again:
56 /* If the release is specified as "__RELEASE" or "any", then just
57 * assume that the path the user gave is ok.
58 */
59 rel = variable_get(VAR_RELNAME);
60 /*
61 msgConfirm("rel: -%s-", rel);
62 */
63
64 if (strcmp(rel, "__RELEASE") && strcmp(rel, "any")) {
65 for (fdir = 0; ftp_dirs[fdir]; fdir++) {
66 sprintf(req, "%s/%s/%s", variable_get(VAR_HTTP_DIR),
67 ftp_dirs[fdir], rel);
68 variable_set2(VAR_HTTP_PATH, req, 0);
69 if (checkAccess(FALSE, FALSE)) {
70 found = TRUE;
71 break;
72 }
73 }
74 } else {
75 variable_set2(VAR_HTTP_PATH, variable_get(VAR_HTTP_DIR), 0);
76 found = checkAccess(FALSE, FALSE);
77 }
78 if (!found) {
79 msgConfirm("No such directory: %s\n"
80 "please check the URL and try again.", variable_get(VAR_HTTP_PATH));
81 variable_unset(VAR_HTTP_PATH);
82 dialog_clear_norefresh();
83 clear();
84 if (DITEM_STATUS(mediaSetHTTPDirect(NULL)) != DITEM_FAILURE) goto again;
85 }
86 return found;
87 }
88
89 FILE *
mediaGetHTTPDirect(Device * dev,char * file,Boolean probe)90 mediaGetHTTPDirect(Device *dev, char *file, Boolean probe)
91 {
92 FILE *fp;
93 int rv, s, af;
94 bool el; /* end of header line */
95 char *cp, buf[PATH_MAX], req[BUFSIZ];
96 struct addrinfo hints, *res, *res0;
97
98 af = variable_cmp(VAR_IPV6_ENABLE, "YES") ? AF_INET : AF_UNSPEC;
99 memset(&hints, 0, sizeof(hints));
100 hints.ai_family = af;
101 hints.ai_socktype = SOCK_STREAM;
102 hints.ai_protocol = 0;
103 if ((rv = getaddrinfo(variable_get(VAR_HTTP_HOST),
104 variable_get(VAR_HTTP_PORT), &hints, &res0)) != 0) {
105 msgConfirm("%s", gai_strerror(rv));
106 return NULL;
107 }
108 s = -1;
109 for (res = res0; res; res = res->ai_next) {
110 if ((s = socket(res->ai_family, res->ai_socktype,
111 res->ai_protocol)) < 0)
112 continue;
113 if (connect(s, res->ai_addr, res->ai_addrlen) >= 0)
114 break;
115 close(s);
116 s = -1;
117 }
118 freeaddrinfo(res0);
119 if (s == -1) {
120 msgConfirm("Couldn't connect to http://%s:%s/",
121 variable_get(VAR_HTTP_HOST),variable_get(VAR_HTTP_PORT));
122 return NULL;
123 }
124
125 sprintf(req,"GET /%s/%s HTTP/1.0\r\n\r\n",
126 variable_get(VAR_HTTP_PATH), file);
127
128 if (isDebug()) {
129 msgDebug("sending http request: %s\n",req);
130 }
131 write(s,req,strlen(req));
132
133 /*
134 * scan the headers of the response
135 * this is extremely quick'n dirty
136 *
137 */
138 cp=buf;
139 el=FALSE;
140 rv=read(s,cp,1);
141 while (rv>0) {
142 if ((*cp == '\012') && el) {
143 /* reached end of a header line */
144 if (!strncmp(buf,"HTTP",4)) {
145 rv=strtol((char *)(buf+9),0,0);
146 *(cp-1)='\0'; /* chop the CRLF off */
147 if (probe && (rv != 200)) {
148 return NULL;
149 } else if (rv >= 500) {
150 msgConfirm("Server error %s when sending %s, you could try an other server",buf, req);
151 return NULL;
152 } else if (rv == 404) {
153 msgConfirm("%s was not found, maybe directory or release-version are wrong?",req);
154 return NULL;
155 } else if (rv >= 400) {
156 msgConfirm("Client error %s, you could try an other server",buf);
157 return NULL;
158 } else if (rv >= 300) {
159 msgConfirm("Error %s",buf);
160 return NULL;
161 } else if (rv != 200) {
162 msgConfirm("Error %s when sending %s, you could try an other server",buf, req);
163 return NULL;
164 }
165 }
166 /* ignore other headers */
167 /* check for "\015\012" at beginning of line, i.e. end of headers */
168 if ((cp-buf) == 1)
169 break;
170 cp=buf;
171 rv=read(s,cp,1);
172 } else {
173 el=FALSE;
174 if (*cp == '\015')
175 el=TRUE;
176 cp++;
177 rv=read(s,cp,1);
178 }
179 }
180 fp=fdopen(s,"r");
181 return fp;
182 }
183