aoecfg.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /*
  2. * aoecfgstr.c - fiddle aoe configuration strings.
  3. * Copyright 2007, Erik Quanstrom, Coraid, Inc., Licenced under GPL v2
  4. */
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <stdlib.h>
  8. #include <unistd.h>
  9. #include <stdint.h>
  10. #include <ctype.h>
  11. #include <netinet/in.h>
  12. #include <errno.h>
  13. #include <sys/time.h>
  14. #include <time.h>
  15. #include <arpa/inet.h>
  16. #include "dat.h"
  17. #include "fns.h"
  18. int sfd;
  19. uchar mac[6];
  20. int timeout;
  21. u16 shelf = 0xffff;
  22. uchar slot = 0xff;
  23. char *net = "eth0";
  24. char *cfgstr;
  25. int cfgstrlen;
  26. char *errtab[7] = {
  27. "*GOK*",
  28. "*badcmd*",
  29. "*badarg*",
  30. "*baddev*",
  31. "*badcfg*",
  32. "*badvers*",
  33. "*GOK*",
  34. };
  35. void
  36. resp(Conf *c)
  37. {
  38. Aoehdr *h;
  39. char *s;
  40. int l;
  41. h = (Aoehdr*) c;
  42. if (h->flags & Error) {
  43. s = errtab[h->error & 7];
  44. l = strlen(s);
  45. } else {
  46. s = (char*) c->data;
  47. l = ntohs(c->len);
  48. }
  49. if (shelf != 0xffff && slot != 0xff)
  50. printf("%.*s\n", l, s);
  51. else
  52. printf("%d.%d\t%.*s\n", ntohs(h->maj), h->min, l, s);
  53. }
  54. int
  55. readto(int fd, void *buf, int size)
  56. {
  57. fd_set rfd;
  58. struct timeval tv;
  59. static int to;
  60. if (timeout == 0)
  61. goto f1;
  62. if (to == 0)
  63. to = time(0) + timeout;
  64. FD_ZERO(&rfd);
  65. FD_SET(fd, &rfd);
  66. tv.tv_sec = to - time(0);
  67. tv.tv_usec = 0;
  68. switch (select(fd+1, &rfd, 0, 0, &tv)) {
  69. case -1:
  70. perror("select");
  71. exit(1);
  72. case 0:
  73. exit(0);
  74. }
  75. f1:
  76. return read(fd, buf, size);
  77. }
  78. u32
  79. aoe_tag(void)
  80. {
  81. u32 n;
  82. struct timeval t = { 0, 0 };
  83. /* Tag should be just enough to avoid conflicts with other
  84. * aoeping and aoecfg processes, and should set high bit
  85. * to avoid conflicting with in-kernel AoE.
  86. */
  87. if (gettimeofday(&t, NULL)) {
  88. perror("gettimeofday");
  89. exit(1);
  90. }
  91. n = t.tv_usec | 1UL << 31;
  92. return htonl(n);
  93. }
  94. void
  95. cfgquery(int cmd, int shelf, int slot)
  96. {
  97. int n;
  98. Aoehdr *h;
  99. Conf *c;
  100. uchar buf[1024 + sizeof *h];
  101. u32 tag;
  102. c = (Conf*) buf;
  103. h = (Aoehdr*) c;
  104. memset(h, 0, sizeof *h);
  105. memset(h->dst, 0xff, sizeof h->dst);
  106. memmove(h->src, mac, sizeof h->src);
  107. h->type = htons(AOE_ETH_PROTO);
  108. h->flags = AoEver << 4;
  109. h->maj = htons(shelf);
  110. h->min = slot;
  111. h->cmd = Config;
  112. tag = aoe_tag();
  113. memmove(h->tag, &tag, sizeof h->tag);
  114. c->bufcnt = 3;
  115. c->vercmd = 0x10 | cmd;
  116. memmove(c->data, cfgstr, cfgstrlen);
  117. c->len = htons(cfgstrlen);
  118. if (write(sfd, c, sizeof *c) == -1) {
  119. perror("send config query");
  120. exit(1);
  121. }
  122. for (;;) {
  123. n = readto(sfd, buf, sizeof buf);
  124. if (n < 0) {
  125. perror("read network");
  126. exit(1);
  127. }
  128. if (n < 60)
  129. continue;
  130. h = (Aoehdr *) buf;
  131. if (ntohs(h->type) != AOE_ETH_PROTO)
  132. continue;
  133. if (ntohs(h->maj) == 0xffff || h->min == 0xff)
  134. continue;
  135. if (shelf != 0xffff && ntohs(h->maj) != shelf)
  136. continue;
  137. if (slot != 0xff && h->min != slot)
  138. continue;
  139. if (memcmp(h->tag, &tag, sizeof h->tag))
  140. continue;
  141. resp((Conf*) buf);
  142. if (shelf != 0xffff && slot != 0xff)
  143. break;
  144. }
  145. }
  146. void
  147. usage(void)
  148. {
  149. fputs("usage: aoecfg "
  150. "[-c cmd] [-s cfgstr] [-t timeout] "
  151. "[shelf slot] [net]\n", stderr);
  152. exit(1);
  153. }
  154. typedef struct{
  155. char *s;
  156. int cmd;
  157. } Tab;
  158. Tab tab[] = {
  159. { "read", Qread, },
  160. { "test", Qtest, },
  161. { "prefix", Qprefix, },
  162. { "set", Qset, },
  163. { "fset", Qfset, },
  164. };
  165. int
  166. xlatecmd(char *s)
  167. {
  168. int i;
  169. for (i = 0; i < nelem(tab); i++)
  170. if (strcmp(tab[i].s, s) == 0)
  171. return tab[i].cmd;
  172. usage();
  173. return -1; // whine whine whine
  174. }
  175. int
  176. main(int argc, char *argv[])
  177. {
  178. int c, cmd;
  179. cmd = Qread;
  180. while ((c = getopt(argc, argv, "s:c:t:v")) != -1) {
  181. switch (c) {
  182. case 'c':
  183. cmd = xlatecmd(optarg);
  184. break;
  185. case 's':
  186. cfgstr = optarg;
  187. cfgstrlen = strlen(cfgstr);
  188. break;
  189. case 't':
  190. timeout = atoi(optarg);
  191. break;
  192. default:
  193. usage();
  194. }
  195. }
  196. c = argc - optind;
  197. argv += optind;
  198. if (c < 2)
  199. goto f1;
  200. if (c != 3 && c != 2)
  201. usage();
  202. shelf = strtoul(*argv++, 0, 0);
  203. slot = strtoul(*argv++, 0, 0);
  204. f1:
  205. if (*argv) {
  206. net = *argv;
  207. if (isdigit((int) *net)) {
  208. fprintf(stderr,
  209. "aoecfg Error: \"%s\" %s\n", net,
  210. "is not a valid network interface");
  211. usage();
  212. }
  213. }
  214. sfd = dial(net);
  215. if (getea(sfd, net, mac) == 0)
  216. exit(1);
  217. cfgquery(cmd, shelf, slot);
  218. return 0;
  219. }