utils.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * utils.c
  4. *
  5. * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
  6. *
  7. * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  8. *
  9. * Changes:
  10. *
  11. * Rani Assaf <rani@magic.metawire.com> 980929: resolve addresses
  12. */
  13. #include "libbb.h"
  14. #include <string.h>
  15. #include <unistd.h>
  16. #include "utils.h"
  17. #include "inet_common.h"
  18. int get_integer(int *val, char *arg, int base)
  19. {
  20. long res;
  21. char *ptr;
  22. if (!arg || !*arg)
  23. return -1;
  24. res = strtol(arg, &ptr, base);
  25. if (!ptr || ptr == arg || *ptr || res > INT_MAX || res < INT_MIN)
  26. return -1;
  27. *val = res;
  28. return 0;
  29. }
  30. int get_unsigned(unsigned *val, char *arg, int base)
  31. {
  32. unsigned long res;
  33. char *ptr;
  34. if (!arg || !*arg)
  35. return -1;
  36. res = strtoul(arg, &ptr, base);
  37. if (!ptr || ptr == arg || *ptr || res > UINT_MAX)
  38. return -1;
  39. *val = res;
  40. return 0;
  41. }
  42. int get_u32(uint32_t * val, char *arg, int base)
  43. {
  44. unsigned long res;
  45. char *ptr;
  46. if (!arg || !*arg)
  47. return -1;
  48. res = strtoul(arg, &ptr, base);
  49. if (!ptr || ptr == arg || *ptr || res > 0xFFFFFFFFUL)
  50. return -1;
  51. *val = res;
  52. return 0;
  53. }
  54. int get_u16(uint16_t * val, char *arg, int base)
  55. {
  56. unsigned long res;
  57. char *ptr;
  58. if (!arg || !*arg)
  59. return -1;
  60. res = strtoul(arg, &ptr, base);
  61. if (!ptr || ptr == arg || *ptr || res > 0xFFFF)
  62. return -1;
  63. *val = res;
  64. return 0;
  65. }
  66. int get_u8(uint8_t * val, char *arg, int base)
  67. {
  68. unsigned long res;
  69. char *ptr;
  70. if (!arg || !*arg)
  71. return -1;
  72. res = strtoul(arg, &ptr, base);
  73. if (!ptr || ptr == arg || *ptr || res > 0xFF)
  74. return -1;
  75. *val = res;
  76. return 0;
  77. }
  78. int get_s16(int16_t * val, char *arg, int base)
  79. {
  80. long res;
  81. char *ptr;
  82. if (!arg || !*arg)
  83. return -1;
  84. res = strtol(arg, &ptr, base);
  85. if (!ptr || ptr == arg || *ptr || res > 0x7FFF || res < -0x8000)
  86. return -1;
  87. *val = res;
  88. return 0;
  89. }
  90. int get_s8(int8_t * val, char *arg, int base)
  91. {
  92. long res;
  93. char *ptr;
  94. if (!arg || !*arg)
  95. return -1;
  96. res = strtol(arg, &ptr, base);
  97. if (!ptr || ptr == arg || *ptr || res > 0x7F || res < -0x80)
  98. return -1;
  99. *val = res;
  100. return 0;
  101. }
  102. int get_addr_1(inet_prefix * addr, char *name, int family)
  103. {
  104. char *cp;
  105. unsigned char *ap = (unsigned char *) addr->data;
  106. int i;
  107. memset(addr, 0, sizeof(*addr));
  108. if (strcmp(name, bb_str_default) == 0 ||
  109. strcmp(name, "all") == 0 || strcmp(name, "any") == 0) {
  110. addr->family = family;
  111. addr->bytelen = (family == AF_INET6 ? 16 : 4);
  112. addr->bitlen = -1;
  113. return 0;
  114. }
  115. if (strchr(name, ':')) {
  116. addr->family = AF_INET6;
  117. if (family != AF_UNSPEC && family != AF_INET6)
  118. return -1;
  119. if (inet_pton(AF_INET6, name, addr->data) <= 0)
  120. return -1;
  121. addr->bytelen = 16;
  122. addr->bitlen = -1;
  123. return 0;
  124. }
  125. addr->family = AF_INET;
  126. if (family != AF_UNSPEC && family != AF_INET)
  127. return -1;
  128. addr->bytelen = 4;
  129. addr->bitlen = -1;
  130. for (cp = name, i = 0; *cp; cp++) {
  131. if (*cp <= '9' && *cp >= '0') {
  132. ap[i] = 10 * ap[i] + (*cp - '0');
  133. continue;
  134. }
  135. if (*cp == '.' && ++i <= 3)
  136. continue;
  137. return -1;
  138. }
  139. return 0;
  140. }
  141. int get_prefix_1(inet_prefix * dst, char *arg, int family)
  142. {
  143. int err;
  144. int plen;
  145. char *slash;
  146. memset(dst, 0, sizeof(*dst));
  147. if (strcmp(arg, bb_str_default) == 0 || strcmp(arg, "any") == 0) {
  148. dst->family = family;
  149. dst->bytelen = 0;
  150. dst->bitlen = 0;
  151. return 0;
  152. }
  153. slash = strchr(arg, '/');
  154. if (slash)
  155. *slash = 0;
  156. err = get_addr_1(dst, arg, family);
  157. if (err == 0) {
  158. switch (dst->family) {
  159. case AF_INET6:
  160. dst->bitlen = 128;
  161. break;
  162. default:
  163. case AF_INET:
  164. dst->bitlen = 32;
  165. }
  166. if (slash) {
  167. if (get_integer(&plen, slash + 1, 0) || plen > dst->bitlen) {
  168. err = -1;
  169. goto done;
  170. }
  171. dst->bitlen = plen;
  172. }
  173. }
  174. done:
  175. if (slash)
  176. *slash = '/';
  177. return err;
  178. }
  179. int get_addr(inet_prefix * dst, char *arg, int family)
  180. {
  181. if (family == AF_PACKET) {
  182. bb_error_msg_and_die("\"%s\" may be inet address, but it is not allowed in this context", arg);
  183. }
  184. if (get_addr_1(dst, arg, family)) {
  185. bb_error_msg_and_die("an inet address is expected rather than \"%s\"", arg);
  186. }
  187. return 0;
  188. }
  189. int get_prefix(inet_prefix * dst, char *arg, int family)
  190. {
  191. if (family == AF_PACKET) {
  192. bb_error_msg_and_die("\"%s\" may be inet address, but it is not allowed in this context", arg);
  193. }
  194. if (get_prefix_1(dst, arg, family)) {
  195. bb_error_msg_and_die("an inet address is expected rather than \"%s\"", arg);
  196. }
  197. return 0;
  198. }
  199. uint32_t get_addr32(char *name)
  200. {
  201. inet_prefix addr;
  202. if (get_addr_1(&addr, name, AF_INET)) {
  203. bb_error_msg_and_die("an IP address is expected rather than \"%s\"", name);
  204. }
  205. return addr.data[0];
  206. }
  207. void incomplete_command(void)
  208. {
  209. bb_error_msg("command line is not complete, try option \"help\"");
  210. exit(-1);
  211. }
  212. void invarg(const char * const arg, const char * const opt)
  213. {
  214. bb_error_msg(bb_msg_invalid_arg, arg, opt);
  215. exit(-1);
  216. }
  217. void duparg(char *key, char *arg)
  218. {
  219. bb_error_msg("duplicate \"%s\": \"%s\" is the second value", key, arg);
  220. exit(-1);
  221. }
  222. void duparg2(char *key, char *arg)
  223. {
  224. bb_error_msg("either \"%s\" is duplicate, or \"%s\" is garbage", key, arg);
  225. exit(-1);
  226. }
  227. int matches(char *cmd, char *pattern)
  228. {
  229. int len = strlen(cmd);
  230. return strncmp(pattern, cmd, len);
  231. }
  232. int inet_addr_match(inet_prefix * a, inet_prefix * b, int bits)
  233. {
  234. uint32_t *a1 = a->data;
  235. uint32_t *a2 = b->data;
  236. int words = bits >> 0x05;
  237. bits &= 0x1f;
  238. if (words)
  239. if (memcmp(a1, a2, words << 2))
  240. return -1;
  241. if (bits) {
  242. uint32_t w1, w2;
  243. uint32_t mask;
  244. w1 = a1[words];
  245. w2 = a2[words];
  246. mask = htonl((0xffffffff) << (0x20 - bits));
  247. if ((w1 ^ w2) & mask)
  248. return 1;
  249. }
  250. return 0;
  251. }
  252. const char *rt_addr_n2a(int af, int ATTRIBUTE_UNUSED len,
  253. void *addr, char *buf, int buflen)
  254. {
  255. switch (af) {
  256. case AF_INET:
  257. case AF_INET6:
  258. return inet_ntop(af, addr, buf, buflen);
  259. default:
  260. return "???";
  261. }
  262. }
  263. const char *format_host(int af, int len, void *addr, char *buf, int buflen)
  264. {
  265. #ifdef RESOLVE_HOSTNAMES
  266. if (resolve_hosts) {
  267. struct hostent *h_ent;
  268. if (len <= 0) {
  269. switch (af) {
  270. case AF_INET:
  271. len = 4;
  272. break;
  273. case AF_INET6:
  274. len = 16;
  275. break;
  276. default:;
  277. }
  278. }
  279. if (len > 0 && (h_ent = gethostbyaddr(addr, len, af)) != NULL) {
  280. snprintf(buf, buflen - 1, "%s", h_ent->h_name);
  281. return buf;
  282. }
  283. }
  284. #endif
  285. return rt_addr_n2a(af, len, addr, buf, buflen);
  286. }