aoecfg.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /*
  2. * aoecfgstr.c - fiddle aoe configuration strings.
  3. * Copyright 2009, 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 = 0;
  115. c->firmware = 0;
  116. c->scnt = 0;
  117. c->vercmd = cmd;
  118. memmove(c->data, cfgstr, cfgstrlen);
  119. c->len = htons(cfgstrlen);
  120. if (write(sfd, c, sizeof *c) == -1) {
  121. perror("send config query");
  122. exit(1);
  123. }
  124. for (;;) {
  125. n = readto(sfd, buf, sizeof buf);
  126. if (n < 0) {
  127. perror("read network");
  128. exit(1);
  129. }
  130. if (n < 60)
  131. continue;
  132. h = (Aoehdr *) buf;
  133. if (ntohs(h->type) != AOE_ETH_PROTO)
  134. continue;
  135. if (ntohs(h->maj) == 0xffff || h->min == 0xff)
  136. continue;
  137. if (shelf != 0xffff && ntohs(h->maj) != shelf)
  138. continue;
  139. if (slot != 0xff && h->min != slot)
  140. continue;
  141. if (memcmp(h->tag, &tag, sizeof h->tag))
  142. continue;
  143. resp((Conf*) buf);
  144. if (shelf != 0xffff && slot != 0xff)
  145. break;
  146. }
  147. }
  148. void
  149. usage(void)
  150. {
  151. fputs("usage: aoecfg "
  152. "[-c cmd] [-s cfgstr] [-t timeout] "
  153. "[shelf slot] [net]\n", stderr);
  154. exit(1);
  155. }
  156. typedef struct{
  157. char *s;
  158. int cmd;
  159. } Tab;
  160. Tab tab[] = {
  161. { "read", Qread, },
  162. { "test", Qtest, },
  163. { "prefix", Qprefix, },
  164. { "set", Qset, },
  165. { "fset", Qfset, },
  166. };
  167. int
  168. xlatecmd(char *s)
  169. {
  170. int i;
  171. for (i = 0; i < nelem(tab); i++)
  172. if (strcmp(tab[i].s, s) == 0)
  173. return tab[i].cmd;
  174. usage();
  175. return -1; // whine whine whine
  176. }
  177. int
  178. main(int argc, char *argv[])
  179. {
  180. int c, cmd;
  181. cmd = Qread;
  182. while ((c = getopt(argc, argv, "s:c:t:v")) != -1) {
  183. switch (c) {
  184. case 'c':
  185. cmd = xlatecmd(optarg);
  186. break;
  187. case 's':
  188. cfgstr = optarg;
  189. cfgstrlen = strlen(cfgstr);
  190. break;
  191. case 't':
  192. timeout = atoi(optarg);
  193. break;
  194. default:
  195. usage();
  196. }
  197. }
  198. c = argc - optind;
  199. argv += optind;
  200. if (c < 2)
  201. goto f1;
  202. if (c != 3 && c != 2)
  203. usage();
  204. shelf = strtoul(*argv++, 0, 0);
  205. slot = strtoul(*argv++, 0, 0);
  206. f1:
  207. if (*argv) {
  208. net = *argv;
  209. if (isdigit((int) *net)) {
  210. fprintf(stderr,
  211. "aoecfg Error: \"%s\" %s\n", net,
  212. "is not a valid network interface");
  213. usage();
  214. }
  215. }
  216. sfd = dial(net);
  217. if (getea(sfd, net, mac) == 0)
  218. exit(1);
  219. cfgquery(cmd, shelf, slot);
  220. return 0;
  221. }