1 #include <linux/module.h>
2 #include <linux/init.h>
3 #include <linux/netdevice.h> /* struct device, and other headers */
4 #include <linux/etherdevice.h> /* eth_type_trans */
5 #include <linux/ip.h> /* struct iphdr */
6 #include <linux/ipv6.h> /* struct ipv6hdr */
9 #include "smskdefs.h" // page, scatterlist, kmutex
10 #include "smscoreapi.h"
13 #define IPV4VERSION 0x40
14 #define IPV6VERSION 0x60
15 #define GETIPVERSION(_x_) ((_x_) & 0xf0)
17 typedef struct _smsnet_client
19 struct list_head entry
;
21 smscore_device_t
*coredev
;
22 smscore_client_t
*smsclient
;
24 int packet_length
, splitpacket_length
;
25 int header_length
, splitheader_length
;
26 u8 splitpacket
[ETH_DATA_LEN
];
29 struct list_head g_smsnet_clients
;
30 kmutex_t g_smsnet_clientslock
;
32 struct net_device
*g_smsnet_device
= NULL
;
33 struct net_device_stats g_smsnet_stats
;
35 int g_smsnet_inuse
= 0;
37 void smsnet_send_packet(u8
* buffer
, int length
)
40 struct sk_buff
*skb
= dev_alloc_skb(length
+ ETH_HLEN
+ NET_IP_ALIGN
);
44 g_smsnet_stats
.rx_dropped
++;
48 skb_reserve(skb
, NET_IP_ALIGN
);
50 eth
= (u8
*) skb_put(skb
, length
+ ETH_HLEN
);
51 memcpy(eth
+ ETH_HLEN
, buffer
, length
);
60 if (GETIPVERSION(*buffer
) == IPV4VERSION
)
65 eth
[3] = buffer
[17] & 0x7f;
74 // todo: ip6 mcast address
80 skb
->dev
= g_smsnet_device
;
81 skb
->protocol
= eth_type_trans(skb
, g_smsnet_device
);
82 skb
->ip_summed
= CHECKSUM_UNNECESSARY
;
84 g_smsnet_stats
.rx_packets
++;
85 g_smsnet_stats
.rx_bytes
+= skb
->len
;
90 int check_header(smsnet_client_t
* client
, u8
* buffer
)
92 struct iphdr
*ip4_hdr
;
93 struct ipv6hdr
*ip6_hdr
;
94 struct udphdr
*udp_hdr
;
97 // check if packet header is valid and it is a UDP
98 if (GETIPVERSION(*buffer
) == IPV4VERSION
)
100 ip4_hdr
= (struct iphdr
*) buffer
;
101 csum
= ip4_hdr
->check
;
105 // check header checksum for IPv4 packets
106 if(ip4_hdr
->protocol
!= IPPROTO_UDP
|| csum
!= ip_fast_csum(buffer
, ip4_hdr
->ihl
))
108 ip4_hdr
->check
= csum
;
112 ip4_hdr
->check
= csum
;
113 client
->packet_length
= ntohs(ip4_hdr
->tot_len
);
117 ip6_hdr
= (struct ipv6hdr
*) buffer
;
118 udp_hdr
= (struct udphdr
*)(ip6_hdr
+ 1);
120 if ((ip6_hdr
->nexthdr
!= IPPROTO_UDP
) ||
121 (ip6_hdr
->payload_len
!= udp_hdr
->len
))
126 client
->packet_length
= ntohs(ip6_hdr
->payload_len
) + sizeof(struct ipv6hdr
);
129 // check for abnormal packet length
130 if (client
->packet_length
> ETH_DATA_LEN
)
136 int smsnet_onresponse(void *context
, smscore_buffer_t
*cb
)
138 smsnet_client_t
*client
= (smsnet_client_t
*) context
;
142 buffer
= ((u8
*) cb
->p
) + cb
->offset
+ sizeof(SmsMsgHdr_ST
);
143 length
= cb
->size
- sizeof(SmsMsgHdr_ST
);
145 if (client
->splitheader_length
)
147 // how much data is missing ?
148 rest
= client
->header_length
- client
->splitheader_length
;
150 // do we have enough in this buffer ?
151 rest
= min(rest
, length
);
153 memcpy(&client
->splitpacket
[client
->splitheader_length
], buffer
, rest
);
155 client
->splitheader_length
+= rest
;
157 if (client
->splitheader_length
!= client
->header_length
)
160 if (check_header(client
, client
->splitpacket
))
165 client
->splitpacket_length
= client
->header_length
;
168 client
->splitheader_length
= 0;
171 if (client
->splitpacket_length
)
173 // how much data is missing ?
174 rest
= client
->packet_length
- client
->splitpacket_length
;
176 // do we have enough in this buffer ?
177 rest
= min(rest
, length
);
179 memcpy(&client
->splitpacket
[client
->splitpacket_length
], buffer
, rest
);
181 client
->splitpacket_length
+= rest
;
183 if (client
->splitpacket_length
!= client
->packet_length
)
186 client
->splitpacket_length
= 0;
188 smsnet_send_packet(client
->splitpacket
, client
->packet_length
);
196 ip_ver
= GETIPVERSION(*buffer
);
197 while (length
&& (ip_ver
!= IPV4VERSION
) && (ip_ver
!= IPV6VERSION
))
201 ip_ver
= GETIPVERSION(*buffer
);
204 // No more data in section
208 // Set the header length at start of packet according to the version
209 // no problem with the IP header cast, since we have at least 1 byte (we use only the first byte)
210 client
->header_length
= (ip_ver
== IPV4VERSION
) ? (((struct iphdr
*) buffer
)->ihl
* 4) : (sizeof(struct ipv6hdr
) + sizeof(struct udphdr
));
212 // Check that Header length is at least 20 (min IPv4 length)
213 if (client
->header_length
< 20)
220 // check split header case
221 if (client
->header_length
> length
)
223 memcpy(client
->splitpacket
, buffer
, length
);
224 client
->splitheader_length
= length
;
228 if (check_header(client
, buffer
))
230 // check split packet case
231 if (client
->packet_length
> length
)
233 memcpy(client
->splitpacket
, buffer
, length
);
234 client
->splitpacket_length
= length
;
245 smsnet_send_packet(buffer
, client
->packet_length
);
247 buffer
+= client
->packet_length
;
248 length
-= client
->packet_length
;
252 smscore_putbuffer(client
->coredev
, cb
);
257 void smsnet_unregister_client(smsnet_client_t
* client
)
259 // must be called under clientslock
261 list_del(&client
->entry
);
263 smscore_unregister_client(client
->smsclient
);
267 void smsnet_onremove(void *context
)
269 kmutex_lock(&g_smsnet_clientslock
);
271 smsnet_unregister_client((smsnet_client_t
*) context
);
273 kmutex_unlock(&g_smsnet_clientslock
);
276 int smsnet_hotplug(smscore_device_t
*coredev
, struct device
* device
, int arrival
)
278 smsclient_params_t params
;
279 smsnet_client_t
* client
;
282 // device removal handled by onremove callback
286 client
= kzalloc(sizeof(smsnet_client_t
), GFP_KERNEL
);
289 printk(KERN_INFO
"%s kmalloc() failed\n", __FUNCTION__
);
293 params
.initial_id
= 0;
294 params
.data_type
= MSG_SMS_DATA_MSG
;
295 params
.onresponse_handler
= smsnet_onresponse
;
296 params
.onremove_handler
= smsnet_onremove
;
297 params
.context
= client
;
299 rc
= smscore_register_client(coredev
, ¶ms
, &client
->smsclient
);
302 printk(KERN_INFO
"%s smscore_register_client() failed %d\n", __FUNCTION__
, rc
);
307 client
->coredev
= coredev
;
309 kmutex_lock(&g_smsnet_clientslock
);
311 list_add(&client
->entry
, &g_smsnet_clients
);
313 kmutex_unlock(&g_smsnet_clientslock
);
315 printk(KERN_INFO
"%s success\n", __FUNCTION__
);
320 static int smsnet_open(struct net_device
*dev
)
324 netif_start_queue(dev
);
326 printk(KERN_INFO
"%s, %d\n", __FUNCTION__
, g_smsnet_inuse
);
331 static int smsnet_stop(struct net_device
*dev
)
333 netif_stop_queue(dev
);
337 printk(KERN_INFO
"%s, %d\n", __FUNCTION__
, g_smsnet_inuse
);
342 static int smsnet_hard_start_xmit(struct sk_buff
*skb
, struct net_device
*dev
)
344 printk(KERN_INFO
"%s\n", __FUNCTION__
);
350 static struct net_device_stats
* smsnet_get_stats(struct net_device
*dev
)
352 return &g_smsnet_stats
;
355 static void smsnet_set_multicast_list(struct net_device
*dev
)
357 printk(KERN_INFO
"%s %d\n", __FUNCTION__
, dev
->mc_count
);
360 struct dev_mc_list
*p
;
362 for (p
= dev
->mc_list
; p
; p
= p
->next
)
363 printk(KERN_INFO
"%s %d %02x %02x %02x %02x %02x %02x %02x %02x\n", __FUNCTION__
, p
->dmi_addrlen
,
364 p
->dmi_addr
[0], p
->dmi_addr
[1], p
->dmi_addr
[2], p
->dmi_addr
[3],
365 p
->dmi_addr
[4], p
->dmi_addr
[5], p
->dmi_addr
[6], p
->dmi_addr
[7]
370 static void smsnet_setup_device(struct net_device
*dev
)
374 dev
->open
= smsnet_open
;
375 dev
->stop
= smsnet_stop
;
376 dev
->hard_start_xmit
= smsnet_hard_start_xmit
;
377 dev
->get_stats
= smsnet_get_stats
;
378 dev
->set_multicast_list
= smsnet_set_multicast_list
;
381 dev
->hard_header_cache
= NULL
;
383 memcpy(dev
->dev_addr
, "\0SIANO", ETH_ALEN
);
385 dev
->flags
|= IFF_NOARP
;
386 dev
->features
|= NETIF_F_NO_CSUM
;
389 int smsnet_module_init(void)
393 INIT_LIST_HEAD(&g_smsnet_clients
);
394 kmutex_init(&g_smsnet_clientslock
);
396 memset(&g_smsnet_stats
, 0, sizeof(g_smsnet_stats
));
398 g_smsnet_device
= alloc_netdev(0, "sms", smsnet_setup_device
);
399 if (!g_smsnet_device
)
401 printk(KERN_INFO
"%s alloc_netdev() failed\n", __FUNCTION__
);
405 rc
= register_netdev(g_smsnet_device
);
408 printk(KERN_INFO
"%s register_netdev() failed %d\n", __FUNCTION__
, rc
);
409 free_netdev(g_smsnet_device
);
413 rc
= smscore_register_hotplug(smsnet_hotplug
);
415 printk(KERN_INFO
"%s, rc %d\n", __FUNCTION__
, rc
);
420 void smsnet_module_exit(void)
424 unregister_netdev(g_smsnet_device
);
425 free_netdev(g_smsnet_device
);
427 g_smsnet_device
= NULL
;
430 smscore_unregister_hotplug(smsnet_hotplug
);
432 kmutex_lock(&g_smsnet_clientslock
);
434 while (!list_empty(&g_smsnet_clients
))
435 smsnet_unregister_client((smsnet_client_t
*) g_smsnet_clients
.next
);
437 kmutex_unlock(&g_smsnet_clientslock
);
439 printk(KERN_INFO
"%s\n", __FUNCTION__
);
442 module_init(smsnet_module_init
);
443 module_exit(smsnet_module_exit
);
445 MODULE_DESCRIPTION("smsnet dvb-h ip sink module");
446 MODULE_AUTHOR("Anatoly Greenblatt,,, (anatolyg@siano-ms.com)");
447 MODULE_LICENSE("GPL");