#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */
typedef struct TYPE_2__ TYPE_1__;

/* Type definitions */
typedef scalar_t__ uint8_t;
typedef int uint16_t;
struct tcphdr {
  int dummy;
};
struct TYPE_2__ {
  int /*<<< orphan*/ s_addr;
};
struct sockaddr_in {
  TYPE_1__ sin_addr;
};
struct sockaddr {
  int dummy;
};
struct iphdr {
  int ihl;
  int version;
  int ttl;
  void *check;
  void *tot_len;
  int /*<<< orphan*/ daddr;
  int /*<<< orphan*/ saddr;
  scalar_t__ protocol;
  void *frag_off;
  void *id;
  scalar_t__ tos;
};

/* Variables and functions */
#define IPPROTO_TCP 128
int USHRT_MAX;
void *htons(int);
scalar_t__ rand();
void crafter_ip4(char *buffer, struct sockaddr *saddr, struct sockaddr *taddr,
                 uint16_t target_protocol, uint16_t options) {
  struct iphdr *head = (struct iphdr *)buffer;
  (void)options;
  head->ihl = 5;
  head->version = 4;
  head->tos = 0;
  head->id = htons(((uint16_t)rand() % (USHRT_MAX + 1)));
  head->frag_off = htons(0x4000);
  head->ttl = 0x40;
  head->protocol = (uint8_t)target_protocol;
  head->check = htons(0);
  head->saddr = ((struct sockaddr_in *)saddr)->sin_addr.s_addr;
  head->daddr = ((struct sockaddr_in *)taddr)->sin_addr.s_addr;
  switch (target_protocol) {
  case IPPROTO_TCP:
    head->tot_len = htons(sizeof(struct iphdr) + sizeof(struct tcphdr));
    head->check = 0;
    break;
  }
}


x86 assembly (clang, -O0):
<crafter_ip4>:
push   %rbp
mov    %rsp,%rbp
sub    $0x30,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    %ecx,-0x1c(%rbp)
mov    %r8d,-0x20(%rbp)
mov    -0x8(%rbp),%rax
mov    %rax,-0x28(%rbp)
mov    -0x28(%rbp),%rax
movl   $0x5,(%rax)
mov    -0x28(%rbp),%rax
movl   $0x4,0x4(%rax)
mov    -0x28(%rbp),%rax
movq   $0x0,0x40(%rax)
xor    %eax,%eax
mov    %eax,-0x2c(%rbp)
call   1040 <rand@plt>
mov    0x2e73(%rip),%rcx
mov    (%rcx),%ecx
add    $0x1,%ecx
cltd
idiv   %ecx
mov    %edx,%edi
call   1030 <htons@plt>
mov    %rax,%rcx
mov    -0x28(%rbp),%rax
mov    %rcx,0x38(%rax)
mov    $0x4000,%edi
call   1030 <htons@plt>
mov    -0x2c(%rbp),%edi
mov    %rax,%rcx
mov    -0x28(%rbp),%rax
mov    %rcx,0x30(%rax)
mov    -0x28(%rbp),%rax
movl   $0x40,0x8(%rax)
movslq -0x1c(%rbp),%rcx
mov    -0x28(%rbp),%rax
mov    %rcx,0x28(%rax)
call   1030 <htons@plt>
mov    %rax,%rcx
mov    -0x28(%rbp),%rax
mov    %rcx,0x10(%rax)
mov    -0x10(%rbp),%rax
mov    (%rax),%ecx
mov    -0x28(%rbp),%rax
mov    %ecx,0x24(%rax)
mov    -0x18(%rbp),%rax
mov    (%rax),%ecx
mov    -0x28(%rbp),%rax
mov    %ecx,0x20(%rax)
mov    -0x1c(%rbp),%eax
sub    $0x80,%eax
jne    121c <crafter_ip4+0xfc>
jmp    11fb <crafter_ip4+0xdb>
mov    $0x4c,%edi
call   1030 <htons@plt>
mov    %rax,%rcx
mov    -0x28(%rbp),%rax
mov    %rcx,0x18(%rax)
mov    -0x28(%rbp),%rax
movq   $0x0,0x10(%rax)
add    $0x30,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<crafter_ip4>:
push   %rbp
push   %r15
push   %r14
push   %rbx
push   %rax
mov    %ecx,%ebp
mov    %rdx,%r14
mov    %rsi,%r15
mov    %rdi,%rbx
movabs $0x400000005,%rax
mov    %rax,(%rdi)
movq   $0x0,0x40(%rdi)
xor    %eax,%eax
call   1040 <rand@plt>
mov    0x2e93(%rip),%rcx
mov    (%rcx),%ecx
add    $0x1,%ecx
cltd
idiv   %ecx
mov    %edx,%edi
call   1030 <htons@plt>
mov    %rax,0x38(%rbx)
mov    $0x4000,%edi
call   1030 <htons@plt>
mov    %rax,0x30(%rbx)
movl   $0x40,0x8(%rbx)
movslq %ebp,%rbp
mov    %rbp,0x28(%rbx)
xor    %edi,%edi
call   1030 <htons@plt>
mov    %rax,0x10(%rbx)
mov    (%r15),%eax
mov    %eax,0x24(%rbx)
mov    (%r14),%eax
mov    %eax,0x20(%rbx)
cmp    $0x80,%ebp
jne    11b9 <crafter_ip4+0x99>
mov    $0x4c,%edi
call   1030 <htons@plt>
mov    %rax,0x18(%rbx)
movq   $0x0,0x10(%rbx)
add    $0x8,%rsp
pop    %rbx
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
%struct.sockaddr = type { i32 }
%struct.iphdr = type { i32, i32, i32, i8*, i8*, i32, i32, i64, i8*, i8*, i64 }
%struct.sockaddr_in = type { %struct.TYPE_2__ }
%struct.TYPE_2__ = type { i32 }
@USHRT_MAX = global i32 0
define void @crafter_ip4(i8* %0, %struct.sockaddr* %1, %struct.sockaddr* %2, i32 %3, i32 %4) {
%6 = alloca i8*
%7 = alloca %struct.sockaddr*
%8 = alloca %struct.sockaddr*
%9 = alloca i32
%10 = alloca i32
%11 = alloca %struct.iphdr*
store i8* %0, i8** %6
store %struct.sockaddr* %1, %struct.sockaddr** %7
store %struct.sockaddr* %2, %struct.sockaddr** %8
store i32 %3, i32* %9
store i32 %4, i32* %10
%12 = load i8*, i8** %6
%13 = bitcast i8* %12 to %struct.iphdr*
store %struct.iphdr* %13, %struct.iphdr** %11
%14 = load i32, i32* %10
%15 = load %struct.iphdr*, %struct.iphdr** %11
%16 = getelementptr inbounds %struct.iphdr, %struct.iphdr* %15, i32 0, i32 0
store i32 5, i32* %16
%17 = load %struct.iphdr*, %struct.iphdr** %11
%18 = getelementptr inbounds %struct.iphdr, %struct.iphdr* %17, i32 0, i32 1
store i32 4, i32* %18
%19 = load %struct.iphdr*, %struct.iphdr** %11
%20 = getelementptr inbounds %struct.iphdr, %struct.iphdr* %19, i32 0, i32 10
store i64 0, i64* %20
%21 = call i64 (...) @rand()
%22 = trunc i64 %21 to i32
%23 = load i32, i32* @USHRT_MAX
%24 = add nsw i32 %23, 1
%25 = srem i32 %22, %24
%26 = call i8* @htons(i32 %25)
%27 = load %struct.iphdr*, %struct.iphdr** %11
%28 = getelementptr inbounds %struct.iphdr, %struct.iphdr* %27, i32 0, i32 9
store i8* %26, i8** %28
%29 = call i8* @htons(i32 16384)
%30 = load %struct.iphdr*, %struct.iphdr** %11
%31 = getelementptr inbounds %struct.iphdr, %struct.iphdr* %30, i32 0, i32 8
store i8* %29, i8** %31
%32 = load %struct.iphdr*, %struct.iphdr** %11
%33 = getelementptr inbounds %struct.iphdr, %struct.iphdr* %32, i32 0, i32 2
store i32 64, i32* %33
%34 = load i32, i32* %9
%35 = sext i32 %34 to i64
%36 = load %struct.iphdr*, %struct.iphdr** %11
%37 = getelementptr inbounds %struct.iphdr, %struct.iphdr* %36, i32 0, i32 7
store i64 %35, i64* %37
%38 = call i8* @htons(i32 0)
%39 = load %struct.iphdr*, %struct.iphdr** %11
%40 = getelementptr inbounds %struct.iphdr, %struct.iphdr* %39, i32 0, i32 3
store i8* %38, i8** %40
%41 = load %struct.sockaddr*, %struct.sockaddr** %7
%42 = bitcast %struct.sockaddr* %41 to %struct.sockaddr_in*
%43 = getelementptr inbounds %struct.sockaddr_in, %struct.sockaddr_in* %42, i32 0, i32 0
%44 = getelementptr inbounds %struct.TYPE_2__, %struct.TYPE_2__* %43, i32 0, i32 0
%45 = load i32, i32* %44
%46 = load %struct.iphdr*, %struct.iphdr** %11
%47 = getelementptr inbounds %struct.iphdr, %struct.iphdr* %46, i32 0, i32 6
store i32 %45, i32* %47
%48 = load %struct.sockaddr*, %struct.sockaddr** %8
%49 = bitcast %struct.sockaddr* %48 to %struct.sockaddr_in*
%50 = getelementptr inbounds %struct.sockaddr_in, %struct.sockaddr_in* %49, i32 0, i32 0
%51 = getelementptr inbounds %struct.TYPE_2__, %struct.TYPE_2__* %50, i32 0, i32 0
%52 = load i32, i32* %51
%53 = load %struct.iphdr*, %struct.iphdr** %11
%54 = getelementptr inbounds %struct.iphdr, %struct.iphdr* %53, i32 0, i32 5
store i32 %52, i32* %54
%55 = load i32, i32* %9
switch i32 %55, label %62 [
i32 128, label %56
]
56: ; preds = %5
%57 = call i8* @htons(i32 76)
%58 = load %struct.iphdr*, %struct.iphdr** %11
%59 = getelementptr inbounds %struct.iphdr, %struct.iphdr* %58, i32 0, i32 4
store i8* %57, i8** %59
%60 = load %struct.iphdr*, %struct.iphdr** %11
%61 = getelementptr inbounds %struct.iphdr, %struct.iphdr* %60, i32 0, i32 3
store i8* null, i8** %61
br label %62
62: ; preds = %5, %56
ret void
}

LLVM IR (-O2):
%struct.sockaddr = type { i32 }
@USHRT_MAX = global i32 0
define void @crafter_ip4(i8* nocapture writeonly %0, %struct.sockaddr* nocapture %1, %struct.sockaddr* nocapture %2, i32 %3, i32 %4) {
%6 = bitcast i8* %0 to i32*
store i32 5, i32* %6
%7 = getelementptr inbounds i8, i8* %0, i64 4
%8 = bitcast i8* %7 to i32*
store i32 4, i32* %8
%9 = getelementptr inbounds i8, i8* %0, i64 64
%10 = bitcast i8* %9 to i64*
store i64 0, i64* %10
%11 = tail call i64 (...) @rand()
%12 = trunc i64 %11 to i32
%13 = load i32, i32* @USHRT_MAX
%14 = add nsw i32 %13, 1
%15 = srem i32 %12, %14
%16 = tail call i8* @htons(i32 %15)
%17 = getelementptr inbounds i8, i8* %0, i64 56
%18 = bitcast i8* %17 to i8**
store i8* %16, i8** %18
%19 = tail call i8* @htons(i32 16384)
%20 = getelementptr inbounds i8, i8* %0, i64 48
%21 = bitcast i8* %20 to i8**
store i8* %19, i8** %21
%22 = getelementptr inbounds i8, i8* %0, i64 8
%23 = bitcast i8* %22 to i32*
store i32 64, i32* %23
%24 = sext i32 %3 to i64
%25 = getelementptr inbounds i8, i8* %0, i64 40
%26 = bitcast i8* %25 to i64*
store i64 %24, i64* %26
%27 = tail call i8* @htons(i32 0)
%28 = getelementptr inbounds i8, i8* %0, i64 16
%29 = bitcast i8* %28 to i8**
store i8* %27, i8** %29
%30 = getelementptr %struct.sockaddr, %struct.sockaddr* %1, i64 0, i32 0
%31 = load i32, i32* %30
%32 = getelementptr inbounds i8, i8* %0, i64 36
%33 = bitcast i8* %32 to i32*
store i32 %31, i32* %33
%34 = getelementptr %struct.sockaddr, %struct.sockaddr* %2, i64 0, i32 0
%35 = load i32, i32* %34
%36 = getelementptr inbounds i8, i8* %0, i64 32
%37 = bitcast i8* %36 to i32*
store i32 %35, i32* %37
%38 = icmp eq i32 %3, 128
br i1 %38, label %39, label %43
39: ; preds = %5
%40 = tail call i8* @htons(i32 76)
%41 = getelementptr inbounds i8, i8* %0, i64 24
%42 = bitcast i8* %41 to i8**
store i8* %40, i8** %42
store i8* null, i8** %29
br label %43
43: ; preds = %5, %39
ret void
}