/* * mod_ip_opt.c * * Copyright (c) 2001 Dug Song * * $Id$ */ #include "config.h" #include "defines.h" #include "common.h" #include #include #include #include "pkt.h" #include "mod.h" #include "iputil.h" void * ip_opt_close(void *d) { if (d != NULL) free(d); return (NULL); } void * ip_opt_open(int argc, char *argv[]) { struct ip_opt *opt; struct addr addr; int i, j; if (argc < 4) return (NULL); if ((opt = calloc(1, sizeof(*opt))) == NULL) return (NULL); if (strcasecmp(argv[1], "lsrr") == 0) { opt->opt_type = IP_OPT_LSRR; } else if (strcasecmp(argv[1], "ssrr") == 0) { opt->opt_type = IP_OPT_SSRR; } else if (strcasecmp(argv[1], "raw") == 0) { if (raw_ip_opt_parse(argc - 2, &argv[2], &opt->opt_type, &opt->opt_len, &opt->opt_data.data8[0], sizeof(opt->opt_data.data8)) != 0) return (ip_opt_close(opt)); return opt; } else return (ip_opt_close(opt)); if ((i = atoi(argv[2])) < 4 || i > 0xff) { warn(" must be >= 4, and should be a multiple of 4"); return (ip_opt_close(opt)); } opt->opt_data.rr.ptr = i; for (i = 3, j = 0; i < argc && j < 9; i++, j++) { if (addr_aton(argv[i], &addr) < 0) { return (ip_opt_close(opt)); } opt->opt_data.rr.iplist[j] = addr.addr_ip; } opt->opt_len = IP_OPT_LEN + 1 + (IP_ADDR_LEN * j); return (opt); } int ip_opt_apply(void *d, struct pktq *pktq) { struct ip_opt *opt = (struct ip_opt *)d; struct pkt *pkt; size_t len; TAILQ_FOREACH(pkt, pktq, pkt_next) { uint16_t eth_type = htons(pkt->pkt_eth->eth_type); if (eth_type == ETH_TYPE_IP) { len = ip_add_option(pkt->pkt_ip, PKT_BUF_LEN - ETH_HDR_LEN, IP_PROTO_IP, opt, opt->opt_len); if (len > 0) { pkt->pkt_end += len; pkt_decorate(pkt); ip_checksum(pkt->pkt_ip, pkt->pkt_end - pkt->pkt_eth_data); } } } return (0); } struct mod mod_ip_opt = { "ip_opt", /* name */ "ip_opt [lsrr|ssrr ...] | [raw ]", /* usage */ ip_opt_open, /* open */ ip_opt_apply, /* apply */ ip_opt_close /* close */ };