net_user.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  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. void read_output(int fd, char *output, int len)
  45. {
  46. int remain, n, actual;
  47. char c;
  48. if(output == NULL){
  49. output = &c;
  50. len = sizeof(c);
  51. }
  52. *output = '\0';
  53. n = os_read_file(fd, &remain, sizeof(remain));
  54. if(n != sizeof(remain)){
  55. printk("read_output - read of length failed, err = %d\n", -n);
  56. return;
  57. }
  58. while(remain != 0){
  59. n = (remain < len) ? remain : len;
  60. actual = os_read_file(fd, output, n);
  61. if(actual != n){
  62. printk("read_output - read of data failed, "
  63. "err = %d\n", -actual);
  64. return;
  65. }
  66. remain -= actual;
  67. }
  68. return;
  69. }
  70. int net_read(int fd, void *buf, int len)
  71. {
  72. int n;
  73. n = os_read_file(fd, buf, len);
  74. if(n == -EAGAIN)
  75. return(0);
  76. else if(n == 0)
  77. return(-ENOTCONN);
  78. return(n);
  79. }
  80. int net_recvfrom(int fd, void *buf, int len)
  81. {
  82. int n;
  83. while(((n = recvfrom(fd, buf, len, 0, NULL, NULL)) < 0) &&
  84. (errno == EINTR)) ;
  85. if(n < 0){
  86. if(errno == EAGAIN) return(0);
  87. return(-errno);
  88. }
  89. else if(n == 0) return(-ENOTCONN);
  90. return(n);
  91. }
  92. int net_write(int fd, void *buf, int len)
  93. {
  94. int n;
  95. n = os_write_file(fd, buf, len);
  96. if(n == -EAGAIN)
  97. return(0);
  98. else if(n == 0)
  99. return(-ENOTCONN);
  100. return(n);
  101. }
  102. int net_send(int fd, void *buf, int len)
  103. {
  104. int n;
  105. while(((n = send(fd, buf, len, 0)) < 0) && (errno == EINTR)) ;
  106. if(n < 0){
  107. if(errno == EAGAIN) return(0);
  108. return(-errno);
  109. }
  110. else if(n == 0) return(-ENOTCONN);
  111. return(n);
  112. }
  113. int net_sendto(int fd, void *buf, int len, void *to, int sock_len)
  114. {
  115. int n;
  116. while(((n = sendto(fd, buf, len, 0, (struct sockaddr *) to,
  117. sock_len)) < 0) && (errno == EINTR)) ;
  118. if(n < 0){
  119. if(errno == EAGAIN) return(0);
  120. return(-errno);
  121. }
  122. else if(n == 0) return(-ENOTCONN);
  123. return(n);
  124. }
  125. struct change_pre_exec_data {
  126. int close_me;
  127. int stdout;
  128. };
  129. static void change_pre_exec(void *arg)
  130. {
  131. struct change_pre_exec_data *data = arg;
  132. os_close_file(data->close_me);
  133. dup2(data->stdout, 1);
  134. }
  135. static int change_tramp(char **argv, char *output, int output_len)
  136. {
  137. int pid, fds[2], err;
  138. struct change_pre_exec_data pe_data;
  139. err = os_pipe(fds, 1, 0);
  140. if(err < 0){
  141. printk("change_tramp - pipe failed, err = %d\n", -err);
  142. return(err);
  143. }
  144. pe_data.close_me = fds[0];
  145. pe_data.stdout = fds[1];
  146. pid = run_helper(change_pre_exec, &pe_data, argv, NULL);
  147. read_output(fds[0], output, output_len);
  148. os_close_file(fds[0]);
  149. os_close_file(fds[1]);
  150. if (pid > 0)
  151. CATCH_EINTR(err = waitpid(pid, NULL, 0));
  152. return(pid);
  153. }
  154. static void change(char *dev, char *what, unsigned char *addr,
  155. unsigned char *netmask)
  156. {
  157. char addr_buf[sizeof("255.255.255.255\0")];
  158. char netmask_buf[sizeof("255.255.255.255\0")];
  159. char version[sizeof("nnnnn\0")];
  160. char *argv[] = { "uml_net", version, what, dev, addr_buf,
  161. netmask_buf, NULL };
  162. char *output;
  163. int output_len, pid;
  164. sprintf(version, "%d", UML_NET_VERSION);
  165. sprintf(addr_buf, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
  166. sprintf(netmask_buf, "%d.%d.%d.%d", netmask[0], netmask[1],
  167. netmask[2], netmask[3]);
  168. output_len = page_size();
  169. output = um_kmalloc(output_len);
  170. if(output == NULL)
  171. printk("change : failed to allocate output buffer\n");
  172. pid = change_tramp(argv, output, output_len);
  173. if(pid < 0) return;
  174. if(output != NULL){
  175. printk("%s", output);
  176. kfree(output);
  177. }
  178. }
  179. void open_addr(unsigned char *addr, unsigned char *netmask, void *arg)
  180. {
  181. change(arg, "add", addr, netmask);
  182. }
  183. void close_addr(unsigned char *addr, unsigned char *netmask, void *arg)
  184. {
  185. change(arg, "del", addr, netmask);
  186. }
  187. char *split_if_spec(char *str, ...)
  188. {
  189. char **arg, *end;
  190. va_list ap;
  191. va_start(ap, str);
  192. while((arg = va_arg(ap, char **)) != NULL){
  193. if(*str == '\0')
  194. return(NULL);
  195. end = strchr(str, ',');
  196. if(end != str)
  197. *arg = str;
  198. if(end == NULL)
  199. return(NULL);
  200. *end++ = '\0';
  201. str = end;
  202. }
  203. va_end(ap);
  204. return(str);
  205. }
  206. /*
  207. * Overrides for Emacs so that we follow Linus's tabbing style.
  208. * Emacs will notice this stuff at the end of the file and automatically
  209. * adjust the settings for this buffer only. This must remain at the end
  210. * of the file.
  211. * ---------------------------------------------------------------------------
  212. * Local variables:
  213. * c-file-style: "linux"
  214. * End:
  215. */