1#!/usr/bin/env python3 2# 3# SPDX-License-Identifier: ISC 4# 5# Copyright (c) 2012-2021 Alexander Bluhm <bluhm@openbsd.org> 6# 7# Permission to use, copy, modify, and distribute this software for any 8# purpose with or without fee is hereby granted, provided that the above 9# copyright notice and this permission notice appear in all copies. 10# 11# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 19from fragcommon import * 20from itertools import chain 21 22# index boundary 4096 | 23# |--------------| 24# .... 25# |--------------| 26# |--------------| 27# ....----| 28# |XXXX-----| 29# |--------------| 30 31# this should trigger "fragment requeue limit exceeded" log in kernel 32 33def send(src, dst, send_if, recv_if): 34 pid = os.getpid() 35 eid = pid & 0xffff 36 payload = b"ABCDEFGHIJKLMNOP" 37 dummy = b"01234567" 38 fragsize = 64 39 boundary = 4096 40 fragnum= int(boundary / fragsize) 41 packet = sp.IP(src=src, dst=dst)/ \ 42 sp.ICMP(type='echo-request', id=eid)/ \ 43 (int((boundary + boundary) / len(payload)) * payload) 44 frag = [] 45 fid = pid & 0xffff 46 for i in chain(range(fragnum - 1), range(fragnum, fragnum + fragnum - 1)): 47 frag.append(sp.IP(src=src, dst=dst, proto=1, id=fid, 48 frag=(i * fragsize) >> 3, flags='MF') / 49 bytes(packet)[20 + i * fragsize:20 + (i + 1) * fragsize]) 50 frag.append(sp.IP(src=src, dst=dst, proto=1, id=fid, 51 frag=(boundary + boundary - fragsize) >> 3) / 52 bytes(packet)[20 + boundary + boundary - fragsize:]) 53 frag.append(sp.IP(src=src, dst=dst, proto=1, id=fid, 54 frag=(boundary - 8) >> 3, flags='MF')/ 55 (dummy + bytes(packet)[20 + boundary:20 + boundary + 8])) 56 frag.append(sp.IP(src=src, dst=dst, proto=1, id=fid, 57 frag=(boundary - fragsize) >> 3, flags='MF') / 58 bytes(packet)[20 + boundary - fragsize:20 + boundary]) 59 eth = [] 60 for f in frag: 61 eth.append(sp.Ether() / f) 62 63 if os.fork() == 0: 64 time.sleep(1) 65 for e in eth: 66 sp.sendp(e, iface=send_if) 67 time.sleep(0.001) 68 os._exit(0) 69 70 ans = sp.sniff(iface=recv_if, timeout=10, filter= 71 "ip and src " + dst + " and dst " + src + " and icmp") 72 for a in ans: 73 if a and a.type == ETH_P_IP and \ 74 a.payload.proto == 1 and \ 75 a.payload.frag == 0 and \ 76 sp.icmptypes[a.payload.payload.type] == 'echo-reply': 77 id = a.payload.payload.id 78 print("id=%#x" % (id)) 79 if id != eid: 80 print("WRONG ECHO REPLY ID") 81 sys.exit(2) 82 print("ECHO REPLY") 83 sys.exit(1) 84 sys.exit(0) 85 86if __name__ == '__main__': 87 main(send) 88