nfnl_osf.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. /*
  2. * Copyright (c) 2005 Evgeniy Polyakov <johnpol@2ka.mxt.ru>
  3. *
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. */
  19. #include <sys/types.h>
  20. #include <sys/socket.h>
  21. #include <sys/poll.h>
  22. #include <sys/time.h>
  23. #include <arpa/inet.h>
  24. #include <ctype.h>
  25. #include <errno.h>
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include <stdarg.h>
  30. #include <time.h>
  31. #include <unistd.h>
  32. #include <netinet/ip.h>
  33. #include <netinet/tcp.h>
  34. #include <linux/connector.h>
  35. #include <linux/types.h>
  36. #include <linux/netlink.h>
  37. #include <linux/rtnetlink.h>
  38. #include <linux/unistd.h>
  39. #include <libnfnetlink/libnfnetlink.h>
  40. #include <linux/netfilter/nfnetlink.h>
  41. #include <linux/netfilter/xt_osf.h>
  42. #define OPTDEL ','
  43. #define OSFPDEL ':'
  44. #define MAXOPTSTRLEN 128
  45. #ifndef NIPQUAD
  46. #define NIPQUAD(addr) \
  47. ((unsigned char *)&addr)[0], \
  48. ((unsigned char *)&addr)[1], \
  49. ((unsigned char *)&addr)[2], \
  50. ((unsigned char *)&addr)[3]
  51. #endif
  52. static struct nfnl_handle *nfnlh;
  53. static struct nfnl_subsys_handle *nfnlssh;
  54. static struct xt_osf_opt IANA_opts[] = {
  55. { .kind = 0, .length = 1,},
  56. { .kind=1, .length=1,},
  57. { .kind=2, .length=4,},
  58. { .kind=3, .length=3,},
  59. { .kind=4, .length=2,},
  60. { .kind=5, .length=1,}, /* SACK length is not defined */
  61. { .kind=6, .length=6,},
  62. { .kind=7, .length=6,},
  63. { .kind=8, .length=10,},
  64. { .kind=9, .length=2,},
  65. { .kind=10, .length=3,},
  66. { .kind=11, .length=1,}, /* CC: Suppose 1 */
  67. { .kind=12, .length=1,}, /* the same */
  68. { .kind=13, .length=1,}, /* and here too */
  69. { .kind=14, .length=3,},
  70. { .kind=15, .length=1,}, /* TCP Alternate Checksum Data. Length is not defined */
  71. { .kind=16, .length=1,},
  72. { .kind=17, .length=1,},
  73. { .kind=18, .length=3,},
  74. { .kind=19, .length=18,},
  75. { .kind=20, .length=1,},
  76. { .kind=21, .length=1,},
  77. { .kind=22, .length=1,},
  78. { .kind=23, .length=1,},
  79. { .kind=24, .length=1,},
  80. { .kind=25, .length=1,},
  81. { .kind=26, .length=1,},
  82. };
  83. static FILE *osf_log_stream;
  84. static void uloga(const char *f, ...)
  85. {
  86. va_list ap;
  87. if (!osf_log_stream)
  88. osf_log_stream = stdout;
  89. va_start(ap, f);
  90. vfprintf(osf_log_stream, f, ap);
  91. va_end(ap);
  92. fflush(osf_log_stream);
  93. }
  94. static void ulog(const char *f, ...)
  95. {
  96. char str[64];
  97. struct tm tm;
  98. struct timeval tv;
  99. va_list ap;
  100. if (!osf_log_stream)
  101. osf_log_stream = stdout;
  102. gettimeofday(&tv, NULL);
  103. localtime_r((time_t *)&tv.tv_sec, &tm);
  104. strftime(str, sizeof(str), "%F %R:%S", &tm);
  105. fprintf(osf_log_stream, "%s.%lu %ld ", str, tv.tv_usec, syscall(__NR_gettid));
  106. va_start(ap, f);
  107. vfprintf(osf_log_stream, f, ap);
  108. va_end(ap);
  109. fflush(osf_log_stream);
  110. }
  111. #define ulog_err(f, a...) uloga(f ": %s [%d].\n", ##a, strerror(errno), errno)
  112. static char *xt_osf_strchr(char *ptr, char c)
  113. {
  114. char *tmp;
  115. tmp = strchr(ptr, c);
  116. if (tmp)
  117. *tmp = '\0';
  118. while (tmp && tmp + 1 && isspace(*(tmp + 1)))
  119. tmp++;
  120. return tmp;
  121. }
  122. static void xt_osf_parse_opt(struct xt_osf_opt *opt, __u16 *optnum, char *obuf, int olen)
  123. {
  124. int i, op;
  125. char *ptr, wc;
  126. unsigned long val;
  127. ptr = &obuf[0];
  128. i = 0;
  129. while (ptr != NULL && i < olen && *ptr != 0) {
  130. val = 0;
  131. op = 0;
  132. wc = OSF_WSS_PLAIN;
  133. switch (obuf[i]) {
  134. case 'N':
  135. op = OSFOPT_NOP;
  136. ptr = xt_osf_strchr(&obuf[i], OPTDEL);
  137. if (ptr) {
  138. *ptr = '\0';
  139. ptr++;
  140. i += (int)(ptr - &obuf[i]);
  141. } else
  142. i++;
  143. break;
  144. case 'S':
  145. op = OSFOPT_SACKP;
  146. ptr = xt_osf_strchr(&obuf[i], OPTDEL);
  147. if (ptr) {
  148. *ptr = '\0';
  149. ptr++;
  150. i += (int)(ptr - &obuf[i]);
  151. } else
  152. i++;
  153. break;
  154. case 'T':
  155. op = OSFOPT_TS;
  156. ptr = xt_osf_strchr(&obuf[i], OPTDEL);
  157. if (ptr) {
  158. *ptr = '\0';
  159. ptr++;
  160. i += (int)(ptr - &obuf[i]);
  161. } else
  162. i++;
  163. break;
  164. case 'W':
  165. op = OSFOPT_WSO;
  166. ptr = xt_osf_strchr(&obuf[i], OPTDEL);
  167. if (ptr) {
  168. switch (obuf[i + 1]) {
  169. case '%':
  170. wc = OSF_WSS_MODULO;
  171. break;
  172. case 'S':
  173. wc = OSF_WSS_MSS;
  174. break;
  175. case 'T':
  176. wc = OSF_WSS_MTU;
  177. break;
  178. default:
  179. wc = OSF_WSS_PLAIN;
  180. break;
  181. }
  182. *ptr = '\0';
  183. ptr++;
  184. if (wc)
  185. val = strtoul(&obuf[i + 2], NULL, 10);
  186. else
  187. val = strtoul(&obuf[i + 1], NULL, 10);
  188. i += (int)(ptr - &obuf[i]);
  189. } else
  190. i++;
  191. break;
  192. case 'M':
  193. op = OSFOPT_MSS;
  194. ptr = xt_osf_strchr(&obuf[i], OPTDEL);
  195. if (ptr) {
  196. if (obuf[i + 1] == '%')
  197. wc = OSF_WSS_MODULO;
  198. *ptr = '\0';
  199. ptr++;
  200. if (wc)
  201. val = strtoul(&obuf[i + 2], NULL, 10);
  202. else
  203. val = strtoul(&obuf[i + 1], NULL, 10);
  204. i += (int)(ptr - &obuf[i]);
  205. } else
  206. i++;
  207. break;
  208. case 'E':
  209. op = OSFOPT_EOL;
  210. ptr = xt_osf_strchr(&obuf[i], OPTDEL);
  211. if (ptr) {
  212. *ptr = '\0';
  213. ptr++;
  214. i += (int)(ptr - &obuf[i]);
  215. } else
  216. i++;
  217. break;
  218. default:
  219. op = OSFOPT_EMPTY;
  220. ptr = xt_osf_strchr(&obuf[i], OPTDEL);
  221. if (ptr) {
  222. ptr++;
  223. i += (int)(ptr - &obuf[i]);
  224. } else
  225. i++;
  226. break;
  227. }
  228. if (op != OSFOPT_EMPTY) {
  229. opt[*optnum].kind = IANA_opts[op].kind;
  230. opt[*optnum].length = IANA_opts[op].length;
  231. opt[*optnum].wc.wc = wc;
  232. opt[*optnum].wc.val = val;
  233. (*optnum)++;
  234. }
  235. }
  236. }
  237. static int osf_load_line(char *buffer, int len, int del)
  238. {
  239. int i, cnt = 0;
  240. char obuf[MAXOPTSTRLEN];
  241. struct xt_osf_user_finger f;
  242. char *pbeg, *pend;
  243. char buf[NFNL_HEADER_LEN + NFA_LENGTH(sizeof(struct xt_osf_user_finger))];
  244. struct nlmsghdr *nmh = (struct nlmsghdr *) buf;
  245. memset(&f, 0, sizeof(struct xt_osf_user_finger));
  246. ulog("Loading '%s'.\n", buffer);
  247. for (i = 0; i < len && buffer[i] != '\0'; ++i) {
  248. if (buffer[i] == ':')
  249. cnt++;
  250. }
  251. if (cnt != 8) {
  252. ulog("Wrong input line '%s': cnt: %d, must be 8, i: %d, must be %d.\n", buffer, cnt, i, len);
  253. return -EINVAL;
  254. }
  255. memset(obuf, 0, sizeof(obuf));
  256. pbeg = buffer;
  257. pend = xt_osf_strchr(pbeg, OSFPDEL);
  258. if (pend) {
  259. *pend = '\0';
  260. if (pbeg[0] == 'S') {
  261. f.wss.wc = OSF_WSS_MSS;
  262. if (pbeg[1] == '%')
  263. f.wss.val = strtoul(&pbeg[2], NULL, 10);
  264. else if (pbeg[1] == '*')
  265. f.wss.val = 0;
  266. else
  267. f.wss.val = strtoul(&pbeg[1], NULL, 10);
  268. } else if (pbeg[0] == 'T') {
  269. f.wss.wc = OSF_WSS_MTU;
  270. if (pbeg[1] == '%')
  271. f.wss.val = strtoul(&pbeg[2], NULL, 10);
  272. else if (pbeg[1] == '*')
  273. f.wss.val = 0;
  274. else
  275. f.wss.val = strtoul(&pbeg[1], NULL, 10);
  276. } else if (pbeg[0] == '%') {
  277. f.wss.wc = OSF_WSS_MODULO;
  278. f.wss.val = strtoul(&pbeg[1], NULL, 10);
  279. } else if (isdigit(pbeg[0])) {
  280. f.wss.wc = OSF_WSS_PLAIN;
  281. f.wss.val = strtoul(&pbeg[0], NULL, 10);
  282. }
  283. pbeg = pend + 1;
  284. }
  285. pend = xt_osf_strchr(pbeg, OSFPDEL);
  286. if (pend) {
  287. *pend = '\0';
  288. f.ttl = strtoul(pbeg, NULL, 10);
  289. pbeg = pend + 1;
  290. }
  291. pend = xt_osf_strchr(pbeg, OSFPDEL);
  292. if (pend) {
  293. *pend = '\0';
  294. f.df = strtoul(pbeg, NULL, 10);
  295. pbeg = pend + 1;
  296. }
  297. pend = xt_osf_strchr(pbeg, OSFPDEL);
  298. if (pend) {
  299. *pend = '\0';
  300. f.ss = strtoul(pbeg, NULL, 10);
  301. pbeg = pend + 1;
  302. }
  303. pend = xt_osf_strchr(pbeg, OSFPDEL);
  304. if (pend) {
  305. *pend = '\0';
  306. cnt = snprintf(obuf, sizeof(obuf), "%s,", pbeg);
  307. pbeg = pend + 1;
  308. }
  309. pend = xt_osf_strchr(pbeg, OSFPDEL);
  310. if (pend) {
  311. *pend = '\0';
  312. if (pbeg[0] == '@' || pbeg[0] == '*')
  313. cnt = snprintf(f.genre, sizeof(f.genre), "%s", pbeg + 1);
  314. else
  315. cnt = snprintf(f.genre, sizeof(f.genre), "%s", pbeg);
  316. pbeg = pend + 1;
  317. }
  318. pend = xt_osf_strchr(pbeg, OSFPDEL);
  319. if (pend) {
  320. *pend = '\0';
  321. cnt = snprintf(f.version, sizeof(f.version), "%s", pbeg);
  322. pbeg = pend + 1;
  323. }
  324. pend = xt_osf_strchr(pbeg, OSFPDEL);
  325. if (pend) {
  326. *pend = '\0';
  327. cnt =
  328. snprintf(f.subtype, sizeof(f.subtype), "%s", pbeg);
  329. pbeg = pend + 1;
  330. }
  331. xt_osf_parse_opt(f.opt, &f.opt_num, obuf, sizeof(obuf));
  332. memset(buf, 0, sizeof(buf));
  333. if (del)
  334. nfnl_fill_hdr(nfnlssh, nmh, 0, AF_UNSPEC, 0, OSF_MSG_REMOVE, NLM_F_REQUEST);
  335. else
  336. nfnl_fill_hdr(nfnlssh, nmh, 0, AF_UNSPEC, 0, OSF_MSG_ADD, NLM_F_REQUEST | NLM_F_CREATE);
  337. nfnl_addattr_l(nmh, sizeof(buf), OSF_ATTR_FINGER, &f, sizeof(struct xt_osf_user_finger));
  338. return nfnl_talk(nfnlh, nmh, 0, 0, NULL, NULL, NULL);
  339. }
  340. static int osf_load_entries(char *path, int del)
  341. {
  342. FILE *inf;
  343. int err = 0;
  344. char buf[1024];
  345. inf = fopen(path, "r");
  346. if (!inf) {
  347. ulog_err("Failed to open file '%s'", path);
  348. return -1;
  349. }
  350. while(fgets(buf, sizeof(buf), inf)) {
  351. int len;
  352. if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r')
  353. continue;
  354. len = strlen(buf) - 1;
  355. if (len <= 0)
  356. continue;
  357. buf[len] = '\0';
  358. err = osf_load_line(buf, len, del);
  359. if (err)
  360. break;
  361. memset(buf, 0, sizeof(buf));
  362. }
  363. fclose(inf);
  364. return err;
  365. }
  366. int main(int argc, char *argv[])
  367. {
  368. int ch, del = 0, err;
  369. char *fingerprints = NULL;
  370. while ((ch = getopt(argc, argv, "f:dh")) != -1) {
  371. switch (ch) {
  372. case 'f':
  373. fingerprints = optarg;
  374. break;
  375. case 'd':
  376. del = 1;
  377. break;
  378. default:
  379. fprintf(stderr,
  380. "Usage: %s -f fingerprints -d <del rules> -h\n",
  381. argv[0]);
  382. return -1;
  383. }
  384. }
  385. if (!fingerprints) {
  386. err = -ENOENT;
  387. goto err_out_exit;
  388. }
  389. nfnlh = nfnl_open();
  390. if (!nfnlh) {
  391. err = -EINVAL;
  392. ulog_err("Failed to create nfnl handler");
  393. goto err_out_exit;
  394. }
  395. #ifndef NFNL_SUBSYS_OSF
  396. #define NFNL_SUBSYS_OSF 5
  397. #endif
  398. nfnlssh = nfnl_subsys_open(nfnlh, NFNL_SUBSYS_OSF, OSF_MSG_MAX, 0);
  399. if (!nfnlssh) {
  400. err = -EINVAL;
  401. ulog_err("Faied to create nfnl subsystem");
  402. goto err_out_close;
  403. }
  404. err = osf_load_entries(fingerprints, del);
  405. if (err)
  406. goto err_out_close_subsys;
  407. nfnl_subsys_close(nfnlssh);
  408. nfnl_close(nfnlh);
  409. return 0;
  410. err_out_close_subsys:
  411. nfnl_subsys_close(nfnlssh);
  412. err_out_close:
  413. nfnl_close(nfnlh);
  414. err_out_exit:
  415. return err;
  416. }