Browse Source

[ipv6] Add IPv6 socket address converter

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 11 years ago
parent
commit
2c76c1a6d8
2 changed files with 102 additions and 2 deletions
  1. 4
    1
      src/include/ipxe/netdevice.h
  2. 98
    1
      src/net/ipv6.c

+ 4
- 1
src/include/ipxe/netdevice.h View File

292
 	struct net_device_error errors[NETDEV_MAX_UNIQUE_ERRORS];
292
 	struct net_device_error errors[NETDEV_MAX_UNIQUE_ERRORS];
293
 };
293
 };
294
 
294
 
295
+/** Maximum length of a network device name */
296
+#define NETDEV_NAME_LEN 12
297
+
295
 /**
298
 /**
296
  * A network device
299
  * A network device
297
  *
300
  *
312
 	/** Index of this network device */
315
 	/** Index of this network device */
313
 	unsigned int index;
316
 	unsigned int index;
314
 	/** Name of this network device */
317
 	/** Name of this network device */
315
-	char name[12];
318
+	char name[NETDEV_NAME_LEN];
316
 	/** Underlying hardware device */
319
 	/** Underlying hardware device */
317
 	struct device *dev;
320
 	struct device *dev;
318
 
321
 

+ 98
- 1
src/net/ipv6.c View File

190
  * @ret miniroute	Routing table entry to use, or NULL if no route
190
  * @ret miniroute	Routing table entry to use, or NULL if no route
191
  */
191
  */
192
 static struct ipv6_miniroute * ipv6_route ( unsigned int scope_id,
192
 static struct ipv6_miniroute * ipv6_route ( unsigned int scope_id,
193
-					   struct in6_addr **dest ) {
193
+					    struct in6_addr **dest ) {
194
 	struct ipv6_miniroute *miniroute;
194
 	struct ipv6_miniroute *miniroute;
195
 	int local;
195
 	int local;
196
 
196
 
749
 	return inet6_ntoa ( net_addr );
749
 	return inet6_ntoa ( net_addr );
750
 }
750
 }
751
 
751
 
752
+/**
753
+ * Transcribe IPv6 socket address
754
+ *
755
+ * @v sa		Socket address
756
+ * @ret string		Socket address in standard notation
757
+ */
758
+static const char * ipv6_sock_ntoa ( struct sockaddr *sa ) {
759
+	static char buf[ 39 /* "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx" */ +
760
+			 1 /* "%" */ + NETDEV_NAME_LEN + 1 /* NUL */ ];
761
+	struct sockaddr_in6 *sin6 = ( ( struct sockaddr_in6 * ) sa );
762
+	struct in6_addr *in = &sin6->sin6_addr;
763
+	struct net_device *netdev;
764
+	const char *netdev_name;
765
+
766
+	/* Identify network device, if applicable */
767
+	if ( IN6_IS_ADDR_LINKLOCAL ( in ) ) {
768
+		netdev = find_netdev_by_index ( sin6->sin6_scope_id );
769
+		netdev_name = ( netdev ? netdev->name : "UNKNOWN" );
770
+	} else {
771
+		netdev_name = NULL;
772
+	}
773
+
774
+	/* Format socket address */
775
+	snprintf ( buf, sizeof ( buf ), "%s%s%s", inet6_ntoa ( in ),
776
+		   ( netdev_name ? "%" : "" ),
777
+		   ( netdev_name ? netdev_name : "" ) );
778
+	return buf;
779
+}
780
+
781
+/**
782
+ * Parse IPv6 socket address
783
+ *
784
+ * @v string		Socket address string
785
+ * @v sa		Socket address to fill in
786
+ * @ret rc		Return status code
787
+ */
788
+static int ipv6_sock_aton ( const char *string, struct sockaddr *sa ) {
789
+	struct sockaddr_in6 *sin6 = ( ( struct sockaddr_in6 * ) sa );
790
+	struct in6_addr in;
791
+	struct net_device *netdev;
792
+	size_t len;
793
+	char *tmp;
794
+	char *in_string;
795
+	char *netdev_string;
796
+	int rc;
797
+
798
+	/* Create modifiable copy of string */
799
+	tmp = strdup ( string );
800
+	if ( ! tmp ) {
801
+		rc = -ENOMEM;
802
+		goto err_alloc;
803
+	}
804
+	in_string = tmp;
805
+
806
+	/* Strip surrounding "[...]", if present */
807
+	len = strlen ( in_string );
808
+	if ( ( in_string[0] == '[' ) && ( in_string[ len - 1 ] == ']' ) ) {
809
+		in_string[ len - 1 ] = '\0';
810
+		in_string++;
811
+	}
812
+
813
+	/* Split at network device name, if present */
814
+	netdev_string = strchr ( in_string, '%' );
815
+	if ( netdev_string )
816
+		*(netdev_string++) = '\0';
817
+
818
+	/* Parse IPv6 address portion */
819
+	if ( ( rc = inet6_aton ( in_string, &in ) ) != 0 )
820
+		goto err_inet6_aton;
821
+
822
+	/* Parse network device name, if present */
823
+	if ( netdev_string ) {
824
+		netdev = find_netdev ( netdev_string );
825
+		if ( ! netdev ) {
826
+			rc = -ENODEV;
827
+			goto err_find_netdev;
828
+		}
829
+		sin6->sin6_scope_id = netdev->index;
830
+	}
831
+
832
+	/* Copy IPv6 address portion to socket address */
833
+	memcpy ( &sin6->sin6_addr, &in, sizeof ( sin6->sin6_addr ) );
834
+
835
+ err_find_netdev:
836
+ err_inet6_aton:
837
+	free ( tmp );
838
+ err_alloc:
839
+	return rc;
840
+}
841
+
752
 /** IPv6 protocol */
842
 /** IPv6 protocol */
753
 struct net_protocol ipv6_protocol __net_protocol = {
843
 struct net_protocol ipv6_protocol __net_protocol = {
754
 	.name = "IPv6",
844
 	.name = "IPv6",
765
 	.tx = ipv6_tx,
855
 	.tx = ipv6_tx,
766
 };
856
 };
767
 
857
 
858
+/** IPv6 socket address converter */
859
+struct sockaddr_converter ipv6_sockaddr_converter __sockaddr_converter = {
860
+	.family = AF_INET6,
861
+	.ntoa = ipv6_sock_ntoa,
862
+	.aton = ipv6_sock_aton,
863
+};
864
+
768
 /**
865
 /**
769
  * Create IPv6 network device
866
  * Create IPv6 network device
770
  *
867
  *

Loading…
Cancel
Save