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