Krishna iResearch Intelligent Cloud Platform - VIRtual Generic Os - VIRGO - Linux kernel extensions for cloud
 All Classes
virgo_cloudexec.c
1 /***************************************************************************************
2 VIRGO - a linux module extension with CPU and Memory pooling with cloud capabilities
3 
4 Copyright (C) 2009-2013 Ka.Shrinivaasan
5 
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 
19 --------------------------------------------------------------------------------------------------
20 Srinivasan Kannan (alias) Ka.Shrinivaasan (alias) Shrinivas Kannan
21 Independent Open Source Developer, Researcher and Consultant
22 Ph: 9003082186, 9791165980
23 Open Source Products Profile(Krishna iResearch): http://sourceforge.net/users/ka_shrinivaasan
24 Personal website(research): https://sites.google.com/site/kuja27/
25 emails: ka.shrinivaasan@gmail.com, shrinivas.kannan@gmail.com, kashrinivaasan@live.com
26 --------------------------------------------------------------------------------------------------
27 
28 *****************************************************************************************/
29 
30 #include <linux/virgo_queue.h>
31 #include <linux/virgocloudexecsvc.h>
32 #include <linux/virgo_config.h>
33 #include <linux/string.h>
34 #include <linux/kallsyms.h>
35 
36 
37 /*
38 #include <linux/kernel.h>
39 #include <linux/kthread.h>
40 #include <linux/sched.h>
41 #include <linux/module.h>
42 #include <linux/errno.h>
43 #include <linux/fcntl.h>
44 #include <linux/net.h>
45 #include <linux/in.h>
46 #include <linux/inet.h>
47 #include <linux/udp.h>
48 #include <linux/tcp.h>
49 #include <linux/string.h>
50 #include <linux/unistd.h>
51 #include <linux/slab.h>
52 #include <linux/netdevice.h>
53 #include <linux/skbuff.h>
54 #include <linux/file.h>
55 #include <linux/freezer.h>
56 #include <net/sock.h>
57 #include <net/checksum.h>
58 #include <net/ip.h>
59 #include <net/ipv6.h>
60 #include <net/tcp.h>
61 #include <net/tcp_states.h>
62 #include <asm/uaccess.h>
63 #include <asm/ioctls.h>
64 #include <trace/events/skb.h>
65 
66 #include <linux/module.h>
67 #include <linux/types.h>
68 #include <linux/uio.h>
69 #include <linux/unistd.h>
70 #include <linux/init.h>
71 
72 
73 #include <linux/sunrpc/types.h>
74 #include <linux/sunrpc/clnt.h>
75 #include <linux/sunrpc/xdr.h>
76 #include <linux/sunrpc/msg_prot.h>
77 #include <linux/sunrpc/svcsock.h>
78 #include <linux/sunrpc/stats.h>
79 #include <linux/sunrpc/xprt.h>
80 //#include "sunrpc.h"//
81 #include <linux/sunrpc/xprt.h>
82 //#include "netns.h"//
83 
84 #define BUF_SIZE 500
85 typedef int (*FPTR)(void *args);
86 
87 static int virgocloudexec_create(void);
88 static int virgocloudexec_recvfrom(void);
89 static int virgocloudexec_sendto(void);
90 
91 static struct svc_xprt_ops virgo_ops = {
92  .xpo_create = virgocloudexec_create,
93  .xpo_recvfrom = virgocloudexec_recvfrom,
94  .xpo_sendto = virgocloudexec_sendto
95 };
96 
97 static struct svc_xprt_class virgo_class = {
98  .xcl_name = "virgo",
99  .xcl_owner = THIS_MODULE,
100  .xcl_ops = &virgo_ops
101 };
102 
103 
104 
105 struct task_struct *task;
106 int (*cloneFunction_ptr)(void*);
107 char* cloneFunction;
108 int error;
109 char buffer[BUF_SIZE];
110 struct socket *sock;
111 struct sockaddr_in sin;
112 int len=0;
113 struct socket *clientsock;
114 struct kvec iov;
115 struct msghdr msg;
116 int buflen=BUF_SIZE;
117 int nr=0;
118 int args=0;
119 
120 char** node_ip_addrs_in_cloud;
121 int num_cloud_nodes;
122 */
123 
124 
125 /*
126 * The wrapper function that based on switch parameterIsExecutable (values 0,1,2) executes the binary or function data from virgo_clone
127 * system call in either kernel or user address-spaces
128 * - Ka.Shrinivaasan
129 */
130 
131 int clone_func(void* args)
132 {
133  /*
134  * Lack of reflection kind of facilities requires map of function_names to pointers_to_functions to be executed
135  * on cloud. Function name has to be lookedup in the map to get pointer to function. This map is not scalable
136  * if number of functions are in millions and size of the map increases linearly. Also having it in memory is
137  * both CPU and memory intensive.
138  *
139  * Moreover this map has to be synchronized in all nodes for coherency and consistency which is another intensive task.
140  * Thus name to pointer function table is at present not implemented. Suitable way to call a function by name of the function
141  * is yet to be found out and references in this topic are scarce.
142  * - Ka.Shrinivaasan
143  */
144 
145  /*
146  *If parameterIsExecutable is set to 2, the data from virgo_clone() is a function and is executed within kernel address-space itself
147  *Presently just an example function is invoked. Intermodule function invocation functionality which enables complete takeover
148  *of lowlevel system cards, PCI, RAM etc., has been implemented and testcase kern.logs are under ./test_logs/
149  *
150  *If parameterIsExecutable is set to 1 the data received from virgo_clone() is not a function but name of executable
151  *This executable is then run on usermode using call_usermodehelper() which internally takes care of queueing the workstruct
152  *and executes the binary as child of keventd and reaps silently. Thus workqueue component of kernel is indirectly made use of.
153  *This is sometimes more flexible alternative that executes a binary itself on cloud and
154  *is preferable to clone()ing a function on cloud. Virgo_clone() syscall client or telnet needs to send the message with name of binary.
155  *
156  *If parameterIsExecutable is set to 0 then data received from virgo_clone() is name of a function and is executed in else clause
157  *using dlsym() lookup and pthread_create() in user space. This unifies both call_usermodehelper() and creating a userspace thread
158  *with a fixed binary which is same for any function. The dlsym lookup requires mangled function names which need to be sent by
159  *virgo_clone or telnet. This is far more efficient than a function pointer table.
160  *call_usermodehelper() Kernel upcall to usermode to exec a fixed binary that would inturn execute the cloneFunction in userspace
161  *by spawning a pthread. cloneFunction is name of the function and not binary. This clone function will be dlsym()ed
162  *and a pthread will be created by the fixed binary. Name of the fixed binary is hardcoded herein as
163  *"virgo_kernelupcall_plugin". This fixed binary takes clone function as argument. For testing libvirgo.so has been created from
164  *virgo_cloud_test.c and separate build script to build the cloud function binaries has been added.
165  *
166  *- Ka.Shrinivaasan
167  */
168 
169  int ret=0;
170  char *argv[8];
171  char *envp[3];
172 
173  if (parameterIsExecutable==2)
174  {
175  struct task_struct *task;
176  int woken_up_2=0;
177  printk("clone_func(): creating kernel thread and waking up, parameterIsExecutable=%d\n", parameterIsExecutable);
178  /*
179  int (*virgo_cloud_test_kernelspace)(void*);
180  virgo_cloud_test_kernelspace=kallsyms_lookup_name(cloneFunction);
181  */
182  if(use_as_kingcobra_service==1)
183  {
184  printk("clone_func(): VIRGO cloudexec is used as KingCobra service, invoking push_request() in kernelspace for data: %s\n",cloneFunction);
185  struct virgo_request *vrq=kmalloc(sizeof(struct virgo_request),GFP_ATOMIC);
186  vrq->data=kstrdup(cloneFunction,GFP_ATOMIC);
187  vrq->next=NULL;
188  push_request(vrq);
189  /*
190  task=kthread_create(push_request, (void*)args, "KingCobra push_request() thread");
191  woken_up_2=wake_up_process(task);
192  */
193  }
194  else
195  {
196  task=kthread_create(virgo_cloud_test_kernelspace, (void*)args, "cloneFunction thread");
197  woken_up_2=wake_up_process(task);
198  }
199  }
200  else if(parameterIsExecutable==1)
201  {
202  file_stdout=filp_open("/home/kashrinivaasan/linux-3.7.8/drivers/virgo/cpupooling/virgocloudexec/virgo_cloudexec_upcall_usermode_log.txt", O_RDWR|O_APPEND|O_CREAT, S_IRUSR|S_IWUSR);
203  fd_install(1,file_stdout);
204  fd_install(2,file_stdout);
205  argv[0]=kstrdup(cloneFunction,GFP_ATOMIC);
206  /*
207  argv[2]=kstrdup(strcat(argv[2], " >> /home/kashrinivaasan/linux-3.7.8/drivers/virgo/cpupooling/virgocloudexec/virgo_kernelupcall_plugin_userspace_exec.log"),GFP_ATOMIC);
208  */
209  argv[1]=NULL;
210  envp[0]="PATH=/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/home/kashrinivaasan/linux-3.7.8/drivers/virgo/cpupooling/virgocloudexec/";
211  envp[1]="HOME=/home/kashrinivaasan";
212  envp[2]=NULL;
213  /* call_usermodehelper() Kernel upcall to usermode */
214  /* cloneFunction contains name of the binary and not the name of the function */
215  printk("clone_func(): executing call_usermodehelper for data from virgo_clone: %s - parameterIsExecutable=%d\n",cloneFunction, parameterIsExecutable);
216  ret=call_usermodehelper(cloneFunction, argv, envp, UMH_WAIT_EXEC);
217  /*ret=call_usermodehelper("/bin/bash", argv, envp, UMH_WAIT_PROC);*/
218  printk("clone_func(): call_usermodehelper() for binary %s returns ret=%d\n", cloneFunction, ret);
219  filp_close(file_stdout,NULL);
220  }
221  else if (parameterIsExecutable==0)
222  {
223  file_stdout=filp_open("/home/kashrinivaasan/linux-3.7.8/drivers/virgo/cpupooling/virgocloudexec/virgo_cloudexec_upcall_usermode_log.txt", O_RDWR|O_APPEND|O_CREAT, S_IRUSR|S_IWUSR);
224  fd_install(1,file_stdout);
225  fd_install(2,file_stdout);
226  argv[0]=kstrdup("/home/kashrinivaasan/linux-3.7.8/drivers/virgo/cpupooling/virgocloudexec/virgo_kernelupcall_plugin",GFP_ATOMIC);
227  argv[1]=kstrdup(cloneFunction,GFP_ATOMIC);
228  argv[2]=NULL;
229  envp[0]="PATH=/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games::/home/kashrinivaasan/linux-3.7.8/drivers/virgo/cpupooling/virgocloudexec/";
230  envp[1]="HOME=/home/kashrinivaasan";
231  envp[2]=NULL;
232  printk(KERN_INFO "clone_func(): executing the virgo_clone() syscall function parameter in cloud - parameterIsExecutable=%d, cloneFunction=%s\n",parameterIsExecutable,cloneFunction);
233  ret=call_usermodehelper("/home/kashrinivaasan/linux-3.7.8/drivers/virgo/cpupooling/virgocloudexec/virgo_kernelupcall_plugin",argv,envp,UMH_WAIT_EXEC);
234 
235  /*
236  argv[0]=kstrdup("/bin/bash",GFP_ATOMIC);
237  argv[1]=kstrdup("-c",GFP_ATOMIC);
238  argv[2]=kstrdup("/home/kashrinivaasan/linux-3.7.8/drivers/virgo/cpupooling/virgocloudexec/virgo_kernelupcall_plugin",GFP_ATOMIC);
239  argv[3]=kstrdup(cloneFunction,GFP_ATOMIC);
240  argv[4]=NULL;
241  envp[0]="PATH=/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games";
242  envp[1]="HOME=/home/kashrinivaasan";
243  envp[2]=NULL;
244  printk(KERN_INFO "clone_func(): executing the virgo_clone() syscall function parameter in cloud - parameterIsExecutable=%d\n",parameterIsExecutable);
245  ret=call_usermodehelper("/bin/bash",argv,envp,UMH_WAIT_PROC);
246  */
247  printk("clone_func(): call_usermodehelper() for virgo_kernelupcall_plugin returns ret=%d\n", ret);
248  /*
249  Depending on scheduling priority either this or other message in virgocloudexec_sendto() will be sent to
250  virgo_clone() remote syscall
251  */
252  strcpy(buffer,"clone_func(): cloudclonethread executed for clone_func(), sending message to virgo_clone() remote syscall client");
253  filp_close(file_stdout,NULL);
254  }
255  return 1;
256 }
257 
258 char* strip_control_M(char* str)
259 {
260  char* dupstr=kstrdup(str, GFP_ATOMIC);
261  char* newstr=strsep(&dupstr, "\r\n ");
262  return newstr;
263 }
264 
265 int kernel_space_func(void* args)
266 {
267  printk(KERN_INFO "kernel_space_func(): parameterIsExecutable=2; executing function in kernel address space\n");
268  return 0;
269 }
270 
271 void read_virgo_config()
272 {
273  /* virgo_cloud.conf contains a string of comma separated list of IP addresses in the virgo cloud .Read and strtok() it. */
274 
275  loff_t bytesread=0;
276  loff_t pos=0;
277  mm_segment_t fs;
278 
279  /*
280  * It is redundant to use kallsyms_lookup for exported symbols for virgo cloud initialization.
281  * kallsyms_lookup is for non-exported symbols.
282  *
283  * - Ka.Shrinivaasan 10 July 2013
284  *
285 
286  node_ip_addrs_in_cloud=(char**)kallsyms_lookup_name("node_ip_addrs_in_cloud");
287  num_cloud_nodes=kallsyms_lookup_name("num_cloud_nodes");
288 
289  printk(KERN_INFO "virgo kernel service: read_virgo_config(): virgo_cloud config being read... \n");
290  printk(KERN_INFO "virgo kernel service: read_virgo_config(): num_cloud_nodes=%d #### node_ip_addrs_in_cloud=%s\n", num_cloud_nodes,node_ip_addrs_in_cloud);
291  */
292 
293  fs=get_fs();
294  set_fs(get_ds());
295  struct file* f=NULL;
296  f=filp_open("/etc/virgo_cloud.conf", O_RDONLY, 0);
297 
298  char buf[256];
299  int i=0;
300 
301  int k=0;
302  for(k=0;k<256;k++)
303  buf[k]=0;
304 
305  for(k=0; k < num_cloud_nodes; k++)
306  printk(KERN_INFO "virgo kernel service: read_virgo_config(): before reading virgo_cloud.conf - virgo_cloud ip address - %d: %s\n", k+1, node_ip_addrs_in_cloud[k]);
307 
308  printk(KERN_INFO "read_virgo_config(): virgo_cloud config file being read \n");
309 
310 
311  if(f !=NULL)
312  {
313  /*f->f_op->read(f, buf, sizeof(buf), &f->f_pos);*/
314  bytesread=vfs_read(f, buf, 256, &pos);
315  /*strcpy(node_ip_addrs_in_cloud[i],buf);*/
316  printk(KERN_INFO "do_virgo_cloud_init(): virgo_cloud config file string of comma separated IPs : %s \n",buf);
317  /*printk(KERN_INFO "do_virgo_cloud_init(): virgo_cloud config file line %d \n",i);*/
318  pos=pos+bytesread;
319  }
320  /*num_cloud_nodes=tokenize_list_of_ip_addrs(buf);*/
321  char* delim=",";
322  char* token=NULL;
323  char* bufdup=kstrdup(buf,GFP_ATOMIC);
324  printk(KERN_INFO "tokenize_list_of_ip_addrs(): bufdup = %s\n",bufdup);
325  while(bufdup != NULL)
326  {
327  token=strsep(&bufdup, delim);
328  printk(KERN_INFO "tokenize_list_of_ip_addrs(): %s\n",token);
329  node_ip_addrs_in_cloud[i]=kstrdup(token,GFP_ATOMIC);
330  printk(KERN_INFO "tokenize_list_of_ip_addrs(): node_ip_addrs_in_cloud[%d] = %s\n",i,node_ip_addrs_in_cloud[i]);
331  i++;
332  }
333  num_cloud_nodes=i;
334  set_fs(fs);
335  filp_close(f,NULL);
336 }
337 
338 /*
339 Above tokenization made into a function - if needed can be used as multipurpose exported function
340 */
341 int tokenize_list_of_ip_addrs(char* buf)
342 {
343  char* delim=",";
344  char* token=NULL;
345  char* bufdup=kstrdup(buf,GFP_ATOMIC);
346  printk(KERN_INFO, "tokenize_list_of_ip_addrs(): bufdup = %s\n",bufdup);
347  int i=0;
348  while(bufdup != NULL)
349  {
350  token=strsep(&bufdup, delim);
351  printk(KERN_INFO, "tokenize_list_of_ip_addrs(): %s\n",token);
352  /*strcpy(node_ip_addrs_in_cloud[i], token);*/
353  i++;
354  }
355  return i;
356 }
357 
358 /*
359 FPTR get_function_ptr_from_str(char* cloneFunction)
360 {
361  return clone_func;
362 }
363 */
364 
365 static int __init
366 virgocloudexec_init(void)
367 {
368  printk(KERN_INFO "virgocloudexec_init(): doing init() of virgocloudexec kernel module\n");
369  printk(KERN_INFO "virgocloudexec_init(): starting virgo cloudexec service kernel thread\n");
370 
371  printk(KERN_INFO "virgocloudexec_init(): invoking read_virgo_config()\n");
372  read_virgo_config();
373 
374  memset(&sin, 0, sizeof(struct sockaddr_in));
375  sin.sin_family=AF_INET;
376  sin.sin_addr.s_addr=htonl(INADDR_ANY);
377  sin.sin_port=htons(10000);
378 
379  /*stack=kmalloc(65536, GFP_KERNEL);*/
380  error = sock_create_kern(AF_INET, SOCK_STREAM, IPPROTO_TCP, &sock);
381  printk(KERN_INFO "virgocloudexec_init(): sock_create() returns error code: %d\n",error);
382 
383  error = kernel_bind(sock, (struct sockaddr*)&sin, sizeof(struct sockaddr_in));
384  printk(KERN_INFO "virgocloudexec_init(): kernel_bind() returns error code: %d\n",error);
385 
386  error = kernel_listen(sock, 2);
387  printk(KERN_INFO "virgocloudexec_init(): kernel_listen() returns error code: %d\n", error);
388 
389  virgo_cloudexec_service(NULL);
390 
391  /*
392  file_stdout=filp_open("/home/kashrinivaasan/linux-3.7.8/drivers/virgo/cpupooling/virgocloudexec/virgo_cloudexec_upcall_usermode_log.txt", O_RDWR|O_APPEND|O_CREAT, S_IRUSR|S_IWUSR);
393  fd_install(1,file_stdout);
394  fd_install(2,file_stdout);
395  */
396  return 0;
397 }
398 EXPORT_SYMBOL(virgocloudexec_init);
399 
400 int virgocloudexec_create(void)
401 {
402  /*
403  Blocking mode works in this commit again. No changes were made in virgo_clone() or driver code.
404  Hence making it a blocking socket. Root cause for this weird behaviour remains unknown.
405  -Ka.Shrinivaasan
406  */
407 
408  /*
409  Multithreaded VIRGO Kernel Service
410  ----------------------------------
411  */
412  struct socket *clientsock;
413 
414  clientsock=NULL;
415  error = kernel_accept(sock, &clientsock, 0);
416 
417  /*
418  Blocking mode was working and kernel thread was listening and accepting connections without blocking the bootup till previous commit,
419  but suddenly it started to block on startup. Reason unknown (could be anything from hardware microcode update to external
420  causes viz., intrusion. These kind of events recur with high frequency. Needs further investigation).
421  There seems to be no error in the driver kernel service thread or syscall client.
422 
423  Making it temporarily O_NONBLOCK which seems to be quite a cleaner way despite EAGAIN to accept connections as this is always
424  in a while loop for server.
425 
426  Moreover the driver modules_install places it in /lib/modules/`uname -r`/extra which did not occur in previous commit. Origin
427  again mysterious.
428 
429  -Ka.Shrinivaasan
430  error = kernel_accept(sock, &clientsock, O_NONBLOCK);
431  */
432  /*
433  if(error==-EAGAIN)
434  printk(KERN_INFO "kernel_accept() returns -EAGAIN\n");
435  printk(KERN_INFO "virgocloudexec_create(): kernel_accept() returns error code: %d\n",error);
436  printk(KERN_INFO "virgocloudexec_create(): kernel_accept() clientsock: %u\n",clientsock);
437  */
438  return clientsock;
439 }
440 EXPORT_SYMBOL(virgocloudexec_create);
441 
442 int virgocloudexec_recvfrom(struct socket* clsock)
443 {
444  /*
445  Multithreaded VIRGO Kernel Service
446  ----------------------------------
447  */
448  struct socket *clientsock=clsock;
449  struct kvec iov;
450  struct msghdr msg = { NULL, };
451  int buflen=BUF_SIZE;
452  void *args=NULL;
453  int nr=1;
454 
455  struct task_struct *task;
456  int error;
457  char buffer[BUF_SIZE];
458  char *client_ip_str;
459  int len=0;
460 
461  /*
462  do kernel_recvmsg() to get the function data to be executed on a thread
463  */
464  /*
465  printk(KERN_INFO "virgocloudexec_recvfrom(): clientsock: %u\n",clientsock);
466  */
467  if(clientsock != NULL )
468  {
469  printk(KERN_INFO "virgocloudexec_recvfrom(): before kernel_recvmsg()\n");
470  memset(buffer, 0, sizeof(buffer));
471  iov.iov_base=(void*)buffer;
472  iov.iov_len=sizeof(buffer);
473  msg.msg_name = (struct sockaddr *) &sin;
474  msg.msg_namelen = sizeof(struct sockaddr);
475  msg.msg_iov = (struct iovec *) &iov;
476  msg.msg_iovlen = 1;
477  msg.msg_control = NULL;
478  msg.msg_controllen = 0;
479  /*msg.msg_flags=0;*/
480  msg.msg_flags=MSG_NOSIGNAL;
481 
482  /*
483  len = kernel_recvmsg(clientsock, &msg, &iov, nr, BUF_SIZE, msg.msg_flags);
484  */
485  len = kernel_recvmsg(clientsock, &msg, &iov, 1, buflen, msg.msg_flags);
486  printk(KERN_INFO "virgocloudexec_recvfrom(): kernel_recvmsg() returns len: %d\n",len);
487  /*
488  parse the message and invoke kthread_create()
489  do kernel_sendmsg() with the results
490  */
491  cloneFunction = strip_control_M(kstrdup(buffer,GFP_ATOMIC));
492  if(use_as_kingcobra_service==1)
493  {
494  client_ip_str=kmalloc(BUF_SIZE,GFP_ATOMIC);
495  struct sockaddr_in* ipaddr=(struct sockaddr_in*)clientsock;
496  long ipaddr_int = ipaddr->sin_addr.s_addr;
497  /*inet_ntop(AF_INET, &ipaddr_int, client_ip_str, BUF_SIZE);*/
498  sprintf(client_ip_str,"%x",ipaddr_int);
499  printk(KERN_INFO "virgocloudexec_recvfrom(): client_ip_str = %s\n",client_ip_str);
500  client_ip_str=kstrdup(strcat(client_ip_str,"#"),GFP_ATOMIC);
501  printk(KERN_INFO "virgocloudexec_recvfrom(): client_ip_str with # appended = %s\n",client_ip_str);
502  cloneFunction = kstrdup(strcat(client_ip_str,cloneFunction),GFP_ATOMIC);
503  printk(KERN_INFO "virgocloudexec_recvfrom(): use_as_kingcobra_service=1, cloneFunction with prepended client ip=%s\n",cloneFunction);
504  }
505  /*cloneFunction[strlen(cloneFunction)-2]='\0';*/
506 
507  printk(KERN_INFO "virgocloudexec_recvfrom(): kernel_recvmsg() returns in recv buffer: %s\n", buffer);
508  print_buffer(buffer);
509  le32_to_cpus(buffer);
510  printk(KERN_INFO "virgocloudexec_recvfrom(): kernel_recvmsg() le32 to cpu %s\n", buffer);
511  printk(KERN_INFO "virgocloudexec_recvfrom(): cloneFunction : %s \n", cloneFunction);
512  /*cloneFunction_ptr = get_function_ptr_from_str(cloneFunction);*/
513  /*task=kthread_run(cloneFunction_ptr, (void*)args, "cloudclonethread");*/
514  task=kthread_create(clone_func, (void*)args, "clone_func thread");
515  int woken_up=wake_up_process(task);
516  printk(KERN_INFO "virgocloudexec_recvfrom(): clone thread woken_up : %d\n",woken_up);
517  /*
518  task=kthread_create(clone_func, (void*)args, "cloudclonethread");
519  strcpy(buffer,"cloudclonethread executed");
520  */
521  }
522  return 0;
523 }
524 EXPORT_SYMBOL(virgocloudexec_recvfrom);
525 
526 void print_buffer(char* buffer)
527 {
528  printk(KERN_INFO "print_buffer(): ");
529  int i=0;
530  for(i=0; i < sizeof(buffer); i++)
531  printk(KERN_INFO "%c", buffer[i]);
532  printk(KERN_INFO "\n");
533 }
534 
535 int virgocloudexec_sendto(struct socket* clsock)
536 {
537  /*
538  Multithreaded VIRGO Kernel Service
539  ----------------------------------
540  */
541 
542  struct socket *clientsock=clsock;
543  struct kvec iov;
544  struct msghdr msg = { NULL, };
545  int buflen=BUF_SIZE;
546  void *args=NULL;
547  int nr=1;
548 
549  struct task_struct *task;
550  int error;
551  char buffer[BUF_SIZE];
552  int len=0;
553 
554  /*
555  printk(KERN_INFO "virgocloudexec_sendto(): clientsock: %u\n",clientsock);
556  */
557  if(clientsock != NULL)
558  {
559  strcpy(buffer,"virgo_cloudexec_sendto(): cloudclonethread executed for clone_func(), sending message to virgo_clone() remote syscall client\n");
560  /*iov.iov_base=(void*)buffer;*/
561  /*memset(buffer, 0, sizeof(buffer));*/
562  iov.iov_base=buffer;
563  /*iov.iov_len=BUF_SIZE;*/
564  iov.iov_len=sizeof(buffer);
565  msg.msg_name = (struct sockaddr *) &sin;
566  msg.msg_namelen = sizeof(struct sockaddr);
567  msg.msg_iov = (struct iovec *) &iov;
568  msg.msg_iovlen = 1;
569  msg.msg_control = NULL;
570  msg.msg_controllen = 0;
571  msg.msg_flags=0;
572 
573  int ret;
574  printk(KERN_INFO "virgocloudexec_sendto(): before kernel_sendmsg() for send buffer: %s\n", buffer);
575  ret = kernel_sendmsg(clientsock, &msg, &iov, 1, buflen);
576  /*len = kernel_recvmsg(clientsock, &msg, &iov, 1, buflen, msg.msg_flags);*/
577  /*ret = kernel_sendmsg(clientsock, &msg, &iov, nr, buflen);*/
578  printk(KERN_INFO "virgocloudexec_sendto(): kernel_sendmsg() returns ret: %d\n",ret);
579  /*
580  printk(KERN_INFO "virgocloudexec_sendto(): kernel_recvmsg() returns len: %d\n",len);
581  printk(KERN_INFO "virgocloudexec_sendto(): kernel_recvmsg() returns in recv buffer: %s\n", buffer);
582  */
583  kernel_sock_shutdown(clientsock,SOCK_WAKE_URG);
584  printk(KERN_INFO "virgocloudexec_sendto(): Shut down Kernel Side Client Socket with SOCK_WAKE_URG after sendmsg \n");
585  sock_release(clientsock);
586  printk(KERN_INFO "virgocloudexec_sendto(): sock_release invoked on client socket \n");
587  }
588  return 0;
589 
590  /*
591  struct task_struct *task;
592  int error;
593  struct addrinfo hints;
594  struct socket* sock;
595  struct socket* client_sock;
596  struct addrinfo *result, *rp;
597  int sfd, s;
598  struct sockaddr_storage peer_addr;
599  socklen_t peer_addr_len;
600  ssize_t nread;
601  char buf[BUF_SIZE];
602  struct kvec iov;
603  struct msghdr msg = {
604  .msg_flags = MSG_DONTWAIT,
605  };
606 
607  memset(&hints, 0, sizeof(struct addrinfo));
608  hints.ai_family = AF_UNSPEC; / Allow IPv4 or IPv6 /
609  hints.ai_socktype = SOCK_STREAM; / Datagram socket /
610  hints.ai_flags = AI_PASSIVE; / For wildcard IP address /
611  hints.ai_protocol = 0; / Any protocol /
612  hints.ai_canonname = NULL;
613  hints.ai_addr = NULL;
614  hints.ai_next = NULL;
615 
616  char* cloud_clone_port=60000;
617 
618  stack=kmalloc(65536, GFP_KERNEL);
619  iov.iov_base=(void*)buf;
620  iov.iov_len=BUF_SIZE;
621  s = getaddrinfo(NULL, cloud_clone_port, &hints, &result);
622 
623  sock_create(rp->ai_family, rp->ai_socktype,
624  rp->ai_protocol, sock);
625 
626  kernel_bind(sock, rp->ai_addr, rp->ai_addrlen);
627  kernel_listen(sock,64);
628 
629  freeaddrinfo(result); / No longer needed /
630 
631  error = kernel_accept(sock, clientsock, O_NONBLOCK);
632 
633  for (;;) {
634  nread = kernel_recvmsg(clientsock, &msg, buflen, &iov, nr, msg.msg_flags);
635 
636  char* cloneFunction = kstrdup(iov.iov_base,GFP_KERNEL);
637 
638  int ((*cloneFunction_ptr)(void*));
639  cloneFunction_ptr = get_function_ptr_from_str(cloneFunction);
640  int *args=0;
641  task=kthread_create(cloneFunction_ptr, (void*)args, "cloudclonethread");
642  strcpy(buffer,"cloudclonethread executed");
643  iov.iov_base=(void*)buf;
644  iov.iov_len=BUF_SIZE;
645  kernel_sendmsg(clientsock, &msg, buflen, &iov, nr);
646  }
647  */
648 
649 }
650 EXPORT_SYMBOL(virgocloudexec_sendto);
651 
652 
653 static void __exit
654 virgocloudexec_exit(void)
655 {
656  printk(KERN_INFO "exiting virgocloudexec kernel module \n");
657  /*filp_close(file_stdout,NULL);*/
658  do_exit(1);
659 }
660 EXPORT_SYMBOL(virgocloudexec_exit);
661 
662 
663 MODULE_LICENSE("GPL");
664 module_init(virgocloudexec_init);
665 module_exit(virgocloudexec_exit);