mod_ip_opt.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /*
  2. * mod_ip_opt.c
  3. *
  4. * Copyright (c) 2001 Dug Song <dugsong@monkey.org>
  5. *
  6. * $Id$
  7. */
  8. #include "config.h"
  9. #include "defines.h"
  10. #include "common.h"
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include "pkt.h"
  15. #include "mod.h"
  16. #include "iputil.h"
  17. void *
  18. ip_opt_close(void *d)
  19. {
  20. if (d != NULL)
  21. free(d);
  22. return (NULL);
  23. }
  24. void *
  25. ip_opt_open(int argc, char *argv[])
  26. {
  27. struct ip_opt *opt;
  28. struct addr addr;
  29. int i, j;
  30. if (argc < 4)
  31. return (NULL);
  32. if ((opt = calloc(1, sizeof(*opt))) == NULL)
  33. return (NULL);
  34. if (strcasecmp(argv[1], "lsrr") == 0) {
  35. opt->opt_type = IP_OPT_LSRR;
  36. } else if (strcasecmp(argv[1], "ssrr") == 0) {
  37. opt->opt_type = IP_OPT_SSRR;
  38. } else if (strcasecmp(argv[1], "raw") == 0) {
  39. if (raw_ip_opt_parse(argc - 2, &argv[2], &opt->opt_type, &opt->opt_len,
  40. &opt->opt_data.data8[0], sizeof(opt->opt_data.data8)) != 0)
  41. return (ip_opt_close(opt));
  42. return opt;
  43. } else
  44. return (ip_opt_close(opt));
  45. if ((i = atoi(argv[2])) < 4 || i > 0xff) {
  46. warn("<ptr> must be >= 4, and should be a multiple of 4");
  47. return (ip_opt_close(opt));
  48. }
  49. opt->opt_data.rr.ptr = i;
  50. for (i = 3, j = 0; i < argc && j < 9; i++, j++) {
  51. if (addr_aton(argv[i], &addr) < 0) {
  52. return (ip_opt_close(opt));
  53. }
  54. opt->opt_data.rr.iplist[j] = addr.addr_ip;
  55. }
  56. opt->opt_len = IP_OPT_LEN + 1 + (IP_ADDR_LEN * j);
  57. return (opt);
  58. }
  59. int
  60. ip_opt_apply(void *d, struct pktq *pktq)
  61. {
  62. struct ip_opt *opt = (struct ip_opt *)d;
  63. struct pkt *pkt;
  64. size_t len;
  65. TAILQ_FOREACH(pkt, pktq, pkt_next) {
  66. uint16_t eth_type = htons(pkt->pkt_eth->eth_type);
  67. if (eth_type == ETH_TYPE_IP) {
  68. len = ip_add_option(pkt->pkt_ip, PKT_BUF_LEN - ETH_HDR_LEN,
  69. IP_PROTO_IP, opt, opt->opt_len);
  70. if (len > 0) {
  71. pkt->pkt_end += len;
  72. pkt_decorate(pkt);
  73. ip_checksum(pkt->pkt_ip,
  74. pkt->pkt_end - pkt->pkt_eth_data);
  75. }
  76. }
  77. }
  78. return (0);
  79. }
  80. struct mod mod_ip_opt = {
  81. "ip_opt", /* name */
  82. "ip_opt [lsrr|ssrr <ptr> <ip-addr> ...] | [raw <byte stream>]", /* usage */
  83. ip_opt_open, /* open */
  84. ip_opt_apply, /* apply */
  85. ip_opt_close /* close */
  86. };