summaryrefslogtreecommitdiff
path: root/other/fizzbounce/network.c
diff options
context:
space:
mode:
Diffstat (limited to 'other/fizzbounce/network.c')
-rw-r--r--other/fizzbounce/network.c691
1 files changed, 691 insertions, 0 deletions
diff --git a/other/fizzbounce/network.c b/other/fizzbounce/network.c
new file mode 100644
index 0000000..5e73e5c
--- /dev/null
+++ b/other/fizzbounce/network.c
@@ -0,0 +1,691 @@
1
2/* scut's leet network library ;)
3 * 1999 (c) scut
4 *
5 * networking routines
6 * based on my hbot networking sources,
7 * revised, extended and adapted 990405
8 * extended, improved and fixed 990430
9 *
10 * nearly all of this code wouldn't have been possible without w. richard stevens
11 * excellent network coding book. if you are interested in network coding,
12 * there is no way around it.
13 */
14
15#include <sys/ioctl.h>
16#include <sys/socket.h>
17#include <sys/time.h>
18#include <sys/types.h>
19#include <arpa/inet.h>
20#include <netdb.h>
21#include <net/if.h>
22#include <netinet/in.h>
23#include <errno.h>
24#include <fcntl.h>
25#include <stdarg.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <unistd.h>
30#include "network.h"
31
32int net_readtimeout = NET_READTIMEOUT;
33int net_conntimeout = NET_CONNTIMEOUT;
34int net_identtimeout = NET_IDENTTIMEOUT;
35
36int
37net_socks_connect (char *socks, unsigned short int sport, char *server, unsigned short int port, int sec)
38{
39 int s5s;
40 struct sockaddr_in cs;
41
42 s5s = net_connect (&cs, socks, sport, sec);
43 if (s5s == -1)
44 return (-1);
45
46 if (net_socks_put_s5info (s5s, server, port, sec) == -1) {
47 close (s5s);
48 return (-1);
49 }
50 return (s5s);
51}
52
53int
54net_socks_put_s5info (int s5s, char *server, unsigned short int port, int sec)
55{
56 int n;
57 char buff[1024];
58
59 /* v5 + noauth */
60 net_write (s5s, "\x05\x01%c", 0);
61 if (net_rtimeout (s5s, sec) == -1)
62 return (-1);
63 recv (s5s, buff, sizeof (buff), 0);
64
65 /* chain us =) */
66 net_write (s5s, "\x05\x01%c\x03%c%s%c%c", 0, strlen (server), server, (port >> 8) & 0xff, port & 0xff);
67 if (net_rtimeout (s5s, sec) == -1)
68 return (-1);
69 n = recv (s5s, buff, sizeof (buff), 0);
70 if (buff[1] != 0x00) {
71 return (-1);
72 }
73 return (1);
74}
75
76int
77net_parseip (char *inp, char **ip, unsigned short int *port)
78{
79 int n;
80
81 if (inp == NULL)
82 return (0);
83 if (strchr (inp, ':') == NULL)
84 return (0);
85
86 n = sscanf (inp, "%a[^:]:%hu", ip, port);
87 if (n != 2)
88 return (0);
89
90 if (*ip == NULL || (*port < 1 || *port > 65535))
91 return (0);
92
93 return (1);
94}
95
96char *
97net_getlocalip (void)
98{
99 struct sockaddr_in pf;
100 char name[255];
101
102 memset (name, '\0', sizeof (name));
103
104 if (gethostname (name, sizeof (name) - 1) == -1) {
105 return (NULL);
106 }
107
108 pf.sin_addr.s_addr = net_resolve (name);
109
110 return (strdup (inet_ntoa (pf.sin_addr)));;
111}
112
113FILE *
114net_descriptify (int socket)
115{
116 FILE *fp;
117
118 fp = fdopen (socket, "r+");
119 return ((fp == NULL) ? (NULL) : (fp));
120}
121
122/* loosely based on rfc931.c */
123
124int
125net_ident (char **ident, struct sockaddr_in *locals, unsigned short int localport,
126 struct sockaddr_in *remotes, unsigned short int remoteport)
127{
128 int is; /* ident socket */
129 struct sockaddr_in isa;
130 int n;
131 char identreply[512], *cp;
132 unsigned int rmt_port, our_port;
133
134
135 *ident = NULL;
136
137 is = net_connect (&isa, inet_ntoa (remotes->sin_addr), 113, net_identtimeout);
138 if (is == -1)
139 return (-1);
140
141 /* ident request */
142 net_write (is, "%u,%u\r\n", remoteport, localport);
143 memset (identreply, '\0', sizeof (identreply));
144
145 n = net_rlinet (is, identreply, sizeof(identreply) -1, net_identtimeout);
146 if (n == -1) {
147 close (is);
148 return (-1);
149 }
150 close (is);
151
152 *ident = calloc (1, 256);
153#ifdef DEBUG
154 printf("%s\n", identreply);
155#endif
156 n = sscanf (identreply, "%u , %u : USERID :%*[^:]:%255s", &rmt_port, &our_port, *ident);
157 if (n != 3) {
158 free (*ident);
159 *ident = NULL;
160 return (-1);
161 }
162
163 /* check the ports 'man */
164 if ((rmt_port != remoteport) || (our_port != localport)) {
165 free (*ident);
166 *ident = NULL;
167 return (-1);
168 }
169
170 /* strip character and save some memory */
171 if ((cp = strchr (*ident, '\r')))
172 *cp = '\0';
173 n = strlen (*ident);
174 *ident = realloc (*ident, n + 1);
175 (*ident)[n] = '\0';
176
177#ifdef DEBUG
178 printf("ident-return: %s\n", *ident);
179#endif
180 return (1);
181}
182
183
184int
185net_accept (int s, struct sockaddr_in *cs, int maxsec)
186{
187 int flags, n;
188 fd_set ac_s;
189 int len;
190 struct timeval tval;
191
192 flags = fcntl(s, F_GETFL, 0);
193 if (flags == -1)
194 return (-1);
195 n = fcntl(s, F_SETFL, flags | O_NONBLOCK);
196 if (flags == -1)
197 return (-1);
198
199 FD_ZERO(&ac_s);
200 FD_SET(s, &ac_s);
201 tval.tv_sec = maxsec;
202 tval.tv_usec = 0;
203
204 n = select(s + 1, &ac_s, NULL, NULL, maxsec ? &tval : NULL);
205 if (n == 0)
206 return (0);
207
208 if (FD_ISSET(s, &ac_s)) {
209 len = sizeof(struct sockaddr_in);
210 n = accept(s, (struct sockaddr *) cs, &len);
211 if (n == -1) {
212 switch (errno) {
213 case EWOULDBLOCK:
214 case ECONNABORTED:
215 case EPROTO:
216 case EINTR: if (fcntl(s, F_SETFL, flags) == -1)
217 return (-1);
218 return (0);
219 default: return (-1);
220 }
221 }
222 if (fcntl(s, F_SETFL, flags) == -1)
223 return (-1);
224 return (n);
225 }
226 if (fcntl(s, F_SETFL, flags) == -1)
227 return (-1);
228 return (0);
229}
230
231int
232net_testvip (char *ip)
233{
234 struct ifi_info *ifi, *ifc;
235 struct in_addr ip_n;
236
237 if (ip == NULL)
238 return (1);
239 if (strcmp(ip, "*") == 0)
240 return (1);
241
242 ip_n.s_addr = net_resolve(ip);
243 if (!(ip_n.s_addr))
244 return (0);
245
246 ifi = net_ifi_get (AF_INET, 1);
247 if (ifi == NULL)
248 return (0);
249 for (ifc = ifi; ifc != NULL; ifc = ifc->ifi_next) {
250 if (memcmp(&ip_n.s_addr, &ifc->ifi_saddr.s_addr, sizeof(struct in_addr)) == 0) {
251 net_ifi_free(ifi);
252 return (1);
253 }
254 }
255 net_ifi_free(ifi);
256 return (0);
257}
258
259void
260net_ifi_free (struct ifi_info *tf)
261{
262 struct ifi_info *ifi, *ifil;
263
264 ifil = NULL;
265 for (ifi = tf; ifi != NULL; ifi = ifi->ifi_next) {
266 if (ifil)
267 free (ifil);
268 if (ifi->ifi_addr)
269 free (ifi->ifi_addr);
270 ifil = ifi;
271 }
272 if (ifil)
273 free (ifil);
274 return;
275}
276
277struct ifi_info *
278net_ifi_get (int family, int doaliases)
279{
280 struct ifi_info *ifi, *ifihead, **ifipnext;
281 int sockfd, len, lastlen, flags, myflags;
282 char *ptr, *buf, lastname[IFNAMSIZ], *cptr;
283 struct ifconf ifc;
284 struct ifreq *ifr, ifrcopy;
285 struct sockaddr_in *sinptr;
286
287 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
288 if (sockfd == -1)
289 return (NULL);
290
291 lastlen = 0;
292 len = 100 * sizeof(struct ifreq);
293 for (;;) {
294 buf = malloc(len);
295 if (buf == NULL)
296 return (NULL);
297 ifc.ifc_len = len;
298 ifc.ifc_buf = buf;
299 if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
300 if (errno != EINVAL || lastlen != 0)
301 return (NULL);
302 } else {
303 if (ifc.ifc_len == lastlen)
304 break;
305 lastlen = ifc.ifc_len;
306 }
307 len += 10 * sizeof(struct ifreq);
308 free (buf);
309 }
310 ifihead = NULL;
311 ifipnext = &ifihead;
312 lastname[0] = 0;
313
314 for (ptr = buf; ptr < buf + ifc.ifc_len;) {
315 ifr = (struct ifreq *) ptr;
316 if (ifr->ifr_addr.sa_family == AF_INET)
317 len = sizeof(struct sockaddr);
318 ptr += sizeof(ifr->ifr_name) + len;
319
320 if (ifr->ifr_addr.sa_family != family)
321 continue;
322 myflags = 0;
323 if ((cptr = strchr(ifr->ifr_name, ':')) != NULL)
324 *cptr = 0;
325 if (strncmp(lastname, ifr->ifr_name, IFNAMSIZ) == 0) {
326 if (doaliases == 0)
327 continue;
328 myflags = IFI_ALIAS;
329 }
330 memcpy(lastname, ifr->ifr_name, IFNAMSIZ);
331
332 ifrcopy = *ifr;
333 if (ioctl(sockfd, SIOCGIFFLAGS, &ifrcopy) < 0)
334 return (NULL);
335 flags = ifrcopy.ifr_flags;
336 if ((flags & IFF_UP) == 0)
337 continue;
338
339 ifi = calloc(1, sizeof(struct ifi_info));
340 if (ifi == NULL)
341 return (NULL);
342 *ifipnext = ifi;
343 ifipnext = &ifi->ifi_next;
344 ifi->ifi_flags = flags;
345 ifi->ifi_myflags = myflags;
346 memcpy(ifi->ifi_name, ifr->ifr_name, IFI_NAME);
347 ifi->ifi_name[IFI_NAME - 1] = '\0';
348
349#ifdef DEBUG
350 printf("got: %s\n", ifi->ifi_name);
351#endif
352
353 switch (ifr->ifr_addr.sa_family) {
354 case AF_INET:
355 sinptr = (struct sockaddr_in *) &ifr->ifr_addr;
356 memcpy(&ifi->ifi_saddr, &sinptr->sin_addr, sizeof(struct in_addr));
357 if (ifi->ifi_addr == NULL) {
358 ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in));
359 if (ifi->ifi_addr == NULL)
360 return (NULL);
361 memcpy(ifi->ifi_addr, sinptr, sizeof(struct sockaddr_in));
362 }
363 break;
364 default:
365 break;
366 }
367 }
368 free (buf);
369 return (ifihead);
370}
371
372void
373net_boundfree (bound *bf)
374{
375 close (bf->bs);
376 free(bf);
377 return;
378}
379
380bound *
381net_bind (char *ip, unsigned short int port)
382{
383 bound *b;
384 int br, gsnr, lr;
385 int len;
386 struct sockaddr_in *sap;
387
388 if (port >= 65536)
389 return (NULL);
390
391 b = calloc(1, sizeof(bound));
392 if (b == NULL)
393 return (NULL);
394 b->bs = socket(AF_INET, SOCK_STREAM, 0);
395 if (b->bs == -1)
396 goto berror;
397
398 sap = (struct sockaddr_in *) &b->bsa;
399 sap->sin_family = AF_INET;
400 sap->sin_port = htons(port); /* 0 = ephemeral */
401
402 if (ip != NULL) {
403 if (strcmp(ip,"*") == 0) {
404 sap->sin_addr.s_addr = htonl(INADDR_ANY);
405 } else {
406 if (!(sap->sin_addr.s_addr = net_resolve(ip))) {
407 goto berror;
408 }
409 }
410 } else {
411 sap->sin_addr.s_addr = htonl(INADDR_ANY);
412 }
413
414 br = bind(b->bs, (struct sockaddr *) &b->bsa, sizeof(struct sockaddr));
415 if (br == -1)
416 goto berror;
417
418 len = sizeof(struct sockaddr);
419 gsnr = getsockname(b->bs, (struct sockaddr *) &b->bsa, &len);
420 b->port = ntohs(sap->sin_port);
421 if (gsnr == -1)
422 goto berror;
423
424 lr = listen(b->bs, 16);
425 if (lr == -1) {
426 goto berror;
427 }
428 return (b);
429
430berror:
431 free(b);
432
433 return(NULL);
434}
435
436unsigned long int
437net_resolve (char *host)
438{
439 long i;
440 struct hostent *he;
441
442 i = inet_addr(host);
443 if (i == -1) {
444 he = gethostbyname(host);
445 if (he == NULL) {
446 return (0);
447 } else {
448 return (*(unsigned long *) he->h_addr);
449 }
450 }
451 return (i);
452}
453
454int
455net_connect (struct sockaddr_in *cs, char *server, unsigned short int port, int sec)
456{
457 int n, len, error, flags;
458 int fd;
459 struct timeval tv;
460 fd_set rset, wset;
461
462 if (!(cs->sin_addr.s_addr = net_resolve(server))) {
463 return (-1);
464 }
465 cs->sin_family = AF_INET;
466 cs->sin_port = htons(port);
467
468 fd = socket(cs->sin_family, SOCK_STREAM, 0);
469 if (fd == -1)
470 return (-1);
471
472 flags = fcntl(fd, F_GETFL, 0);
473 if (flags == -1)
474 return (-1);
475 n = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
476 if (n == -1)
477 return (-1);
478
479 error = 0;
480
481 n = connect(fd, (struct sockaddr *) cs, sizeof(struct sockaddr_in));
482 if (n < 0) {
483 if (errno != EINPROGRESS) {
484 return (-1);
485 }
486 }
487 if (n == 0)
488 goto done;
489
490 FD_ZERO(&rset);
491 FD_ZERO(&wset);
492 FD_SET(fd, &rset);
493 FD_SET(fd, &wset);
494 tv.tv_sec = sec;
495 tv.tv_usec = 0;
496
497 n = select(fd + 1, &rset, &wset, NULL, &tv);
498 if (n == 0) {
499 close(fd);
500 errno = ETIMEDOUT;
501 return (-1);
502 }
503 if (n == -1)
504 return (-1);
505
506 if (FD_ISSET(fd, &rset) || FD_ISSET(fd, &wset)) {
507 if (FD_ISSET(fd, &rset) && FD_ISSET(fd, &wset)) {
508 len = sizeof(error);
509 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
510 errno = ETIMEDOUT;
511 return (-1);
512 }
513 if (error == 0) {
514 goto done;
515 } else {
516 errno = error;
517 return (-1);
518 }
519 }
520 } else
521 return (-1);
522
523done:
524 n = fcntl(fd, F_SETFL, flags);
525 if (n == -1)
526 return (-1);
527 return (fd);
528}
529
530int
531net_tline (char *buf, int bufsize)
532{
533 int p;
534
535 for (p = 0; p < bufsize; p++) {
536 if (buf[p] == '\n')
537 return (p + 1);
538 }
539 return (-1);
540}
541
542int
543net_rlinet (int fd, char *buf, int bufsize, int sec)
544{
545 int n;
546 unsigned long int rb = 0;
547 struct timeval tv_start, tv_cur;
548
549 memset(buf, '\0', bufsize);
550 (void) gettimeofday(&tv_start, NULL);
551
552 do {
553 (void) gettimeofday(&tv_cur, NULL);
554 if (sec > 0) {
555 if ((((tv_cur.tv_sec * 1000000) + (tv_cur.tv_usec)) -
556 ((tv_start.tv_sec * 1000000) + (tv_start.tv_usec))) > (sec * 1000000)) {
557 return (-1);
558 }
559 }
560 n = net_rtimeout(fd, net_readtimeout);
561 if (n <= 0) {
562 return (-1);
563 }
564 n = read(fd, buf, 1);
565 if (n <= 0) {
566 return (n);
567 }
568 rb++;
569 if (*buf == '\n')
570 return (rb);
571 buf++;
572 if (rb >= bufsize)
573 return (-1);
574 } while (1);
575}
576
577long int
578net_rbuf (int fd, char **dst)
579{
580 long int ml = 0;
581 long int read_bytes;
582 int p;
583
584 while ((p = net_rtimeout(fd, net_readtimeout)) == 1) {
585 *dst = (char *) realloc(*dst, ml + NET_BSIZE);
586 if (*dst == NULL)
587 return (-1);
588 ml += read_bytes = read(fd, *dst + ml, NET_BSIZE);
589 if (read_bytes == 0) {
590 *dst = (char *) realloc(*dst, ml);
591 if ((*dst == NULL) && (ml == 0)) {
592 return (1);
593 } else if (*dst == NULL) {
594 return (-1);
595 } else {
596 return (ml);
597 }
598 }
599 }
600 return (-1);
601}
602
603int
604net_rbuft (int fd, char *dst, unsigned long int dsize)
605{
606 unsigned long int bl = 0, m;
607 int p;
608
609 while (bl < dsize) {
610 p = net_rtimeout(fd, net_readtimeout);
611 if ((p == 0) || (p == -1)) {
612 return (-1);
613 }
614
615 m = read(fd, dst + bl, (dsize - bl));
616 if ((m == 0) || (m == -1)) {
617 return (-1);
618 }
619 bl += m;
620 }
621 return (1);
622}
623
624int
625net_rtimeout (int fd, int sec)
626{
627 fd_set rset;
628 struct timeval tv;
629 int n, error, flags;
630
631 error = 0;
632 flags = fcntl(fd, F_GETFL, 0);
633 n = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
634 if (n == -1)
635 return (-1);
636
637 FD_ZERO(&rset);
638 FD_SET(fd, &rset);
639 tv.tv_sec = sec;
640 tv.tv_usec = 0;
641
642 /* now we wait until more data is received then the tcp low level watermark,
643 * which should be setted to 1 in this case (1 is default)
644 */
645
646 n = select(fd + 1, &rset, NULL, NULL, &tv);
647 if (n == 0) {
648 n = fcntl(fd, F_SETFL, flags);
649 if (n == -1)
650 return (-1);
651 errno = ETIMEDOUT;
652 return (-1);
653 }
654 if (n == -1) {
655 return (-1);
656 }
657 /* socket readable ? */
658 if (FD_ISSET(fd, &rset)) {
659 n = fcntl(fd, F_SETFL, flags);
660 if (n == -1)
661 return (-1);
662 return (1);
663 } else {
664 n = fcntl(fd, F_SETFL, flags);
665 if (n == -1)
666 return (-1);
667 errno = ETIMEDOUT;
668 return (-1);
669 }
670}
671
672void
673net_write (int fd, const char *str, ...)
674{
675 char tmp[1025];
676 va_list vl;
677 int i;
678
679 va_start(vl, str);
680 memset(tmp, 0, sizeof(tmp));
681 i = vsnprintf(tmp, sizeof(tmp), str, vl);
682 va_end(vl);
683
684#ifdef DEBUG
685 printf("[snd] %s\n", tmp);
686#endif
687
688 send(fd, tmp, i, 0);
689 return;
690}
691