@@ -73,8 +73,6 @@ static atomic_t iface_counter = ATOMIC_INIT(0);
7373/* Private data structure */
7474struct sierra_net_data {
7575
76- u8 ethr_hdr_tmpl [ETH_HLEN ]; /* ethernet header template for rx'd pkts */
77-
7876 u16 link_up ; /* air link up or down */
7977 u8 tx_hdr_template [4 ]; /* part of HIP hdr for tx'd packets */
8078
@@ -122,24 +120,31 @@ struct param {
122120
123121/* LSI Protocol types */
124122#define SIERRA_NET_PROTOCOL_UMTS 0x01
123+ #define SIERRA_NET_PROTOCOL_UMTS_DS 0x04
125124/* LSI Coverage */
126125#define SIERRA_NET_COVERAGE_NONE 0x00
127126#define SIERRA_NET_COVERAGE_NOPACKET 0x01
128127
129128/* LSI Session */
130129#define SIERRA_NET_SESSION_IDLE 0x00
131130/* LSI Link types */
132- #define SIERRA_NET_AS_LINK_TYPE_IPv4 0x00
131+ #define SIERRA_NET_AS_LINK_TYPE_IPV4 0x00
132+ #define SIERRA_NET_AS_LINK_TYPE_IPV6 0x02
133133
134134struct lsi_umts {
135135 u8 protocol ;
136136 u8 unused1 ;
137137 __be16 length ;
138138 /* eventually use a union for the rest - assume umts for now */
139139 u8 coverage ;
140- u8 unused2 [41 ];
140+ u8 network_len ; /* network name len */
141+ u8 network [40 ]; /* network name (UCS2, bigendian) */
141142 u8 session_state ;
142143 u8 unused3 [33 ];
144+ } __packed ;
145+
146+ struct lsi_umts_single {
147+ struct lsi_umts lsi ;
143148 u8 link_type ;
144149 u8 pdp_addr_len ; /* NW-supplied PDP address len */
145150 u8 pdp_addr [16 ]; /* NW-supplied PDP address (bigendian)) */
@@ -158,10 +163,31 @@ struct lsi_umts {
158163 u8 reserved [8 ];
159164} __packed ;
160165
166+ struct lsi_umts_dual {
167+ struct lsi_umts lsi ;
168+ u8 pdp_addr4_len ; /* NW-supplied PDP IPv4 address len */
169+ u8 pdp_addr4 [4 ]; /* NW-supplied PDP IPv4 address (bigendian)) */
170+ u8 pdp_addr6_len ; /* NW-supplied PDP IPv6 address len */
171+ u8 pdp_addr6 [16 ]; /* NW-supplied PDP IPv6 address (bigendian)) */
172+ u8 unused4 [23 ];
173+ u8 dns1_addr4_len ; /* NW-supplied 1st DNS v4 address len (bigendian) */
174+ u8 dns1_addr4 [4 ]; /* NW-supplied 1st DNS v4 address */
175+ u8 dns1_addr6_len ; /* NW-supplied 1st DNS v6 address len */
176+ u8 dns1_addr6 [16 ]; /* NW-supplied 1st DNS v6 address (bigendian)*/
177+ u8 dns2_addr4_len ; /* NW-supplied 2nd DNS v4 address len (bigendian) */
178+ u8 dns2_addr4 [4 ]; /* NW-supplied 2nd DNS v4 address */
179+ u8 dns2_addr6_len ; /* NW-supplied 2nd DNS v6 address len */
180+ u8 dns2_addr6 [16 ]; /* NW-supplied 2nd DNS v6 address (bigendian)*/
181+ u8 unused5 [68 ];
182+ } __packed ;
183+
161184#define SIERRA_NET_LSI_COMMON_LEN 4
162- #define SIERRA_NET_LSI_UMTS_LEN (sizeof(struct lsi_umts ))
185+ #define SIERRA_NET_LSI_UMTS_LEN (sizeof(struct lsi_umts_single ))
163186#define SIERRA_NET_LSI_UMTS_STATUS_LEN \
164187 (SIERRA_NET_LSI_UMTS_LEN - SIERRA_NET_LSI_COMMON_LEN)
188+ #define SIERRA_NET_LSI_UMTS_DS_LEN (sizeof(struct lsi_umts_dual))
189+ #define SIERRA_NET_LSI_UMTS_DS_STATUS_LEN \
190+ (SIERRA_NET_LSI_UMTS_DS_LEN - SIERRA_NET_LSI_COMMON_LEN)
165191
166192/* Forward definitions */
167193static void sierra_sync_timer (unsigned long syncdata );
@@ -191,10 +217,11 @@ static inline void sierra_net_set_private(struct usbnet *dev,
191217 dev -> data [0 ] = (unsigned long )priv ;
192218}
193219
194- /* is packet IPv4 */
220+ /* is packet IPv4/IPv6 */
195221static inline int is_ip (struct sk_buff * skb )
196222{
197- return skb -> protocol == cpu_to_be16 (ETH_P_IP );
223+ return skb -> protocol == cpu_to_be16 (ETH_P_IP ) ||
224+ skb -> protocol == cpu_to_be16 (ETH_P_IPV6 );
198225}
199226
200227/*
@@ -350,18 +377,11 @@ static inline int sierra_net_is_valid_addrlen(u8 len)
350377static int sierra_net_parse_lsi (struct usbnet * dev , char * data , int datalen )
351378{
352379 struct lsi_umts * lsi = (struct lsi_umts * )data ;
380+ u32 expected_length ;
353381
354- if (datalen < sizeof (struct lsi_umts )) {
355- netdev_err (dev -> net , "%s: Data length %d, exp %Zu\n" ,
356- __func__ , datalen ,
357- sizeof (struct lsi_umts ));
358- return -1 ;
359- }
360-
361- if (lsi -> length != cpu_to_be16 (SIERRA_NET_LSI_UMTS_STATUS_LEN )) {
362- netdev_err (dev -> net , "%s: LSI_UMTS_STATUS_LEN %d, exp %u\n" ,
363- __func__ , be16_to_cpu (lsi -> length ),
364- (u32 )SIERRA_NET_LSI_UMTS_STATUS_LEN );
382+ if (datalen < sizeof (struct lsi_umts_single )) {
383+ netdev_err (dev -> net , "%s: Data length %d, exp >= %Zu\n" ,
384+ __func__ , datalen , sizeof (struct lsi_umts_single ));
365385 return -1 ;
366386 }
367387
@@ -373,22 +393,34 @@ static int sierra_net_parse_lsi(struct usbnet *dev, char *data, int datalen)
373393 }
374394
375395 /* Validate the protocol - only support UMTS for now */
376- if (lsi -> protocol != SIERRA_NET_PROTOCOL_UMTS ) {
396+ if (lsi -> protocol == SIERRA_NET_PROTOCOL_UMTS ) {
397+ struct lsi_umts_single * single = (struct lsi_umts_single * )lsi ;
398+
399+ /* Validate the link type */
400+ if (single -> link_type != SIERRA_NET_AS_LINK_TYPE_IPV4 &&
401+ single -> link_type != SIERRA_NET_AS_LINK_TYPE_IPV6 ) {
402+ netdev_err (dev -> net , "Link type unsupported: 0x%02x\n" ,
403+ single -> link_type );
404+ return -1 ;
405+ }
406+ expected_length = SIERRA_NET_LSI_UMTS_STATUS_LEN ;
407+ } else if (lsi -> protocol == SIERRA_NET_PROTOCOL_UMTS_DS ) {
408+ expected_length = SIERRA_NET_LSI_UMTS_DS_STATUS_LEN ;
409+ } else {
377410 netdev_err (dev -> net , "Protocol unsupported, 0x%02x\n" ,
378- lsi -> protocol );
411+ lsi -> protocol );
379412 return -1 ;
380413 }
381414
382- /* Validate the link type */
383- if (lsi -> link_type != SIERRA_NET_AS_LINK_TYPE_IPv4 ) {
384- netdev_err (dev -> net , "Link type unsupported: 0x%02x\n" ,
385- lsi -> link_type );
415+ if (be16_to_cpu (lsi -> length ) != expected_length ) {
416+ netdev_err (dev -> net , "%s: LSI_UMTS_STATUS_LEN %d, exp %u\n" ,
417+ __func__ , be16_to_cpu (lsi -> length ), expected_length );
386418 return -1 ;
387419 }
388420
389421 /* Validate the coverage */
390- if (lsi -> coverage == SIERRA_NET_COVERAGE_NONE
391- || lsi -> coverage == SIERRA_NET_COVERAGE_NOPACKET ) {
422+ if (lsi -> coverage == SIERRA_NET_COVERAGE_NONE ||
423+ lsi -> coverage == SIERRA_NET_COVERAGE_NOPACKET ) {
392424 netdev_err (dev -> net , "No coverage, 0x%02x\n" , lsi -> coverage );
393425 return 0 ;
394426 }
@@ -662,7 +694,6 @@ static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf)
662694 u8 numendpoints ;
663695 u16 fwattr = 0 ;
664696 int status ;
665- struct ethhdr * eth ;
666697 struct sierra_net_data * priv ;
667698 static const u8 sync_tmplate [sizeof (priv -> sync_msg )] = {
668699 0x00 , 0x00 , SIERRA_NET_HIP_MSYNC_ID , 0x00 };
@@ -700,11 +731,6 @@ static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf)
700731 dev -> net -> dev_addr [ETH_ALEN - 2 ] = atomic_inc_return (& iface_counter );
701732 dev -> net -> dev_addr [ETH_ALEN - 1 ] = ifacenum ;
702733
703- /* we will have to manufacture ethernet headers, prepare template */
704- eth = (struct ethhdr * )priv -> ethr_hdr_tmpl ;
705- memcpy (& eth -> h_dest , dev -> net -> dev_addr , ETH_ALEN );
706- eth -> h_proto = cpu_to_be16 (ETH_P_IP );
707-
708734 /* prepare shutdown message template */
709735 memcpy (priv -> shdwn_msg , shdwn_tmplate , sizeof (priv -> shdwn_msg ));
710736 /* set context index initially to 0 - prepares tx hdr template */
@@ -833,9 +859,14 @@ static int sierra_net_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
833859
834860 skb_pull (skb , hh .hdrlen );
835861
836- /* We are going to accept this packet, prepare it */
837- memcpy (skb -> data , sierra_net_get_private (dev )-> ethr_hdr_tmpl ,
838- ETH_HLEN );
862+ /* We are going to accept this packet, prepare it.
863+ * In case protocol is IPv6, keep it, otherwise force IPv4.
864+ */
865+ skb_reset_mac_header (skb );
866+ if (eth_hdr (skb )-> h_proto != cpu_to_be16 (ETH_P_IPV6 ))
867+ eth_hdr (skb )-> h_proto = cpu_to_be16 (ETH_P_IP );
868+ eth_zero_addr (eth_hdr (skb )-> h_source );
869+ memcpy (eth_hdr (skb )-> h_dest , dev -> net -> dev_addr , ETH_ALEN );
839870
840871 /* Last packet in batch handled by usbnet */
841872 if (hh .payload_len .word == skb -> len )
0 commit comments