/sysfs.c

https://bitbucket.org/fwilliams/ncm · C · 210 lines · 170 code · 21 blank · 19 comment · 57 complexity · fa5c0219ccde879f2ce03d296d764e82 MD5 · raw file

  1. #include <linux/kernel.h>
  2. #include <linux/module.h>
  3. #include <linux/types.h>
  4. #include <linux/slab.h>
  5. #include "sysfs.h"
  6. // sscanf(buf, "%d", &a->value);
  7. static ncm_sysfs_t sysfs;
  8. // the attrs here are wrapped twice: once inside a kobj_attribute and once inside a ncm_attr_t
  9. static struct attribute *attrs[MAX_VARIABLES+1];
  10. static struct attribute_group attr_group = {
  11. .name = "varspace",
  12. .attrs = attrs,
  13. };
  14. static ssize_t ncm_sysfs_var_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) {
  15. u32 klen, var;
  16. sscanf(attr->attr.name, "%i", &var);
  17. get_variable_data(&sysfs.ncm_interp->variable_space, var, buf, &klen);
  18. return klen;
  19. }
  20. static ssize_t ncm_sysfs_var_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t len) {
  21. u32 var;
  22. sscanf(attr->attr.name, "%i", &var);
  23. set_variable_data(&sysfs.ncm_interp->variable_space, var, (u8*)buf, len);
  24. return len;
  25. }
  26. static ssize_t ncm_sysfs_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) {
  27. u32 channels;
  28. if(strcmp(attr->attr.name, "code") == 0){
  29. // dump the interpreter array
  30. memcpy(buf, sysfs.program->instructions, sizeof(ncm_instr_t) * sysfs.program->length);
  31. return sizeof(ncm_instr_t) * sysfs.program->length;
  32. } else if(strcmp(attr->attr.name, "control") == 0){
  33. if(is_running(sysfs.ncm_interp)){
  34. memcpy(buf, "running\n", sizeof("running\n"));
  35. return sizeof("running\n");
  36. } else {
  37. memcpy(buf, "not running\n", sizeof("not running\n"));
  38. return sizeof("not running\n");
  39. }
  40. } else if(strcmp(attr->attr.name, "params") == 0){
  41. channels = sysfs.interp_params->network.channels;
  42. memcpy(buf, sysfs.interp_params, sizeof(sysfs.interp_params->network.channels));
  43. // copy to the end of the known size part, overwriting all the pointers we don't want to save
  44. // note that net_device_name has to be the first pointer in unknown size part
  45. memcpy(buf + sizeof(sysfs.interp_params->network.channels), sysfs.interp_params->network.net_device_name,
  46. channels * IFNAMSIZ);
  47. memcpy(buf + sizeof(sysfs.interp_params->network.channels) + channels * IFNAMSIZ, sysfs.interp_params->network.channel_mac,
  48. channels * ETH_ALEN);
  49. return sizeof(sysfs.interp_params->network.channels) + channels * (IFNAMSIZ + ETH_ALEN);
  50. } else {
  51. return 0;
  52. }
  53. // return scnprintf(buf, PAGE_SIZE, "%d\n", a->value);
  54. }
  55. static ssize_t ncm_sysfs_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t len) {
  56. u32 channels;
  57. ncm_net_params_t *network;
  58. if(strcmp(attr->attr.name, "params") == 0){
  59. // make sure we don't modify interpreter state while it's running
  60. if(!is_running(sysfs.ncm_interp)){
  61. // make sure the input is correctly formatted
  62. channels = ((ncm_interp_params_t*)buf)->network.channels;
  63. if(len == sizeof(sysfs.interp_params->network.channels) + (IFNAMSIZ+ETH_ALEN) * channels){
  64. network = &sysfs.interp_params->network;
  65. // free the old params if there were any
  66. if(network->net_device_name != 0){
  67. kfree(network->net_device_name);
  68. }
  69. if(network->channel_mac != 0){
  70. kfree(network->channel_mac);
  71. }
  72. // copy the given data to the new params
  73. memcpy(sysfs.interp_params, buf, sizeof(sysfs.interp_params->network.channels));
  74. // create new params
  75. network->net_device_name = kmalloc(IFNAMSIZ * channels, GFP_KERNEL);
  76. network->channel_mac = kmalloc(ETH_ALEN * channels, GFP_KERNEL);
  77. memcpy(network->net_device_name, buf + sizeof(sysfs.interp_params->network.channels), IFNAMSIZ * channels);
  78. memcpy(network->channel_mac, buf + sizeof(sysfs.interp_params->network.channels) +
  79. IFNAMSIZ * channels, ETH_ALEN * channels);
  80. } else {
  81. printk(KERN_WARNING "Invalid params file.");
  82. }
  83. } else {
  84. printk(KERN_WARNING "Tried to load params into running ncm program. Please stop it first.");
  85. }
  86. } else if(strcmp(attr->attr.name, "code") == 0){
  87. // make sure we don't modify interpreter state while it's running
  88. if(!is_running(sysfs.ncm_interp)){
  89. // free the instructions if there were any
  90. if(sysfs.program->instructions != 0){
  91. kfree(sysfs.program->instructions);
  92. }
  93. // create new instructions block
  94. sysfs.program->instructions = kmalloc(len, GFP_KERNEL);
  95. sysfs.program->length = len;
  96. // copy the given data into it
  97. memcpy(sysfs.program->instructions, buf, len);
  98. } else {
  99. printk(KERN_WARNING "Tried to load code into running ncm program. Please stop it first.");
  100. }
  101. } else if(strcmp(attr->attr.name, "control") == 0){
  102. // if you write "run" into the command
  103. if(memcmp(buf, "run", 3) == 0){
  104. if(!is_running(sysfs.ncm_interp)){
  105. if(sysfs.program->instructions == NULL){
  106. printk(KERN_WARNING "Cannot start because no network code program has been loaded.");
  107. return len;
  108. }
  109. if(sysfs.interp_params->network.net_device_name == NULL || sysfs.interp_params->network.channel_mac == NULL){
  110. printk(KERN_WARNING "Cannot start because no network code parameters have been loaded.");
  111. return len;
  112. }
  113. start_interpreter(sysfs.ncm_interp, sysfs.program, sysfs.interp_params);
  114. }
  115. // if you write "stop" into the command
  116. } else if (memcmp(buf, "stop", 4) == 0){
  117. if(is_running(sysfs.ncm_interp)){
  118. stop_interpreter(sysfs.ncm_interp);
  119. }
  120. } else {
  121. return len;
  122. }
  123. } else {
  124. return len;
  125. }
  126. return len;// return ??
  127. }
  128. struct kobj_attribute nc_sysfs_attr_code = {
  129. .attr = {"code", 0644},
  130. .show = ncm_sysfs_show,
  131. .store = ncm_sysfs_store
  132. };
  133. struct kobj_attribute nc_sysfs_attr_params = {
  134. .attr = {"params", 0644},
  135. .show = ncm_sysfs_show,
  136. .store = ncm_sysfs_store
  137. };
  138. struct kobj_attribute nc_sysfs_attr_control = {
  139. .attr = {"control", 0644},
  140. .show = ncm_sysfs_show,
  141. .store = ncm_sysfs_store
  142. };
  143. char sysfs_var_names[MAX_VARIABLES][ATTR_NAME_LEN];
  144. int nc_init_sysfs(ncm_interpreter_t *ncm_interp,
  145. ncm_program_t *program, ncm_interp_params_t *interp_params) {
  146. int err = 0, i;
  147. struct kobj_attribute *kattr;
  148. // pack the struct in the needed format to set up the sysfs device
  149. sysfs.program = program;
  150. sysfs.interp_params = interp_params;
  151. sysfs.ncm_interp = ncm_interp;
  152. sysfs.nc_kobj = kobject_create_and_add("network_code", NULL);
  153. if (!sysfs.nc_kobj)
  154. return -ENOMEM;
  155. for(i=0; i<MAX_VARIABLES; i++){
  156. kattr = kzalloc(sizeof(struct kobj_attribute), GFP_KERNEL);
  157. snprintf(sysfs_var_names[i], ATTR_NAME_LEN, "%i" , i);
  158. kattr->attr.name = sysfs_var_names[i];
  159. kattr->attr.mode = 0666;
  160. kattr->show = ncm_sysfs_var_show;
  161. kattr->store = ncm_sysfs_var_store;
  162. attrs[i] = &kattr->attr;
  163. }
  164. attrs[i] = NULL;
  165. err = sysfs_create_file(sysfs.nc_kobj, &nc_sysfs_attr_code.attr);
  166. if (err) goto err;
  167. err = sysfs_create_file(sysfs.nc_kobj, &nc_sysfs_attr_control.attr);
  168. if (err) goto err;
  169. err = sysfs_create_file(sysfs.nc_kobj, &nc_sysfs_attr_params.attr);
  170. if (err) goto err;
  171. err = sysfs_create_group(sysfs.nc_kobj, &attr_group);
  172. if (err) goto err;
  173. return err;
  174. err:
  175. kobject_put(sysfs.nc_kobj);
  176. sysfs.nc_kobj = NULL;
  177. return err;
  178. }
  179. void ncm_sysfs_cleanup(void){
  180. //free attrs
  181. int i;
  182. for(i=0; i<MAX_VARIABLES; i++){
  183. if(attrs[i] != 0)
  184. kfree(container_of(attrs[i], struct kobj_attribute, attr));
  185. }
  186. if (sysfs.nc_kobj) {
  187. kobject_put(sysfs.nc_kobj);
  188. }
  189. }