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