|
@@ -190,7 +190,7 @@ static void del_ipv6_miniroute ( struct ipv6_miniroute *miniroute ) {
|
190
|
190
|
* @ret miniroute Routing table entry to use, or NULL if no route
|
191
|
191
|
*/
|
192
|
192
|
static struct ipv6_miniroute * ipv6_route ( unsigned int scope_id,
|
193
|
|
- struct in6_addr **dest ) {
|
|
193
|
+ struct in6_addr **dest ) {
|
194
|
194
|
struct ipv6_miniroute *miniroute;
|
195
|
195
|
int local;
|
196
|
196
|
|
|
@@ -749,6 +749,96 @@ static const char * ipv6_ntoa ( const void *net_addr ) {
|
749
|
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
|
842
|
/** IPv6 protocol */
|
753
|
843
|
struct net_protocol ipv6_protocol __net_protocol = {
|
754
|
844
|
.name = "IPv6",
|
|
@@ -765,6 +855,13 @@ struct tcpip_net_protocol ipv6_tcpip_protocol __tcpip_net_protocol = {
|
765
|
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
|
866
|
* Create IPv6 network device
|
770
|
867
|
*
|