mod_ip6_opt.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /*
  2. * mod_ip6_opt.c
  3. *
  4. * Copyright (c) 2001 Dug Song <dugsong@monkey.org>
  5. *
  6. */
  7. #include "config.h"
  8. #include <err.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include "pkt.h"
  13. #include "mod.h"
  14. #include "iputil.h"
  15. #define MAX_ADDRS 32
  16. #define OPT6_TYPE_ROUTE 1
  17. #define OPT6_TYPE_RAW 2
  18. struct ip6_opt_data_route
  19. {
  20. int segments;
  21. struct addr addr[MAX_ADDRS];
  22. };
  23. struct ip6_opt_data_raw
  24. {
  25. int len;
  26. uint8_t proto;
  27. uint8_t data8[512];
  28. };
  29. struct ip6_opt_data
  30. {
  31. int type;
  32. union
  33. {
  34. struct ip6_opt_data_route route;
  35. struct ip6_opt_data_raw raw;
  36. } u;
  37. };
  38. void *
  39. ip6_opt_close(void *d)
  40. {
  41. if (d != NULL)
  42. free(d);
  43. return (NULL);
  44. }
  45. void *
  46. ip6_opt_open(int argc, char *argv[])
  47. {
  48. struct ip6_opt_data *opt;
  49. if (argc < 4)
  50. return (NULL);
  51. if ((opt = calloc(1, sizeof(*opt))) == NULL)
  52. return (NULL);
  53. if (strcasecmp(argv[1], "route") == 0) {
  54. int i, j;
  55. opt->type = OPT6_TYPE_ROUTE;
  56. if ((opt->u.route.segments = atoi(argv[2])) < 1 ||
  57. opt->u.route.segments > MAX_ADDRS) {
  58. warnx("<segments> must be >= 1");
  59. return (ip6_opt_close(opt));
  60. }
  61. i = 0;
  62. j = 3;
  63. if (opt->u.route.segments + 3 != argc) {
  64. return (ip6_opt_close(opt));
  65. }
  66. for (; j < argc; i++, j++) {
  67. if (addr_aton(argv[j], &opt->u.route.addr[i]) < 0 ||
  68. opt->u.route.addr[i].addr_type != ADDR_TYPE_IP6) {
  69. return (ip6_opt_close(opt));
  70. }
  71. }
  72. } else if (strcasecmp(argv[1], "raw") == 0) {
  73. opt->type = OPT6_TYPE_RAW;
  74. if (raw_ip6_opt_parse(argc - 2, &argv[2],
  75. &opt->u.raw.proto, &opt->u.raw.len,
  76. &opt->u.raw.data8[2], sizeof(opt->u.raw.data8) - 2) != 0)
  77. return (ip6_opt_close(opt));
  78. opt->u.raw.len += 2;
  79. opt->u.raw.data8[0] = 0;
  80. opt->u.raw.data8[1] = opt->u.raw.len / 8;
  81. } else {
  82. return (ip6_opt_close(opt));
  83. }
  84. return (opt);
  85. }
  86. int
  87. ip6_opt_apply(void *d, struct pktq *pktq)
  88. {
  89. struct ip6_opt_data *opt = (struct ip6_opt_data *)d;
  90. struct ip6_ext_hdr* ext;
  91. int offset, len;
  92. struct pkt *pkt;
  93. uint8_t nxt, iph_nxt;
  94. uint8_t* p;
  95. int i;
  96. TAILQ_FOREACH(pkt, pktq, pkt_next) {
  97. uint16_t eth_type = htons(pkt->pkt_eth->eth_type);
  98. if (eth_type != ETH_TYPE_IPV6) {
  99. continue;
  100. }
  101. nxt = pkt->pkt_ip6->ip6_nxt;
  102. ext = (struct ip6_ext_hdr*)(((u_char*)pkt->pkt_ip6) + IP6_HDR_LEN);
  103. if (opt->type == OPT6_TYPE_ROUTE) {
  104. offset = 8 + IP6_ADDR_LEN * opt->u.route.segments;
  105. memmove(((u_char*)ext) + offset, ext, pkt->pkt_end - (u_char*)ext);
  106. pkt->pkt_end += offset;
  107. pkt->pkt_ip_data += offset;
  108. len = (IP6_ADDR_LEN / 8) * opt->u.route.segments;
  109. ext->ext_data.routing.type = 0;
  110. ext->ext_data.routing.segleft = opt->u.route.segments;
  111. ((uint32_t*)ext)[1] = 0; /* reserved */
  112. iph_nxt = IP_PROTO_ROUTING;
  113. p = (uint8_t*)(ext) + 8;
  114. for (i = 0; i < opt->u.route.segments; ++i, p += IP6_ADDR_LEN) {
  115. memcpy(p, opt->u.route.addr[i].addr_data8, IP6_ADDR_LEN);
  116. }
  117. } else if (opt->type == OPT6_TYPE_RAW) {
  118. offset = opt->u.raw.len;
  119. memmove(((u_char*)ext) + offset, ext, pkt->pkt_end - (u_char*)ext);
  120. pkt->pkt_end += offset;
  121. pkt->pkt_ip_data += offset;
  122. iph_nxt = opt->u.raw.proto;
  123. p = (uint8_t*)ext;
  124. memcpy(p, opt->u.raw.data8, opt->u.raw.len);
  125. #if 0
  126. printf("len: %d, data %02x %02x %02x %02x %02x %02x %02x %02x\n",
  127. opt->u.raw.len, opt->u.raw.data8[0], opt->u.raw.data8[1],
  128. opt->u.raw.data8[2], opt->u.raw.data8[3],
  129. opt->u.raw.data8[4], opt->u.raw.data8[5],
  130. opt->u.raw.data8[6], opt->u.raw.data8[7]);
  131. #endif
  132. len = (opt->u.raw.len - 8) / 8;
  133. } else {
  134. continue;
  135. }
  136. ext->ext_nxt = nxt;
  137. ext->ext_len = len;
  138. pkt->pkt_ip6->ip6_nxt = iph_nxt;
  139. pkt->pkt_ip6->ip6_plen = htons(htons(pkt->pkt_ip6->ip6_plen) + offset);
  140. /* XXX: do we need it? */
  141. pkt_decorate(pkt);
  142. /* ip6_checksum(pkt->pkt_ip, pkt->pkt_end - pkt->pkt_eth_data); */
  143. }
  144. return (0);
  145. }
  146. struct mod mod_ip6_opt = {
  147. "ip6_opt", /* name */
  148. "ip6_opt [route <segments> <ip6-addr> ...] | [raw <type> <byte stream>]", /* usage */
  149. ip6_opt_open, /* open */
  150. ip6_opt_apply, /* apply */
  151. ip6_opt_close /* close */
  152. };