xref: /freebsd/tests/sys/netinet/redirect.py (revision d0b2dbfa0ecf2bbc9709efc5e20baf8e4b44bbbf)
134a5582cSAlexander V. Chernikov#!/usr/bin/env python
234a5582cSAlexander V. Chernikov# -
334a5582cSAlexander V. Chernikov# SPDX-License-Identifier: BSD-2-Clause
434a5582cSAlexander V. Chernikov#
534a5582cSAlexander V. Chernikov# Copyright (c) 2020 Alexander V. Chernikov
634a5582cSAlexander V. Chernikov#
734a5582cSAlexander V. Chernikov# Redistribution and use in source and binary forms, with or without
834a5582cSAlexander V. Chernikov# modification, are permitted provided that the following conditions
934a5582cSAlexander V. Chernikov# are met:
1034a5582cSAlexander V. Chernikov# 1. Redistributions of source code must retain the above copyright
1134a5582cSAlexander V. Chernikov#    notice, this list of conditions and the following disclaimer.
1234a5582cSAlexander V. Chernikov# 2. Redistributions in binary form must reproduce the above copyright
1334a5582cSAlexander V. Chernikov#    notice, this list of conditions and the following disclaimer in the
1434a5582cSAlexander V. Chernikov#    documentation and/or other materials provided with the distribution.
1534a5582cSAlexander V. Chernikov#
1634a5582cSAlexander V. Chernikov# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1734a5582cSAlexander V. Chernikov# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1834a5582cSAlexander V. Chernikov# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1934a5582cSAlexander V. Chernikov# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2034a5582cSAlexander V. Chernikov# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2134a5582cSAlexander V. Chernikov# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2234a5582cSAlexander V. Chernikov# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2334a5582cSAlexander V. Chernikov# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2434a5582cSAlexander V. Chernikov# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2534a5582cSAlexander V. Chernikov# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2634a5582cSAlexander V. Chernikov# SUCH DAMAGE.
2734a5582cSAlexander V. Chernikov#
2834a5582cSAlexander V. Chernikov#
2934a5582cSAlexander V. Chernikov
3034a5582cSAlexander V. Chernikovimport argparse
31*d234b011SKristof Provostimport logging
32*d234b011SKristof Provostlogging.getLogger("scapy").setLevel(logging.CRITICAL)
3334a5582cSAlexander V. Chernikovimport scapy.all as sc
3434a5582cSAlexander V. Chernikovimport socket
3534a5582cSAlexander V. Chernikovimport sys
3634a5582cSAlexander V. Chernikovimport fcntl
3734a5582cSAlexander V. Chernikovimport struct
3834a5582cSAlexander V. Chernikov
3934a5582cSAlexander V. Chernikov
4034a5582cSAlexander V. Chernikovdef parse_args():
4134a5582cSAlexander V. Chernikov    parser = argparse.ArgumentParser(description='ICMP redirect generator')
4234a5582cSAlexander V. Chernikov    parser.add_argument('--smac', type=str, required=True,
4334a5582cSAlexander V. Chernikov                        help='eth source mac')
4434a5582cSAlexander V. Chernikov    parser.add_argument('--dmac', type=str, required=True,
4534a5582cSAlexander V. Chernikov                        help='eth dest mac')
4634a5582cSAlexander V. Chernikov    parser.add_argument('--sip', type=str, required=True,
4734a5582cSAlexander V. Chernikov                        help='remote router source ip')
4834a5582cSAlexander V. Chernikov    parser.add_argument('--dip', type=str, required=True,
4934a5582cSAlexander V. Chernikov                        help='local router ip')
5034a5582cSAlexander V. Chernikov    parser.add_argument('--iface', type=str, required=True,
5134a5582cSAlexander V. Chernikov                        help='ifname to send packet to')
5234a5582cSAlexander V. Chernikov    parser.add_argument('--route', type=str, required=True,
5334a5582cSAlexander V. Chernikov                        help='destination IP to redirect')
5434a5582cSAlexander V. Chernikov    parser.add_argument('--gw', type=str, required=True,
5534a5582cSAlexander V. Chernikov                        help='redirect GW')
5634a5582cSAlexander V. Chernikov    return parser.parse_args()
5734a5582cSAlexander V. Chernikov
5834a5582cSAlexander V. Chernikov
5934a5582cSAlexander V. Chernikovdef construct_icmp_redirect(smac, dmac, sip, dip, route_dst, route_gw):
6034a5582cSAlexander V. Chernikov    e = sc.Ether(src=smac, dst=dmac)
6134a5582cSAlexander V. Chernikov    l3 = sc.IP(src=sip, dst=dip)
6234a5582cSAlexander V. Chernikov    icmp = sc.ICMP(type=5, code=1, gw=route_gw)
6334a5582cSAlexander V. Chernikov    orig_ip = sc.IP(src=sip, dst=route_dst)
6434a5582cSAlexander V. Chernikov    return e / l3 / icmp / orig_ip / sc.UDP()
6534a5582cSAlexander V. Chernikov
6634a5582cSAlexander V. Chernikov
6734a5582cSAlexander V. Chernikovdef send_packet(pkt, iface, feedback=False):
6834a5582cSAlexander V. Chernikov    if feedback:
6934a5582cSAlexander V. Chernikov        # Make kernel receive the packet as well
7034a5582cSAlexander V. Chernikov        BIOCFEEDBACK = 0x8004427c
7134a5582cSAlexander V. Chernikov        socket = sc.conf.L2socket(iface=args.iface)
7234a5582cSAlexander V. Chernikov        fcntl.ioctl(socket.ins, BIOCFEEDBACK, struct.pack('I', 1))
7334a5582cSAlexander V. Chernikov        sc.sendp(pkt, socket=socket, verbose=True)
7434a5582cSAlexander V. Chernikov    else:
7534a5582cSAlexander V. Chernikov        sc.sendp(pkt, iface=iface, verbose=False)
7634a5582cSAlexander V. Chernikov
7734a5582cSAlexander V. Chernikov
7834a5582cSAlexander V. Chernikovdef main():
7934a5582cSAlexander V. Chernikov    args = parse_args()
8034a5582cSAlexander V. Chernikov    pkt = construct_icmp_redirect(args.smac, args.dmac, args.sip, args.dip,
8134a5582cSAlexander V. Chernikov                                  args.route, args.gw)
8234a5582cSAlexander V. Chernikov    send_packet(pkt, args.iface)
8334a5582cSAlexander V. Chernikov
8434a5582cSAlexander V. Chernikov
8534a5582cSAlexander V. Chernikovif __name__ == '__main__':
8634a5582cSAlexander V. Chernikov    main()
87