Browse code

- added more utility functions: - su2a() converts a union sockaddr_union into <ip>:<port> (returns pointer to null terminated static string) - ip_addr2sbuf() converts a struct ip_addr into its ascii repsentation in the supplied buffer (unlike ip_addr2a() which uses a static buffer) - ip4tosbuf(), ip6tosbuf() directly convert a raw ip address (byte array) into ascii

Andrei Pelinescu-Onciul authored on 21/05/2008 21:37:26
Showing 1 changed files
... ...
@@ -33,6 +33,7 @@
33 33
  *  2006-04-20  comp support in recv_info and dest_info (andrei)
34 34
  *  2006-04-21  added init_dst_from_rcv (andrei)
35 35
  *  2007-06-26  added ip_addr_mk_any() (andrei)
36
+ *  2008-05-21  added su2a(), ip_addr2sbuf(), ip4tosbuf(), ip62sbuf() (andrei)
36 37
  */
37 38
 
38 39
 #ifndef ip_addr_h
... ...
@@ -45,6 +46,7 @@
45 45
 #include <netdb.h>
46 46
 #include "str.h"
47 47
 #include "compiler_opt.h"
48
+#include "ut.h"
48 49
 
49 50
 
50 51
 #include "dprint.h"
... ...
@@ -443,138 +445,225 @@ static inline int hostent2su( union sockaddr_union* su,
443 443
 	return 0;
444 444
 }
445 445
 
446
-/* maximum size of a str returned by ip_addr2a (including \0) */
447
-#define IP_ADDR_MAX_STR_SIZE 40 /* 1234:5678:9012:3456:7890:1234:5678:9012\0 */
448
-/* fast ip_addr -> string converter;
449
- * it uses an internal buffer
450
- */
451
-static inline char* ip_addr2a(struct ip_addr* ip)
452
-{
453 446
 
454
-	static char buff[IP_ADDR_MAX_STR_SIZE];
447
+
448
+/* maximum size of a str returned by ip_addr2str */
449
+#define IP6_MAX_STR_SIZE 39 /*1234:5678:9012:3456:7890:1234:5678:9012*/
450
+#define IP4_MAX_STR_SIZE 15 /*123.456.789.012*/
451
+
452
+#ifdef USE_IPV6
453
+/* converts a raw ipv6 addr (16 bytes) to ascii */
454
+static inline int ip6tosbuf(unsigned char* ip6, char* buff, int len)
455
+{
455 456
 	int offset;
456 457
 	register unsigned char a,b,c;
457
-#ifdef USE_IPV6
458 458
 	register unsigned char d;
459 459
 	register unsigned short hex4;
460
-#endif
461 460
 	int r;
462 461
 	#define HEXDIG(x) (((x)>=10)?(x)-10+'A':(x)+'0')
463 462
 	
464 463
 	
465 464
 	offset=0;
465
+	if (unlikely(len<IP6_MAX_STR_SIZE))
466
+		return 0;
467
+	for(r=0;r<7;r++){
468
+		hex4=((unsigned char)ip6[r*2]<<8)+(unsigned char)ip6[r*2+1];
469
+		a=hex4>>12;
470
+		b=(hex4>>8)&0xf;
471
+		c=(hex4>>4)&0xf;
472
+		d=hex4&0xf;
473
+		if (a){
474
+			buff[offset]=HEXDIG(a);
475
+			buff[offset+1]=HEXDIG(b);
476
+			buff[offset+2]=HEXDIG(c);
477
+			buff[offset+3]=HEXDIG(d);
478
+			buff[offset+4]=':';
479
+			offset+=5;
480
+		}else if(b){
481
+			buff[offset]=HEXDIG(b);
482
+			buff[offset+1]=HEXDIG(c);
483
+			buff[offset+2]=HEXDIG(d);
484
+			buff[offset+3]=':';
485
+			offset+=4;
486
+		}else if(c){
487
+			buff[offset]=HEXDIG(c);
488
+			buff[offset+1]=HEXDIG(d);
489
+			buff[offset+2]=':';
490
+			offset+=3;
491
+		}else{
492
+			buff[offset]=HEXDIG(d);
493
+			buff[offset+1]=':';
494
+			offset+=2;
495
+		}
496
+	}
497
+	/* last int16*/
498
+	hex4=((unsigned char)ip6[r*2]<<8)+(unsigned char)ip6[r*2+1];
499
+	a=hex4>>12;
500
+	b=(hex4>>8)&0xf;
501
+	c=(hex4>>4)&0xf;
502
+	d=hex4&0xf;
503
+	if (a){
504
+		buff[offset]=HEXDIG(a);
505
+		buff[offset+1]=HEXDIG(b);
506
+		buff[offset+2]=HEXDIG(c);
507
+		buff[offset+3]=HEXDIG(d);
508
+		offset+=4;
509
+	}else if(b){
510
+		buff[offset]=HEXDIG(b);
511
+		buff[offset+1]=HEXDIG(c);
512
+		buff[offset+2]=HEXDIG(d);
513
+		offset+=3;
514
+	}else if(c){
515
+		buff[offset]=HEXDIG(c);
516
+		buff[offset+1]=HEXDIG(d);
517
+		offset+=2;
518
+	}else{
519
+		buff[offset]=HEXDIG(d);
520
+		offset+=1;
521
+	}
522
+	
523
+	return offset;
524
+}
525
+#endif /* USE_IPV6 */
526
+
527
+
528
+
529
+/* converts a raw ipv4 addr (4 bytes) to ascii */
530
+static inline int ip4tosbuf(unsigned char* ip4, char* buff, int len)
531
+{
532
+	int offset;
533
+	register unsigned char a,b,c;
534
+	int r;
535
+	
536
+	
537
+	offset=0;
538
+	if (unlikely(len<IP4_MAX_STR_SIZE))
539
+		return 0;
540
+	for(r=0;r<3;r++){
541
+		a=(unsigned char)ip4[r]/100;
542
+		c=(unsigned char)ip4[r]%10;
543
+		b=(unsigned char)ip4[r]%100/10;
544
+		if (a){
545
+			buff[offset]=a+'0';
546
+			buff[offset+1]=b+'0';
547
+			buff[offset+2]=c+'0';
548
+			buff[offset+3]='.';
549
+			offset+=4;
550
+		}else if (b){
551
+			buff[offset]=b+'0';
552
+			buff[offset+1]=c+'0';
553
+			buff[offset+2]='.';
554
+			offset+=3;
555
+		}else{
556
+			buff[offset]=c+'0';
557
+			buff[offset+1]='.';
558
+			offset+=2;
559
+		}
560
+	}
561
+	/* last number */
562
+	a=(unsigned char)ip4[r]/100;
563
+	c=(unsigned char)ip4[r]%10;
564
+	b=(unsigned char)ip4[r]%100/10;
565
+	if (a){
566
+		buff[offset]=a+'0';
567
+		buff[offset+1]=b+'0';
568
+		buff[offset+2]=c+'0';
569
+		offset+=3;
570
+	}else if (b){
571
+		buff[offset]=b+'0';
572
+		buff[offset+1]=c+'0';
573
+		offset+=2;
574
+	}else{
575
+		buff[offset]=c+'0';
576
+		offset+=1;
577
+	}
578
+	
579
+	return offset;
580
+}
581
+
582
+
583
+
584
+/* fast ip_addr -> string converter;
585
+ * returns number of bytes written in buf on success, <=0 on error
586
+ * The buffer must have enough space to hold the maximum size ip address
587
+ *  of the corresponding address (see IP[46] above) or else the function
588
+ *  will return error (no detailed might fit checks are made, for example
589
+ *   if len==7 the function will fail even for 1.2.3.4).
590
+ */
591
+static inline int ip_addr2sbuf(struct ip_addr* ip, char* buff, int len)
592
+{
466 593
 	switch(ip->af){
467 594
 	#ifdef USE_IPV6
468 595
 		case AF_INET6:
469
-			for(r=0;r<7;r++){
470
-				hex4=ntohs(ip->u.addr16[r]);
471
-				a=hex4>>12;
472
-				b=(hex4>>8)&0xf;
473
-				c=(hex4>>4)&0xf;
474
-				d=hex4&0xf;
475
-				if (a){
476
-					buff[offset]=HEXDIG(a);
477
-					buff[offset+1]=HEXDIG(b);
478
-					buff[offset+2]=HEXDIG(c);
479
-					buff[offset+3]=HEXDIG(d);
480
-					buff[offset+4]=':';
481
-					offset+=5;
482
-				}else if(b){
483
-					buff[offset]=HEXDIG(b);
484
-					buff[offset+1]=HEXDIG(c);
485
-					buff[offset+2]=HEXDIG(d);
486
-					buff[offset+3]=':';
487
-					offset+=4;
488
-				}else if(c){
489
-					buff[offset]=HEXDIG(c);
490
-					buff[offset+1]=HEXDIG(d);
491
-					buff[offset+2]=':';
492
-					offset+=3;
493
-				}else{
494
-					buff[offset]=HEXDIG(d);
495
-					buff[offset+1]=':';
496
-					offset+=2;
497
-				}
498
-			}
499
-			/* last int16*/
500
-			hex4=ntohs(ip->u.addr16[r]);
501
-			a=hex4>>12;
502
-			b=(hex4>>8)&0xf;
503
-			c=(hex4>>4)&0xf;
504
-			d=hex4&0xf;
505
-			if (a){
506
-				buff[offset]=HEXDIG(a);
507
-				buff[offset+1]=HEXDIG(b);
508
-				buff[offset+2]=HEXDIG(c);
509
-				buff[offset+3]=HEXDIG(d);
510
-				buff[offset+4]=0;
511
-			}else if(b){
512
-				buff[offset]=HEXDIG(b);
513
-				buff[offset+1]=HEXDIG(c);
514
-				buff[offset+2]=HEXDIG(d);
515
-				buff[offset+3]=0;
516
-			}else if(c){
517
-				buff[offset]=HEXDIG(c);
518
-				buff[offset+1]=HEXDIG(d);
519
-				buff[offset+2]=0;
520
-			}else{
521
-				buff[offset]=HEXDIG(d);
522
-				buff[offset+1]=0;
523
-			}
596
+			return ip6tosbuf(ip->u.addr, buff, len);
524 597
 			break;
525
-	#endif
598
+	#endif /* USE_IPV6 */
526 599
 		case AF_INET:
527
-			for(r=0;r<3;r++){
528
-				a=ip->u.addr[r]/100;
529
-				c=ip->u.addr[r]%10;
530
-				b=ip->u.addr[r]%100/10;
531
-				if (a){
532
-					buff[offset]=a+'0';
533
-					buff[offset+1]=b+'0';
534
-					buff[offset+2]=c+'0';
535
-					buff[offset+3]='.';
536
-					offset+=4;
537
-				}else if (b){
538
-					buff[offset]=b+'0';
539
-					buff[offset+1]=c+'0';
540
-					buff[offset+2]='.';
541
-					offset+=3;
542
-				}else{
543
-					buff[offset]=c+'0';
544
-					buff[offset+1]='.';
545
-					offset+=2;
546
-				}
547
-			}
548
-			/* last number */
549
-			a=ip->u.addr[r]/100;
550
-			c=ip->u.addr[r]%10;
551
-			b=ip->u.addr[r]%100/10;
552
-			if (a){
553
-				buff[offset]=a+'0';
554
-				buff[offset+1]=b+'0';
555
-				buff[offset+2]=c+'0';
556
-				buff[offset+3]=0;
557
-			}else if (b){
558
-				buff[offset]=b+'0';
559
-				buff[offset+1]=c+'0';
560
-				buff[offset+2]=0;
561
-			}else{
562
-				buff[offset]=c+'0';
563
-				buff[offset+1]=0;
564
-			}
600
+			return ip4tosbuf(ip->u.addr, buff, len);
565 601
 			break;
566
-		
567 602
 		default:
568
-			LOG(L_CRIT, "BUG: ip_addr2a: unknown address family %d\n",
603
+			LOG(L_CRIT, "BUG: ip_addr2sbuf: unknown address family %d\n",
569 604
 					ip->af);
570 605
 			return 0;
571 606
 	}
607
+	return 0;
608
+}
609
+
610
+
611
+
612
+/* maximum size of a str returned by ip_addr2a (including \0) */
613
+#define IP_ADDR_MAX_STR_SIZE (IP6_MAX_STR_SIZE+1) /* ip62ascii +  \0*/
614
+/* fast ip_addr -> string converter;
615
+ * it uses an internal buffer
616
+ */
617
+static inline char* ip_addr2a(struct ip_addr* ip)
618
+{
619
+
620
+	static char buff[IP_ADDR_MAX_STR_SIZE];
621
+	int len;
572 622
 	
623
+	
624
+	len=ip_addr2sbuf(ip, buff, sizeof(buff)-1);
625
+	buff[len]=0;
626
+
573 627
 	return buff;
574 628
 }
575 629
 
576 630
 
577 631
 
632
+#define SU2A_MAX_STR_SIZE  (IP6_MAX_STR_SIZE + 2 /* [] */+\
633
+								1 /* : */ + USHORT2SBUF_MAX_LEN + 1 /* \0 */)
634
+/* returns an asciiz string containing the ip and the port
635
+ *  (<ip_addr>:port or [<ipv6_addr>]:port)
636
+ */
637
+static inline char* su2a(union sockaddr_union* su, int su_len)
638
+{
639
+	static char buf[SU2A_MAX_STR_SIZE];
640
+	int offs;
641
+	
642
+#ifdef USE_IPV6
643
+	if (unlikely(su->s.sa_family==AF_INET6)){
644
+		if (unlikely(su_len<sizeof(su->sin6)))
645
+			return "<addr. error>";
646
+		buf[0]='[';
647
+		offs=1+ip6tosbuf((unsigned char*)&su->sin6.sin6_addr, &buf[1],
648
+							sizeof(buf)-4);
649
+		buf[offs]=']';
650
+		offs++;
651
+	}else
652
+#endif /* USE_IPV6*/
653
+	if (unlikely(su_len<sizeof(su->sin)))
654
+		return "<addr. error>";
655
+	else
656
+		offs=ip4tosbuf((unsigned char*)&su->sin.sin_addr, buf, sizeof(buf)-2);
657
+	buf[offs]=':';
658
+	offs+=1+ushort2sbuf(su_getport(su), &buf[offs+1], sizeof(buf)-(offs+1)-1);
659
+	buf[offs]=0;
660
+	return buf;
661
+}
662
+
663
+
664
+
578 665
 /* converts an ip_addr structure to a hostent, returns pointer to internal
579 666
  * statical structure */
580 667
 static inline struct hostent* ip_addr2he(str* name, struct ip_addr* ip)