-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmain.c
More file actions
132 lines (108 loc) · 2.73 KB
/
main.c
File metadata and controls
132 lines (108 loc) · 2.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#define _GNU_SOURCE
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/sendfile.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <sched.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#define THREADS 32
#define MAXWAIT 128
#define STACKSIZE 65536
#define FILESIZE (32000 * 65536)
struct thread {
pid_t pid;
int fd;
};
struct thread threads[THREADS];
int sockfd;
char *path;
int contentfd;
#define info (*((struct thread *) data))
int thr(void *data) {
off_t zero;
char req[4096];
int len;
char *nlnl;
while (1) {
info.fd = accept(sockfd, NULL, NULL);
*(uint32_t *)req = 0;
while((len = read(info.fd, req + 4, sizeof(req) - 8)) > 0) {
for(nlnl = req; nlnl < req + len + 4; ++nlnl) {
if(*(uint16_t *)nlnl == 0x0A0A) goto req_complete;
if(*(uint32_t *)nlnl == 0x0A0D0A0Dul) goto req_complete;
}
*(uint32_t *)req = *(uint32_t *)(req + len);
}
req_complete:
zero = 0;
sendfile(info.fd, contentfd, &zero, FILESIZE);
shutdown(info.fd, SHUT_WR);
close(info.fd);
}
return 0;
}
void term(int no_use) {
exit(0);
}
int main(int argc, char *argv[]) {
struct sockaddr_in6 http_addr;
int nt;
char *stack;
int yes = 1;
int port;
if((contentfd = open(path, O_RDONLY)) < 0) {
fprintf(stderr, "could not open path to serve\n");
exit(1);
}
if(setuid(65535) < 0) {
fprintf(stderr, "setuid failed\n");
return 1;
}
if(argc != 3) {
fprintf(stderr, "Usage: sfhttpd <port> <file>\n");
return 1;
}
if(sscanf(argv[1], "%d", &port) != 1) {
fprintf(stderr, "Usage: sfhttpd <port> <file>\n");
return 1;
}
path = argv[2];
http_addr.sin6_family = AF_INET6;
http_addr.sin6_port = htons(port);
memcpy(&http_addr.sin6_addr.s6_addr, &in6addr_any, 16);
if ((sockfd = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP)) < 0) {
fprintf(stderr, "could not create socket\n");
return 1;
}
if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) < 0) {
fprintf(stderr, "could not set SO_REUSEADDR");
return 1;
}
if (bind(sockfd, (struct sockaddr *) &http_addr, sizeof(http_addr)) < 0) {
fprintf(stderr, "could not bind to port %d\n", port);
return 1;
}
if (listen(sockfd, MAXWAIT) < 0) {
fprintf(stderr, "could not listen\n");
return 1;
}
signal(SIGINT, term);
signal(SIGPIPE, SIG_IGN);
stack = malloc(THREADS * STACKSIZE);
for (nt = 0; nt < THREADS; nt++) {
if ((threads[nt].pid = clone(thr, stack += STACKSIZE,
CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_VM,
threads + nt)) < 0) {
fprintf(stderr, "thread creation failed\n");
return 1;
}
}
pause();
return 0;
}