net_user.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /*
  2. * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
  3. * Licensed under the GPL
  4. */
  5. #include <stddef.h>
  6. #include <stdarg.h>
  7. #include <unistd.h>
  8. #include <stdio.h>
  9. #include <errno.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <sys/socket.h>
  13. #include <sys/wait.h>
  14. #include "user.h"
  15. #include "user_util.h"
  16. #include "kern_util.h"
  17. #include "net_user.h"
  18. #include "os.h"
  19. int tap_open_common(void *dev, char *gate_addr)
  20. {
  21. int tap_addr[4];
  22. if(gate_addr == NULL) return(0);
  23. if(sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0],
  24. &tap_addr[1], &tap_addr[2], &tap_addr[3]) != 4){
  25. printk("Invalid tap IP address - '%s'\n", gate_addr);
  26. return(-EINVAL);
  27. }
  28. return(0);
  29. }
  30. void tap_check_ips(char *gate_addr, unsigned char *eth_addr)
  31. {
  32. int tap_addr[4];
  33. if((gate_addr != NULL) &&
  34. (sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0],
  35. &tap_addr[1], &tap_addr[2], &tap_addr[3]) == 4) &&
  36. (eth_addr[0] == tap_addr[0]) &&
  37. (eth_addr[1] == tap_addr[1]) &&
  38. (eth_addr[2] == tap_addr[2]) &&
  39. (eth_addr[3] == tap_addr[3])){
  40. printk("The tap IP address and the UML eth IP address"
  41. " must be different\n");
  42. }
  43. }
  44. /* Do reliable error handling as this fails frequently enough. */
  45. void read_output(int fd, char *output, int len)
  46. {
  47. int remain, ret, expected;
  48. char c;
  49. char *str;
  50. if(output == NULL){
  51. output = &c;
  52. len = sizeof(c);
  53. }
  54. *output = '\0';
  55. ret = os_read_file(fd, &remain, sizeof(remain));
  56. if (ret != sizeof(remain)) {
  57. expected = sizeof(remain);
  58. str = "length";
  59. goto err;
  60. }
  61. while(remain != 0){
  62. expected = (remain < len) ? remain : len;
  63. ret = os_read_file(fd, output, expected);
  64. if (ret != expected) {
  65. str = "data";
  66. goto err;
  67. }
  68. remain -= ret;
  69. }
  70. return;
  71. err:
  72. if (ret < 0)
  73. printk("read_output - read of %s failed, errno = %d\n", str, -ret);
  74. else
  75. printk("read_output - read of %s failed, read only %d of %d bytes\n", str, ret, expected);
  76. }
  77. int net_read(int fd, void *buf, int len)
  78. {
  79. int n;
  80. n = os_read_file(fd, buf, len);
  81. if(n == -EAGAIN)
  82. return(0);
  83. else if(n == 0)
  84. return(-ENOTCONN);
  85. return(n);
  86. }
  87. int net_recvfrom(int fd, void *buf, int len)
  88. {
  89. int n;
  90. while(((n = recvfrom(fd, buf, len, 0, NULL, NULL)) < 0) &&
  91. (errno == EINTR)) ;
  92. if(n < 0){
  93. if(errno == EAGAIN) return(0);
  94. return(-errno);
  95. }
  96. else if(n == 0) return(-ENOTCONN);
  97. return(n);
  98. }
  99. int net_write(int fd, void *buf, int len)
  100. {
  101. int n;
  102. n = os_write_file(fd, buf, len);
  103. if(n == -EAGAIN)
  104. return(0);
  105. else if(n == 0)
  106. return(-ENOTCONN);
  107. return(n);
  108. }
  109. int net_send(int fd, void *buf, int len)
  110. {
  111. int n;
  112. while(((n = send(fd, buf, len, 0)) < 0) && (errno == EINTR)) ;
  113. if(n < 0){
  114. if(errno == EAGAIN) return(0);
  115. return(-errno);
  116. }
  117. else if(n == 0) return(-ENOTCONN);
  118. return(n);
  119. }
  120. int net_sendto(int fd, void *buf, int len, void *to, int sock_len)
  121. {
  122. int n;
  123. while(((n = sendto(fd, buf, len, 0, (struct sockaddr *) to,
  124. sock_len)) < 0) && (errno == EINTR)) ;
  125. if(n < 0){
  126. if(errno == EAGAIN) return(0);
  127. return(-errno);
  128. }
  129. else if(n == 0) return(-ENOTCONN);
  130. return(n);
  131. }
  132. struct change_pre_exec_data {
  133. int close_me;
  134. int stdout;
  135. };
  136. static void change_pre_exec(void *arg)
  137. {
  138. struct change_pre_exec_data *data = arg;
  139. os_close_file(data->close_me);
  140. dup2(data->stdout, 1);
  141. }
  142. static int change_tramp(char **argv, char *output, int output_len)
  143. {
  144. int pid, fds[2], err;
  145. struct change_pre_exec_data pe_data;
  146. err = os_pipe(fds, 1, 0);
  147. if(err < 0){
  148. printk("change_tramp - pipe failed, err = %d\n", -err);
  149. return(err);
  150. }
  151. pe_data.close_me = fds[0];
  152. pe_data.stdout = fds[1];
  153. pid = run_helper(change_pre_exec, &pe_data, argv, NULL);
  154. if (pid > 0) /* Avoid hang as we won't get data in failure case. */
  155. read_output(fds[0], output, output_len);
  156. os_close_file(fds[0]);
  157. os_close_file(fds[1]);
  158. if (pid > 0)
  159. CATCH_EINTR(err = waitpid(pid, NULL, 0));
  160. return(pid);
  161. }
  162. static void change(char *dev, char *what, unsigned char *addr,
  163. unsigned char *netmask)
  164. {
  165. char addr_buf[sizeof("255.255.255.255\0")];
  166. char netmask_buf[sizeof("255.255.255.255\0")];
  167. char version[sizeof("nnnnn\0")];
  168. char *argv[] = { "uml_net", version, what, dev, addr_buf,
  169. netmask_buf, NULL };
  170. char *output;
  171. int output_len, pid;
  172. sprintf(version, "%d", UML_NET_VERSION);
  173. sprintf(addr_buf, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
  174. sprintf(netmask_buf, "%d.%d.%d.%d", netmask[0], netmask[1],
  175. netmask[2], netmask[3]);
  176. output_len = page_size();
  177. output = um_kmalloc(output_len);
  178. if(output == NULL)
  179. printk("change : failed to allocate output buffer\n");
  180. pid = change_tramp(argv, output, output_len);
  181. if(pid < 0) return;
  182. if(output != NULL){
  183. printk("%s", output);
  184. kfree(output);
  185. }
  186. }
  187. void open_addr(unsigned char *addr, unsigned char *netmask, void *arg)
  188. {
  189. change(arg, "add", addr, netmask);
  190. }
  191. void close_addr(unsigned char *addr, unsigned char *netmask, void *arg)
  192. {
  193. change(arg, "del", addr, netmask);
  194. }
  195. char *split_if_spec(char *str, ...)
  196. {
  197. char **arg, *end;
  198. va_list ap;
  199. va_start(ap, str);
  200. while((arg = va_arg(ap, char **)) != NULL){
  201. if(*str == '\0')
  202. return(NULL);
  203. end = strchr(str, ',');
  204. if(end != str)
  205. *arg = str;
  206. if(end == NULL)
  207. return(NULL);
  208. *end++ = '\0';
  209. str = end;
  210. }
  211. va_end(ap);
  212. return(str);
  213. }
  214. /*
  215. * Overrides for Emacs so that we follow Linus's tabbing style.
  216. * Emacs will notice this stuff at the end of the file and automatically
  217. * adjust the settings for this buffer only. This must remain at the end
  218. * of the file.
  219. * ---------------------------------------------------------------------------
  220. * Local variables:
  221. * c-file-style: "linux"
  222. * End:
  223. */