summaryrefslogtreecommitdiff
path: root/other/zylyx/src/network.c
diff options
context:
space:
mode:
Diffstat (limited to 'other/zylyx/src/network.c')
-rw-r--r--other/zylyx/src/network.c861
1 files changed, 861 insertions, 0 deletions
diff --git a/other/zylyx/src/network.c b/other/zylyx/src/network.c
new file mode 100644
index 0000000..ab0f0f7
--- /dev/null
+++ b/other/zylyx/src/network.c
@@ -0,0 +1,861 @@
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/types.h>
16#include <sys/ioctl.h>
17#include <sys/socket.h>
18#include <sys/time.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
36
37int
38net_socks_connect (char *socks, unsigned short int sport, char *server, unsigned short int port, int sec)
39{
40 int s5s;
41 struct sockaddr_in cs;
42
43 s5s = net_connect (&cs, socks, sport, NULL, 0, sec);
44 if (s5s == -1)
45 return (-1);
46
47 if (net_socks_put_s5info (s5s, server, port, sec) == -1) {
48 close (s5s);
49 return (-1);
50 }
51 return (s5s);
52}
53
54
55int
56net_socks_put_s5info (int s5s, char *server, unsigned short int port, int sec)
57{
58 int n;
59 char buff[1024];
60
61 /* v5 + noauth */
62 net_write (s5s, "\x05\x01%c", 0);
63 if (net_rtimeout (s5s, sec) == -1)
64 return (-1);
65 recv (s5s, buff, sizeof (buff), 0);
66
67 /* chain us =) */
68 net_write (s5s, "\x05\x01%c\x03%c%s%c%c", 0, strlen (server), server, (port >> 8) & 0xff, port & 0xff);
69 if (net_rtimeout (s5s, sec) == -1)
70 return (-1);
71 n = recv (s5s, buff, sizeof (buff), 0);
72 if (buff[1] != 0x00) {
73 return (-1);
74 }
75 return (1);
76}
77
78
79int
80net_parseip (char *inp, char **ip, unsigned short int *port)
81{
82 int n;
83
84 if (inp == NULL)
85 return (0);
86 if (strchr (inp, ':') == NULL)
87 return (0);
88
89 *ip = calloc (1, 256);
90 if (*ip == NULL)
91 return (0);
92
93 n = sscanf (inp, "%[^:]:%hu", *ip, port);
94 if (n != 2)
95 return (0);
96
97 *ip = realloc (*ip, strlen (*ip) + 1);
98 if (*ip == NULL || (*port < 1 || *port > 65535))
99 return (0);
100
101 return (1);
102}
103
104
105char *
106net_getlocalip (void)
107{
108 struct sockaddr_in pf;
109 char name[255];
110
111 memset (name, '\0', sizeof (name));
112
113 if (gethostname (name, sizeof (name) - 1) == -1) {
114 return (NULL);
115 }
116
117 pf.sin_addr.s_addr = net_resolve (name);
118
119 return (strdup (inet_ntoa (pf.sin_addr)));;
120}
121
122
123char *
124net_peername (int socket)
125{
126 struct sockaddr_in peeraddr;
127 struct hostent he, *hep;
128 size_t size = sizeof (struct sockaddr_in);
129 int n, h_errno;
130 unsigned char h_buf[8192];
131
132 if (getpeername (socket, (struct sockaddr *) &peeraddr, &size) == -1)
133 return (NULL);
134
135 /* digital unix / hp-ux freaks mod here =)
136 */
137 n = gethostbyaddr_r ((char *) &peeraddr.sin_addr, sizeof (struct in_addr),
138 AF_INET, &he, h_buf, sizeof (h_buf), &hep, &h_errno);
139
140 if (hep == NULL) {
141 char *ip_str = NULL;
142
143 net_printipa (&peeraddr.sin_addr, &ip_str);
144 return (ip_str);
145 }
146
147 return (strdup (he.h_name));
148}
149
150
151FILE *
152net_descriptify (int socket)
153{
154 FILE *fp;
155
156 fp = fdopen (socket, "r+");
157 return ((fp == NULL) ? (NULL) : (fp));
158}
159
160
161/* loosely based on rfc931.c */
162
163int
164net_ident (char **ident, struct sockaddr_in *locals, unsigned short int localport,
165 struct sockaddr_in *remotes, unsigned short int remoteport)
166{
167 int is; /* ident socket */
168 struct sockaddr_in isa;
169 int n;
170 char identreply[512], *cp;
171 unsigned int rmt_port, our_port;
172
173
174 *ident = NULL;
175
176 is = net_connect (&isa, inet_ntoa (remotes->sin_addr), 113, NULL, 0, net_identtimeout);
177 if (is == -1)
178 return (-1);
179
180 /* ident request */
181 net_write (is, "%u,%u\r\n", remoteport, localport);
182 memset (identreply, '\0', sizeof (identreply));
183
184 n = net_rlinet (is, identreply, sizeof(identreply) -1, net_identtimeout);
185 if (n == -1) {
186 close (is);
187 return (-1);
188 }
189 close (is);
190
191 *ident = calloc (1, 256);
192#ifdef DEBUG
193 printf("%s\n", identreply);
194#endif
195 n = sscanf (identreply, "%u , %u : USERID :%*[^:]:%255s", &rmt_port, &our_port, *ident);
196 if (n != 3) {
197 free (*ident);
198 *ident = NULL;
199 return (-1);
200 }
201
202 /* check the ports 'man */
203 if ((rmt_port != remoteport) || (our_port != localport)) {
204 free (*ident);
205 *ident = NULL;
206 return (-1);
207 }
208
209 /* strip character and save some memory */
210 if ((cp = strchr (*ident, '\r')))
211 *cp = '\0';
212 n = strlen (*ident);
213 *ident = realloc (*ident, n + 1);
214 (*ident)[n] = '\0';
215
216#ifdef DEBUG
217 printf("ident-return: %s\n", *ident);
218#endif
219 return (1);
220}
221
222
223int
224net_accept (int s, struct sockaddr_in *cs, int maxsec)
225{
226 int flags, n;
227 fd_set ac_s;
228 int len;
229 struct timeval tval;
230
231 flags = fcntl(s, F_GETFL, 0);
232 if (flags == -1)
233 return (-1);
234 n = fcntl(s, F_SETFL, flags | O_NONBLOCK);
235 if (flags == -1)
236 return (-1);
237
238 FD_ZERO(&ac_s);
239 FD_SET(s, &ac_s);
240 tval.tv_sec = maxsec;
241 tval.tv_usec = 0;
242
243 n = select(s + 1, &ac_s, NULL, NULL, maxsec ? &tval : NULL);
244 if (n == 0)
245 return (0);
246
247 if (FD_ISSET(s, &ac_s)) {
248 len = sizeof(struct sockaddr_in);
249 n = accept(s, (struct sockaddr *) cs, &len);
250 if (n == -1) {
251 switch (errno) {
252 case EWOULDBLOCK:
253 case ECONNABORTED:
254 case EPROTO:
255 case EINTR: if (fcntl(s, F_SETFL, flags) == -1)
256 return (-1);
257 return (0);
258 default: return (-1);
259 }
260 }
261 if (fcntl(s, F_SETFL, flags) == -1)
262 return (-1);
263 return (n);
264 }
265 if (fcntl(s, F_SETFL, flags) == -1)
266 return (-1);
267 return (0);
268}
269
270
271int
272net_testvip (char *ip)
273{
274 struct ifi_info *ifi, *ifc;
275 struct in_addr ip_n;
276
277 if (ip == NULL)
278 return (1);
279 if (strcmp(ip, "*") == 0)
280 return (1);
281
282 ip_n.s_addr = net_resolve(ip);
283 if (!(ip_n.s_addr))
284 return (0);
285
286 ifi = net_ifi_get (AF_INET, 1);
287 if (ifi == NULL)
288 return (0);
289 for (ifc = ifi; ifc != NULL; ifc = ifc->ifi_next) {
290 if (memcmp (&ip_n.s_addr, &ifc->ifi_saddr.s_addr, sizeof (struct in_addr)) == 0) {
291 net_ifi_free(ifi);
292 return (1);
293 }
294 }
295 net_ifi_free(ifi);
296 return (0);
297}
298
299
300void
301net_ifi_free (struct ifi_info *tf)
302{
303 struct ifi_info *ifi, *ifil;
304
305 ifil = NULL;
306 for (ifi = tf; ifi != NULL; ifi = ifi->ifi_next) {
307 if (ifil)
308 free (ifil);
309 if (ifi->ifi_addr)
310 free (ifi->ifi_addr);
311 ifil = ifi;
312 }
313 if (ifil)
314 free (ifil);
315 return;
316}
317
318
319struct ifi_info *
320net_ifi_get (int family, int doaliases)
321{
322 struct ifi_info *ifi, *ifihead, **ifipnext;
323 int sockfd, len, lastlen, flags, myflags;
324 char *ptr, *buf, lastname[IFNAMSIZ], *cptr;
325 struct ifconf ifc;
326 struct ifreq *ifr, ifrcopy;
327 struct sockaddr_in *sinptr;
328
329 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
330 if (sockfd == -1)
331 return (NULL);
332
333 lastlen = 0;
334 len = 100 * sizeof(struct ifreq);
335 for (;;) {
336 buf = malloc(len);
337 if (buf == NULL)
338 return (NULL);
339 ifc.ifc_len = len;
340 ifc.ifc_buf = buf;
341 if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
342 if (errno != EINVAL || lastlen != 0)
343 return (NULL);
344 } else {
345 if (ifc.ifc_len == lastlen)
346 break;
347 lastlen = ifc.ifc_len;
348 }
349 len += 10 * sizeof(struct ifreq);
350 free (buf);
351 }
352 ifihead = NULL;
353 ifipnext = &ifihead;
354 lastname[0] = 0;
355
356 for (ptr = buf; ptr < buf + ifc.ifc_len;) {
357 ifr = (struct ifreq *) ptr;
358 if (ifr->ifr_addr.sa_family == AF_INET)
359 len = sizeof(struct sockaddr);
360 ptr += sizeof(ifr->ifr_name) + len;
361
362 if (ifr->ifr_addr.sa_family != family)
363 continue;
364 myflags = 0;
365 if ((cptr = strchr(ifr->ifr_name, ':')) != NULL)
366 *cptr = 0;
367 if (strncmp(lastname, ifr->ifr_name, IFNAMSIZ) == 0) {
368 if (doaliases == 0)
369 continue;
370 myflags = IFI_ALIAS;
371 }
372 memcpy(lastname, ifr->ifr_name, IFNAMSIZ);
373
374 ifrcopy = *ifr;
375 if (ioctl(sockfd, SIOCGIFFLAGS, &ifrcopy) < 0)
376 return (NULL);
377 flags = ifrcopy.ifr_flags;
378 if ((flags & IFF_UP) == 0)
379 continue;
380
381 ifi = calloc(1, sizeof(struct ifi_info));
382 if (ifi == NULL)
383 return (NULL);
384 *ifipnext = ifi;
385 ifipnext = &ifi->ifi_next;
386 ifi->ifi_flags = flags;
387 ifi->ifi_myflags = myflags;
388 memcpy(ifi->ifi_name, ifr->ifr_name, IFI_NAME);
389 ifi->ifi_name[IFI_NAME - 1] = '\0';
390
391#ifdef DEBUG
392 printf("got: %s\n", ifi->ifi_name);
393#endif
394
395 switch (ifr->ifr_addr.sa_family) {
396 case AF_INET:
397 sinptr = (struct sockaddr_in *) &ifr->ifr_addr;
398 memcpy(&ifi->ifi_saddr, &sinptr->sin_addr, sizeof(struct in_addr));
399 if (ifi->ifi_addr == NULL) {
400 ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in));
401 if (ifi->ifi_addr == NULL)
402 return (NULL);
403 memcpy(ifi->ifi_addr, sinptr, sizeof(struct sockaddr_in));
404 }
405 break;
406 default:
407 break;
408 }
409 }
410 free (buf);
411 return (ifihead);
412}
413
414
415void
416net_boundfree (bound *bf)
417{
418 close (bf->bs);
419 free(bf);
420 return;
421}
422
423
424bound *
425net_bind (char *ip, unsigned short int port)
426{
427 bound *b;
428 int br, gsnr, lr;
429 int len, reusetmp;
430 struct sockaddr_in *sap;
431
432 if (port >= 65536)
433 return (NULL);
434
435 b = calloc(1, sizeof (bound));
436 if (b == NULL)
437 return (NULL);
438 b->bs = socket (AF_INET, SOCK_STREAM, 0);
439 if (b->bs == -1)
440 goto berror;
441
442 reusetmp = 1;
443#ifdef SO_REUSEPORT
444 if (setsockopt (b->bs, SOL_SOCKET, SO_REUSEPORT, &reusetmp, sizeof (reusetmp)) == -1)
445 goto berror;
446#else
447 if (setsockopt (b->bs, SOL_SOCKET, SO_REUSEADDR, &reusetmp, sizeof (reusetmp)) == -1)
448 goto berror;
449#endif
450
451 sap = (struct sockaddr_in *) &b->bsa;
452 sap->sin_family = AF_INET;
453 sap->sin_port = htons (port); /* 0 = ephemeral */
454
455 if (ip != NULL) {
456 if (strcmp (ip, "*") == 0) {
457 sap->sin_addr.s_addr = htonl (INADDR_ANY);
458 } else {
459 if (!(sap->sin_addr.s_addr = net_resolve (ip))) {
460 goto berror;
461 }
462 }
463 } else {
464 sap->sin_addr.s_addr = htonl (INADDR_ANY);
465 }
466
467 br = bind (b->bs, (struct sockaddr *) &b->bsa, sizeof (struct sockaddr));
468 if (br == -1)
469 goto berror;
470
471 len = sizeof (struct sockaddr);
472 gsnr = getsockname (b->bs, (struct sockaddr *) &b->bsa, &len);
473 b->port = ntohs (sap->sin_port);
474 if (gsnr == -1)
475 goto berror;
476
477 lr = listen (b->bs, 16);
478 if (lr == -1) {
479 goto berror;
480 }
481 return (b);
482
483berror:
484 free(b);
485
486 return(NULL);
487}
488
489
490unsigned long int
491net_resolve (char *host)
492{
493 long i;
494 struct hostent *he;
495
496 i = inet_addr(host);
497 if (i == -1) {
498 he = gethostbyname(host);
499 if (he == NULL) {
500 return (0);
501 } else {
502 return (*(unsigned long *) he->h_addr);
503 }
504 }
505 return (i);
506}
507
508
509int
510net_assignaddr (int sd, char *sourceip, unsigned short int sourceport)
511{
512 struct sockaddr_in sourcedef;
513
514 if (sourceip && strcmp (sourceip, "*") == 0)
515 sourceip = NULL;
516
517 if (sourceip == NULL && sourceport == 0)
518 return (1);
519
520 /* is the IP available on the local host ? (not really necessary) */
521 if (sourceip && !net_testvip (sourceip)) {
522 return (0);
523 }
524
525 memset (&sourcedef, '\0', sizeof (struct sockaddr_in));
526
527 /* if sourceip is specified, set it */
528 if (sourceip) {
529 sourcedef.sin_addr.s_addr = net_resolve (sourceip);
530 } else {
531 sourcedef.sin_addr.s_addr = htonl (INADDR_ANY);
532 }
533 if (sourceport)
534 sourcedef.sin_port = htons (sourceport);
535
536 /* now set the source on the socket by binding it */
537 if (bind (sd, (struct sockaddr *) &sourcedef, sizeof (struct sockaddr_in)) == -1) {
538 return (0);
539 }
540
541 return (1);
542}
543
544
545int
546net_connect (struct sockaddr_in *cs, char *server, unsigned short int port, char *sourceip,
547 unsigned short int sourceport, int sec)
548{
549 int n, len, error, flags;
550 int fd;
551 struct timeval tv;
552 fd_set rset, wset;
553
554 /* first allocate a socket */
555 cs->sin_family = AF_INET;
556 cs->sin_port = htons (port);
557 fd = socket (cs->sin_family, SOCK_STREAM, 0);
558 if (fd == -1)
559 return (-1);
560
561 /* check wether we should change the defaults */
562 if (net_assignaddr (fd, sourceip, sourceport) == 0) {
563 close (fd);
564 return (-1);
565 }
566
567 if (!(cs->sin_addr.s_addr = net_resolve (server))) {
568 close (fd);
569 return (-1);
570 }
571
572 flags = fcntl (fd, F_GETFL, 0);
573 if (flags == -1) {
574 close (fd);
575 return (-1);
576 }
577 n = fcntl (fd, F_SETFL, flags | O_NONBLOCK);
578 if (n == -1) {
579 close (fd);
580 return (-1);
581 }
582
583 error = 0;
584
585 n = connect (fd, (struct sockaddr *) cs, sizeof (struct sockaddr_in));
586 if (n < 0) {
587 if (errno != EINPROGRESS) {
588 close (fd);
589 return (-1);
590 }
591 }
592 if (n == 0)
593 goto done;
594
595 FD_ZERO(&rset);
596 FD_ZERO(&wset);
597 FD_SET(fd, &rset);
598 FD_SET(fd, &wset);
599 tv.tv_sec = sec;
600 tv.tv_usec = 0;
601
602 n = select(fd + 1, &rset, &wset, NULL, &tv);
603 if (n == 0) {
604 close(fd);
605 errno = ETIMEDOUT;
606 return (-1);
607 }
608 if (n == -1)
609 return (-1);
610
611 if (FD_ISSET(fd, &rset) || FD_ISSET(fd, &wset)) {
612 if (FD_ISSET(fd, &rset) && FD_ISSET(fd, &wset)) {
613 len = sizeof(error);
614 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
615 errno = ETIMEDOUT;
616 return (-1);
617 }
618 if (error == 0) {
619 goto done;
620 } else {
621 errno = error;
622 return (-1);
623 }
624 }
625 } else
626 return (-1);
627
628done:
629 n = fcntl(fd, F_SETFL, flags);
630 if (n == -1)
631 return (-1);
632 return (fd);
633}
634
635
636int
637net_tline (char *buf, int bufsize)
638{
639 int p;
640
641 for (p = 0; p < bufsize; p++) {
642 if (buf[p] == '\n')
643 return (p + 1);
644 }
645 return (-1);
646}
647
648#define LINET_A 1024
649
650
651int
652net_rlineta (int fd, char **buf, int sec)
653{
654 int n; /* return value */
655 int bufsize = 0;
656
657 *buf = NULL;
658
659 do {
660 bufsize += LINET_A;
661 *buf = realloc (*buf, bufsize);
662 if (*buf == NULL)
663 return (-1);
664
665 n = net_rlinet (fd, *buf + bufsize - LINET_A, LINET_A, sec);
666
667 if (n == -1)
668 goto rlinetaerr;
669 if (n >= 0)
670 goto rlinetastrip;
671 } while (n == -2);
672
673rlinetastrip:
674 *buf = realloc (*buf, strlen (*buf) + 1);
675 return (strlen (*buf));
676
677rlinetaerr:
678 free (*buf);
679 return (-1);
680}
681
682
683int
684net_rlinet (int fd, char *buf, int bufsize, int sec)
685{
686 int n;
687 unsigned long int rb = 0;
688 struct timeval tv_start, tv_cur;
689
690 memset(buf, '\0', bufsize);
691 (void) gettimeofday(&tv_start, NULL);
692
693 do {
694 (void) gettimeofday(&tv_cur, NULL);
695 if (sec > 0) {
696 if ((((tv_cur.tv_sec * 1000000) + (tv_cur.tv_usec)) -
697 ((tv_start.tv_sec * 1000000) + (tv_start.tv_usec))) > (sec * 1000000)) {
698 return (-1);
699 }
700 }
701 n = net_rtimeout(fd, net_readtimeout);
702 if (n <= 0) {
703 return (-1);
704 }
705 n = read(fd, buf, 1);
706 if (n <= 0) {
707 return (n);
708 }
709 rb++;
710 if (*buf == '\n')
711 return (rb);
712 buf++;
713 if (rb >= bufsize)
714 return (-2); /* buffer full */
715 } while (1);
716}
717
718
719long int
720net_rbuf (int fd, char **dst)
721{
722 long int ml = 0;
723 long int read_bytes;
724 int p;
725
726 while ((p = net_rtimeout(fd, net_readtimeout)) == 1) {
727 *dst = (char *) realloc(*dst, ml + NET_BSIZE);
728 if (*dst == NULL)
729 return (-1);
730 ml += read_bytes = read(fd, *dst + ml, NET_BSIZE);
731 if (read_bytes == 0) {
732 *dst = (char *) realloc(*dst, ml);
733 if ((*dst == NULL) && (ml == 0)) {
734 return (1);
735 } else if (*dst == NULL) {
736 return (-1);
737 } else {
738 return (ml);
739 }
740 }
741 }
742 return (-1);
743}
744
745
746int
747net_rbuft (int fd, char *dst, unsigned long int dsize)
748{
749 unsigned long int bl = 0, m;
750 int p;
751
752 while (bl < dsize) {
753 p = net_rtimeout(fd, net_readtimeout);
754 if ((p == 0) || (p == -1)) {
755 return (-1);
756 }
757
758 m = read(fd, dst + bl, (dsize - bl));
759 if ((m == 0) || (m == -1)) {
760 return (-1);
761 }
762 bl += m;
763 }
764 return (1);
765}
766
767
768int
769net_rtimeout (int fd, int sec)
770{
771 fd_set rset;
772 struct timeval tv;
773 int n, error, flags;
774
775 error = 0;
776 flags = fcntl(fd, F_GETFL, 0);
777 n = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
778 if (n == -1)
779 return (-1);
780
781 FD_ZERO(&rset);
782 FD_SET(fd, &rset);
783 tv.tv_sec = sec;
784 tv.tv_usec = 0;
785
786 /* now we wait until more data is received then the tcp low level watermark,
787 * which should be setted to 1 in this case (1 is default)
788 */
789
790 n = select(fd + 1, &rset, NULL, NULL, &tv);
791 if (n == 0) {
792 n = fcntl(fd, F_SETFL, flags);
793 if (n == -1)
794 return (-1);
795 errno = ETIMEDOUT;
796 return (-1);
797 }
798 if (n == -1) {
799 return (-1);
800 }
801 /* socket readable ? */
802 if (FD_ISSET(fd, &rset)) {
803 n = fcntl(fd, F_SETFL, flags);
804 if (n == -1)
805 return (-1);
806 return (1);
807 } else {
808 n = fcntl(fd, F_SETFL, flags);
809 if (n == -1)
810 return (-1);
811 errno = ETIMEDOUT;
812 return (-1);
813 }
814}
815
816
817void
818net_write (int fd, const char *str, ...)
819{
820 char tmp[1025];
821 va_list vl;
822 int i;
823
824 va_start(vl, str);
825 memset(tmp, 0, sizeof(tmp));
826 i = vsnprintf(tmp, sizeof(tmp), str, vl);
827 va_end(vl);
828
829 send(fd, tmp, i, 0);
830 return;
831}
832
833
834int
835net_printip (struct in_addr *ia, char *str, size_t len)
836{
837 unsigned char *ipp;
838
839 ipp = (unsigned char *) &ia->s_addr;
840 snprintf (str, len - 1, "%d.%d.%d.%d", ipp[0], ipp[1], ipp[2], ipp[3]);
841
842 return (0);
843}
844
845
846int
847net_printipa (struct in_addr *ia, char **str)
848{
849 unsigned char *ipp;
850
851 ipp = (unsigned char *) &ia->s_addr;
852 *str = calloc (1, 256);
853 if (*str == NULL)
854 return (1);
855
856 snprintf (*str, 255, "%d.%d.%d.%d", ipp[0], ipp[1], ipp[2], ipp[3]);
857 *str = realloc (*str, strlen (*str) + 1);
858
859 return ((*str == NULL) ? 1 : 0);
860}
861