1 2 /* 3 * Network related functions 4 */ 5 #include <sys/types.h> 6 #include <sys/stat.h> 7 #include <stdarg.h> 8 #include <unistd.h> 9 #include <fcntl.h> 10 #include "conf.h" 11 #include "opennet.h" 12 13 #ifndef NO_NETWORK 14 #include <sys/socket.h> 15 #include <netinet/in.h> 16 #include <arpa/inet.h> 17 #include <stdlib.h> 18 #include <string.h> 19 #include <netdb.h> 20 #include <errno.h> 21 #include <stdio.h> 22 #include "parse.h" 23 #include "crc.h" 24 25 extern int errno; 26 char *opennet_urls[256]; 27 28 /* 29 * Create a listening port on tcp port PORT 30 */ 31 int createlisten(int port) 32 { 33 struct sockaddr_in localname; 34 int sockFd; 35 sockFd=socket(AF_INET,SOCK_STREAM,IPPROTO_IP); 36 localname.sin_family=AF_INET; 37 localname.sin_port=htons(port); 38 localname.sin_addr.s_addr=INADDR_ANY; 39 if (bind(sockFd,(struct sockaddr *) & localname,sizeof(localname))==-1) { perror("bind");return(-1); } 40 if (listen(sockFd,1024)==-1) { perror("listen"); return(-1); } 41 return(sockFd); 42 } 43 44 45 /* 46 * Close that socket, yeah. 47 */ 48 void closeconnection(int sockfd) { 49 shutdown(sockfd, 1); 50 close(sockfd); 51 } 52 53 int createconnection_tcp(char *host, int port) { 54 int sockid; 55 struct hostent *hostinfo; 56 struct sockaddr_in sock; 57 if ((hostinfo=gethostbyname(host))==NULL) { 58 #ifdef HAVE_INET_ATON 59 if (!inet_aton(host,&sock.sin_addr)) 60 #else 61 if ( (sock.sin_addr.s_addr=inet_addr(host) )==-1) 62 #endif 63 return(-1); 64 } else { 65 memcpy(&sock.sin_addr.s_addr,hostinfo->h_addr_list[0],hostinfo->h_length); 66 } 67 sock.sin_family=AF_INET; 68 sock.sin_port=htons(port); 69 if ((sockid=socket(AF_INET, SOCK_STREAM, 0))<0) 70 return(-1); 71 if (connect(sockid, (struct sockaddr *) &sock, sizeof(sock))<0) { 72 close(sockid); 73 return(-1); 74 } 75 return(sockid); 76 } 77 78 int open_net(const char *pathname, int flags, ...) { 79 char scheme[5], host[512], file[1024]; 80 char username[128], password[128]; 81 char *read_buf, *read_buf_s=NULL; 82 char *smallbuf, *tmpbuf; 83 int port, fd, x, ftpfd=-1, retrmode=0; 84 va_list args; 85 mode_t mode; 86 87 va_start(args, flags); 88 mode = va_arg(args, mode_t); 89 va_end(args); 90 91 if (!parse_url(pathname,scheme,username,password,host,&port,file)) { 92 if ((fd=createconnection_tcp(host,port))<0) return(-1); 93 94 switch (ELFCRC(0, scheme, strlen(scheme))) { 95 case 457648: /* http */ 96 if ((flags&3)==O_WRONLY || (flags&3)==O_RDWR) { 97 close(fd); 98 return(-1); 99 } 100 read_buf_s=read_buf=malloc(50); 101 write(fd, "GET ", 4); 102 write(fd, file, strlen(file)); 103 write(fd, " HTTP/1.0\nHost: ",16); 104 write(fd, host, strlen(host)); 105 write(fd, "\n", 1); 106 if (strcmp(username, "")) { 107 smallbuf=malloc(strlen(password)+strlen(username)+3); 108 smallbuf[0]=0; 109 strcat(smallbuf,username); 110 strcat(smallbuf,":"); 111 strcat(smallbuf,password); 112 tmpbuf=mime64(smallbuf); 113 write(fd, "Authorization: Basic ", 21); 114 write(fd, tmpbuf, strlen(tmpbuf)); 115 free(tmpbuf); 116 free(smallbuf); 117 write(fd, "\n", 1); 118 } 119 write(fd, "\n", 1); 120 x=read(fd, read_buf, 50); 121 strsep(&read_buf," "); 122 if (strncmp("200 ",read_buf,4) && strncmp("302 ",read_buf,4)) { 123 free(read_buf_s); 124 close(fd); 125 errno=ENOENT; 126 return(-1); 127 } 128 retrmode=read_buf[0]; 129 read_buf=read_buf_s; 130 read_buf[4]=0; 131 while (1) { 132 read(fd, read_buf, 1); 133 if (read_buf[0]==read_buf[2]&&read_buf[0]=='\n') break; 134 if (!strncmp(":noi", read_buf, 4) && retrmode=='3') { 135 tmpbuf=smallbuf=malloc(512); 136 read(fd, read_buf, 1); 137 read(fd, smallbuf, 510); 138 close(fd); 139 return(open_net(strsep(&smallbuf,"\r\n"),flags,mode)); 140 free(tmpbuf); 141 } 142 read_buf[3]=read_buf[2]; 143 read_buf[2]=read_buf[1]; 144 read_buf[1]=read_buf[0]; 145 } 146 147 free(read_buf_s); 148 149 if (opennet_urls[fd]!=NULL) free(opennet_urls[fd]); 150 opennet_urls[fd]=strdup(pathname); 151 return(fd); 152 break; 153 case 28080: /* ftp */ 154 if ((flags&3)==O_RDWR) { 155 close(fd); 156 return(-1); 157 } 158 159 read_buf_s=read_buf=malloc(1024); 160 read_buf[0]=0; 161 162 while (1) { 163 if ((x=read(fd, read_buf, 1024))<1024) { 164 if (x<0) { 165 free(read_buf_s); 166 errno=EIO; 167 return(-1); 168 } 169 /* It's waiting for input... */ 170 } 171 read_buf[x]=0; 172 173 while ((smallbuf=strsep(&read_buf,"\n"))!=NULL) { 174 switch (ELFCRC(0, smallbuf, 4)) { 175 case 231456: /* 550 */ 176 if (ftpfd!=-1) close(ftpfd); 177 close(fd); 178 free(read_buf_s); 179 errno=ENOENT; 180 return(-1); 181 break; 182 case 230944: /* 530 */ 183 if (ftpfd!=-1) close(ftpfd); 184 close(fd); 185 free(read_buf_s); 186 errno=EIO; 187 return(-1); 188 break; 189 case 231504: /* 553 */ 190 if (ftpfd!=-1) close(ftpfd); 191 close(fd); 192 free(read_buf_s); 193 errno=EPERM; 194 return(-1); 195 break; 196 case 218400: /* 220 */ 197 write(fd, "USER ", 5); 198 if (strcmp(username,"")) { 199 write(fd, username, strlen(username)); 200 } else { 201 write(fd, "anonymous", 9); 202 } 203 write(fd, "\n", 1); 204 break; 205 case 222768: /* 331 */ 206 write(fd, "PASS ", 5); 207 if (strcmp(password,"")) { 208 write(fd, password, strlen(password)); 209 } else { 210 write(fd, "user@host.com", 13); 211 } 212 write(fd, "\n", 1); 213 break; 214 case 218512: /* 227 */ 215 strsep(&smallbuf,"("); 216 host[0]=0; 217 for (x=0;x<4;x++) { 218 strncat(host,strsep(&smallbuf,","),5); 219 strcat(host,"."); 220 } 221 host[strlen(host)-1]=0; 222 port=(atoi(strsep(&smallbuf,","))<<8)+atoi(strsep(&smallbuf,")\n\r ")); 223 write(fd, "TYPE I\n", 7); 224 break; 225 case 217888: 226 if ((flags&3)==O_RDONLY) write(fd,"RETR ",5); 227 if ((flags&3)==O_WRONLY) write(fd,"STOR ",5); 228 write(fd, file, strlen(file)); 229 write(fd, "\n", 1); 230 if ((ftpfd=createconnection_tcp(host,port))<0) { 231 close(fd); 232 errno=ENOENT; 233 return(-1); 234 } 235 break; 236 case 215072: /* 150 */ 237 if (opennet_urls[ftpfd]!=NULL) free(opennet_urls[ftpfd]); 238 opennet_urls[ftpfd]=strdup(pathname); 239 return(ftpfd); 240 break; 241 case 218656: /* 230 */ 242 write(fd, "PASV\n", 5); 243 break; 244 default: 245 break; 246 } 247 } 248 read_buf=read_buf_s; 249 } 250 251 252 break; 253 } 254 255 free(read_buf_s); 256 close(fd); 257 } else { 258 fd=open(pathname,flags,mode); 259 if (opennet_urls[fd]!=NULL) free(opennet_urls[fd]); 260 opennet_urls[fd]=strdup(pathname); 261 return(fd); 262 } 263 264 return(-1); 265 } 266 267 off_t lseek_net(int filedes, off_t offset, int whence) { 268 struct stat file_status; 269 int newfd; 270 271 fstat(filedes, &file_status); 272 if (S_ISSOCK(file_status.st_mode)) { 273 if (whence==SEEK_END) return(-1); 274 if (offset!=0 || whence!=SEEK_SET) return(-1); /* For now ... */ 275 if ((newfd=open_net(opennet_urls[filedes],O_RDONLY))<0) return(-1); 276 close(filedes); 277 dup2(newfd,filedes); 278 return(0); 279 } 280 return(lseek(filedes,offset,whence)); 281 } 282 283 #else 284 int createlisten(int port) { return(-1); } 285 void closeconnection(int sockfd) { return; } 286 int createconnection_tcp(char *host, int port) { return(-1); } 287 int open_net(const char *pathname, int flags,...) { 288 va_list args; 289 mode_t mode; 290 291 va_start(args, flags); 292 mode = va_arg(args, mode_t); 293 va_end(args); 294 295 return(open(pathname,flags,mode)); 296 } 297 off_t lseek_net(int filedes, off_t offset, int whence) { 298 return(lseek(filedes,offset,whence)); 299 } 300 #endif |