Add missing files, update style
This commit is contained in:
@@ -1,35 +1,44 @@
|
||||
{{define "title"}}Hex → pcap{{end}}
|
||||
|
||||
{{define "toolbar-info"}}<span class="toolbar-info">Build a pcap file from hex · <a href="/hex2pcap?example" class="toolbar-link">Load example</a></span>{{end}}
|
||||
|
||||
{{define "content"}}
|
||||
{{with .Data}}
|
||||
<h1>Hex → pcap</h1>
|
||||
<p class="lead">
|
||||
Paste hex for each layer. The fields are decoded and concatenated into one packet.
|
||||
Any field may be empty, so you can also paste a whole packet into a single field.
|
||||
Spaces, newlines, <code>:</code>, <code>-</code>, <code>0x</code> and <code>\x</code> are ignored.
|
||||
<a href="/hex2pcap?example">Load example</a>.
|
||||
</p>
|
||||
|
||||
{{if .Error}}<div class="error" role="alert">{{.Error}}</div>{{end}}
|
||||
|
||||
<form method="post" action="/hex2pcap">
|
||||
<label for="l2">Layer 2 <span class="hint">e.g. Ethernet header</span></label>
|
||||
<textarea id="l2" name="l2" rows="2" spellcheck="false">{{.Form.L2}}</textarea>
|
||||
<section class="widget">
|
||||
<div class="widget-title"><h2>Packet</h2></div>
|
||||
<div class="widget-content">
|
||||
<p class="note">
|
||||
Paste hex for each layer. The fields are decoded and concatenated into one packet.
|
||||
Any field may be empty, so you can also paste a whole packet into a single field.
|
||||
Spaces, newlines, <code>:</code>, <code>-</code>, <code>0x</code> and <code>\x</code> are ignored.
|
||||
</p>
|
||||
|
||||
<label for="l3">Layer 3 <span class="hint">IPv4/IPv6 header with options, optionally followed by the TCP/UDP/ICMP header, or the SCTP header and chunk header(s)</span></label>
|
||||
<textarea id="l3" name="l3" rows="4" spellcheck="false">{{.Form.L3}}</textarea>
|
||||
<label for="l2">Layer 2 <span class="hint">e.g. Ethernet header</span></label>
|
||||
<textarea id="l2" name="l2" rows="2" spellcheck="false">{{.Form.L2}}</textarea>
|
||||
|
||||
<label for="l7">Payload <span class="hint">the rest of the packet, not interpreted</span></label>
|
||||
<textarea id="l7" name="l7" rows="6" spellcheck="false">{{.Form.L7}}</textarea>
|
||||
<label for="l3">Layer 3 <span class="hint">IPv4/IPv6 header with options, optionally followed by the TCP/UDP/ICMP header, or the SCTP header and chunk header(s)</span></label>
|
||||
<textarea id="l3" name="l3" rows="4" spellcheck="false">{{.Form.L3}}</textarea>
|
||||
|
||||
<fieldset>
|
||||
<label for="l7">Payload <span class="hint">the rest of the packet, not interpreted</span></label>
|
||||
<textarea id="l7" name="l7" rows="6" spellcheck="false">{{.Form.L7}}</textarea>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="widget">
|
||||
<div class="widget-title"><h2>Options</h2></div>
|
||||
<div class="widget-content">
|
||||
<label class="check">
|
||||
<input type="checkbox" name="fix"{{if .Form.Fix}} checked{{end}}>
|
||||
Recalculate IP lengths and checksums
|
||||
<span class="hint">IPv4/IPv6 length, IPv4 header checksum, TCP/UDP/ICMP/ICMPv6/SCTP checksum, UDP length.
|
||||
The end of the layer 3 field also sets the TCP data offset and the length of the SCTP chunk the payload belongs to
|
||||
(paste chunk data without padding).</span>
|
||||
</label>
|
||||
<p class="hint field-hint">
|
||||
IPv4/IPv6 length, IPv4 header checksum, TCP/UDP/ICMP/ICMPv6/SCTP checksum, UDP length.
|
||||
The end of the layer 3 field also sets the TCP data offset and the length of the SCTP chunk the payload belongs to
|
||||
(paste chunk data without padding).
|
||||
</p>
|
||||
|
||||
<div class="row">
|
||||
<div>
|
||||
@@ -39,55 +48,59 @@
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label for="customlinktype">Custom link type <span class="hint">when “Custom…” is selected</span></label>
|
||||
<input id="customlinktype" name="customlinktype" inputmode="numeric" value="{{.Form.CustomLinkType}}" placeholder="e.g. 228">
|
||||
<label for="customlinktype">Custom link type</label>
|
||||
<input id="customlinktype" name="customlinktype" inputmode="numeric" value="{{.Form.CustomLinkType}}" placeholder="e.g. 228" aria-describedby="customlinktype-hint">
|
||||
<span id="customlinktype-hint" class="hint field-hint">Used when “Custom…” is selected</span>
|
||||
</div>
|
||||
<div>
|
||||
<label for="filename">File name</label>
|
||||
<input id="filename" name="filename" value="{{.Form.Filename}}" placeholder="packet.pcap">
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<div class="actions">
|
||||
<button type="submit" name="action" value="preview">Preview</button>
|
||||
<button type="submit" name="action" value="download" class="primary">Download pcap</button>
|
||||
<div class="actions">
|
||||
<button type="submit" name="action" value="preview" class="btn">Preview</button>
|
||||
<button type="submit" name="action" value="download" class="btn primary">Download pcap</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</form>
|
||||
|
||||
{{with .Result}}
|
||||
<section class="result">
|
||||
<h2>Preview</h2>
|
||||
<dl class="summary">
|
||||
<dt>Packet length</dt><dd>{{len .Packet}} bytes</dd>
|
||||
<dt>Link type</dt><dd>{{.LinkTypeName}} ({{.LinkType}})</dd>
|
||||
<dt>Layers</dt>
|
||||
<dd>
|
||||
<span class="l2">layer 2: {{.L2Len}}</span> ·
|
||||
<span class="l3">layer 3: {{.L3Len}}</span> ·
|
||||
<span class="l7">payload: {{.L7Len}}</span>
|
||||
</dd>
|
||||
</dl>
|
||||
<section class="widget">
|
||||
<div class="widget-title"><h2>Preview</h2></div>
|
||||
<div class="widget-content">
|
||||
<dl class="summary">
|
||||
<dt>Packet length</dt><dd>{{len .Packet}} bytes</dd>
|
||||
<dt>Link type</dt><dd>{{.LinkTypeName}} ({{.LinkType}})</dd>
|
||||
<dt>Layers</dt>
|
||||
<dd>
|
||||
<span class="l2">layer 2: {{.L2Len}}</span> ·
|
||||
<span class="l3">layer 3: {{.L3Len}}</span> ·
|
||||
<span class="l7">payload: {{.L7Len}}</span>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
{{if .Fixed}}
|
||||
<h3>Fixups <span class="hint">IP header at offset {{.IPOffset}}</span></h3>
|
||||
<table>
|
||||
<thead><tr><th>Field</th><th>Old</th><th>New</th></tr></thead>
|
||||
<tbody>
|
||||
{{range .Fix.Changes}}
|
||||
<tr{{if ne .Old .New}} class="changed"{{end}}><td>{{.Field}}</td><td><code>{{.Old}}</code></td><td><code>{{.New}}</code></td></tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{range .Fix.Notes}}<p class="note">{{.}}</p>{{end}}
|
||||
{{end}}
|
||||
{{if .Fixed}}
|
||||
<h3>Fixups <span class="hint">IP header at offset {{.IPOffset}}</span></h3>
|
||||
<table>
|
||||
<thead><tr><th>Field</th><th>Old</th><th>New</th></tr></thead>
|
||||
<tbody>
|
||||
{{range .Fix.Changes}}
|
||||
<tr{{if ne .Old .New}} class="changed"{{end}}><td>{{.Field}}</td><td><code>{{.Old}}</code></td><td><code>{{.New}}</code></td></tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{range .Fix.Notes}}<p class="note">{{.}}</p>{{end}}
|
||||
{{end}}
|
||||
|
||||
<h3>Hex dump <span class="hint">changed bytes are underlined</span></h3>
|
||||
<pre class="dump">
|
||||
<h3>Hex dump <span class="hint">changed bytes are underlined</span></h3>
|
||||
<pre class="dump">
|
||||
{{- range .Dump -}}
|
||||
<span class="off">{{.Offset}}</span> {{range .Bytes}}<span class="{{.Class}}{{if .Changed}} chg{{end}}">{{.Hex}}</span>{{.Sep}}{{end}} {{.ASCII}}
|
||||
{{end -}}
|
||||
</pre>
|
||||
</div>
|
||||
</section>
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
{{define "title"}}Home{{end}}
|
||||
{{define "title"}}Tools{{end}}
|
||||
|
||||
{{define "toolbar-info"}}<span class="toolbar-info">Small utilities for working with pcap packet captures</span>{{end}}
|
||||
|
||||
{{define "content"}}
|
||||
<h1>pcap tools</h1>
|
||||
<p class="lead">Small utilities for working with pcap packet captures.</p>
|
||||
<ul class="tools">
|
||||
<div class="widget-grid">
|
||||
{{range .Tools}}
|
||||
<li>
|
||||
<a href="{{.Path}}">{{.Name}}</a>
|
||||
<p>{{.Description}}</p>
|
||||
</li>
|
||||
<a href="{{.Path}}" class="widget tool-card">
|
||||
<div class="widget-title"><h2>{{.Name}}</h2></div>
|
||||
<div class="widget-content">{{.Description}}</div>
|
||||
</a>
|
||||
{{end}}
|
||||
</ul>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
@@ -3,17 +3,36 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="color-scheme" content="dark">
|
||||
<title>{{template "title" .}} · pcap tools</title>
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/static/images/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/static/images/favicon-16x16.png">
|
||||
<link rel="stylesheet" href="/static/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<nav>
|
||||
<a href="/" class="brand">pcap tools</a>
|
||||
{{range .Tools}}<a href="{{.Path}}"{{if eq .Path $.Active}} class="active"{{end}}>{{.Name}}</a>{{end}}
|
||||
</nav>
|
||||
<input type="checkbox" id="nav-toggle" class="nav-toggle visually-hidden" aria-label="Toggle navigation">
|
||||
<header class="topbar">
|
||||
<label for="nav-toggle" class="burger" title="Menu">
|
||||
<svg viewBox="0 0 60 50" aria-hidden="true"><rect y="41.8" width="60" height="8.2"/><rect y="20.9" width="60" height="8.2"/><rect width="60" height="8.2"/></svg>
|
||||
</label>
|
||||
<a href="/" class="app-title">pcap tools</a>
|
||||
<a href="/" class="logo-symbol" aria-label="Home">
|
||||
<svg viewBox="0 0 25 25" aria-hidden="true"><path d="m15.3 18.8 1.9 4.2h2.1l-2.5-6.4zM9.9 19.8 7.5 19l.7 4h2z"/><path d="m18.7 8.1-1.2.8L15 7.1l-1.2 1.3L11 7.3l-.5 2.9 2.1 2.3-6.8 1.1.1-2.6-2.1.9.7 1.8-1 9.3h2.1l1.2-5.2 4.8 1.6 2.5 3.6h2.1l-2-4.3 4.4-6.7-.7-1.6.8-.4 1.4 3 1.4-2.8-2.8-2.1zm-3.8 2.2-.8-.5.9-1.4.8.5-.9 1.4zM9.195 2.368l1.042-.354 1.286 3.788-1.042.353zM5.072 3.737l.747-.808 3.892 3.597-.746.808z"/><path d="m4.483 8.179.274-1.065 3.777.97L8.26 9.15z"/></svg>
|
||||
</a>
|
||||
</header>
|
||||
<main>
|
||||
<nav class="sidebar" aria-label="Tools">
|
||||
<div class="nav-section">Tools</div>
|
||||
{{range .Tools}}<a href="{{.Path}}" class="nav-item{{if eq .Path $.Active}} active{{end}}"{{if eq .Path $.Active}} aria-current="page"{{end}}>{{.Name}}</a>
|
||||
{{end}}
|
||||
</nav>
|
||||
<main class="content">
|
||||
<div class="toolbar">
|
||||
<div class="breadcrumb">
|
||||
{{- if ne .Active "/"}}<a href="/" class="toolbar-link">pcap tools</a><span class="title-separator">/</span>{{end -}}
|
||||
<span class="toolbar-title">{{template "title" .}}</span>
|
||||
</div>
|
||||
{{block "toolbar-info" .}}{{end}}
|
||||
</div>
|
||||
{{template "content" .}}
|
||||
</main>
|
||||
</body>
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
{{define "title"}}Reorder pcap{{end}}
|
||||
|
||||
{{define "toolbar-info"}}<span class="toolbar-info">Sort packets by timestamp, like <code>reordercap</code></span>{{end}}
|
||||
|
||||
{{define "content"}}
|
||||
{{with .Data}}
|
||||
{{if .Error}}<div class="error" role="alert">{{.Error}}</div>{{end}}
|
||||
|
||||
<form method="post" action="/reorder" enctype="multipart/form-data">
|
||||
<section class="widget">
|
||||
<div class="widget-title"><h2>Reorder</h2></div>
|
||||
<div class="widget-content">
|
||||
<p class="note">
|
||||
Packets with the same timestamp keep their original order. Packet data and the file header are not changed.
|
||||
</p>
|
||||
|
||||
<label for="file">pcap file <span class="hint">classic pcap, up to {{.MaxUpload}}. Convert pcapng with <code>editcap -F pcap</code></span></label>
|
||||
<input id="file" name="file" type="file" accept=".pcap,.cap,.dmp,application/vnd.tcpdump.pcap" required>
|
||||
|
||||
<p class="note">If the capture ends with a truncated packet, that packet is dropped.</p>
|
||||
|
||||
<div class="actions">
|
||||
<button type="submit" class="btn primary">Reorder and download</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</form>
|
||||
{{end}}
|
||||
{{end}}
|
||||
@@ -1,47 +1,51 @@
|
||||
{{define "title"}}Split pcap{{end}}
|
||||
|
||||
{{define "toolbar-info"}}<span class="toolbar-info">Split a pcap file by packet count or file size</span>{{end}}
|
||||
|
||||
{{define "content"}}
|
||||
{{with .Data}}
|
||||
<h1>Split pcap</h1>
|
||||
<p class="lead">
|
||||
Upload a pcap file and split it into several files by packet count or by file size.
|
||||
The parts are downloaded together as a zip.
|
||||
Packets are copied unchanged, and each part keeps the original file header.
|
||||
</p>
|
||||
|
||||
{{if .Error}}<div class="error" role="alert">{{.Error}}</div>{{end}}
|
||||
|
||||
<form method="post" action="/split" enctype="multipart/form-data">
|
||||
<label for="file">pcap file <span class="hint">classic pcap, up to {{.MaxUpload}}. Convert pcapng with <code>editcap -F pcap</code></span></label>
|
||||
<input id="file" name="file" type="file" accept=".pcap,.cap,.dmp,application/vnd.tcpdump.pcap" required>
|
||||
<section class="widget">
|
||||
<div class="widget-title"><h2>Split</h2></div>
|
||||
<div class="widget-content">
|
||||
<p class="note">
|
||||
The parts are downloaded together as a zip. Packets are copied unchanged, and each part keeps the original file header.
|
||||
</p>
|
||||
|
||||
<fieldset class="modes">
|
||||
<legend>Split by</legend>
|
||||
<label class="check">
|
||||
<input type="radio" name="mode" value="packets"{{if eq .Form.Mode "packets"}} checked{{end}}>
|
||||
At most
|
||||
<input name="packets" class="num" inputmode="numeric" value="{{.Form.Packets}}" aria-label="Packets per file">
|
||||
packets per file
|
||||
</label>
|
||||
<label class="check">
|
||||
<input type="radio" name="mode" value="size"{{if eq .Form.Mode "size"}} checked{{end}}>
|
||||
At most
|
||||
<input name="size" class="num" inputmode="decimal" value="{{.Form.Size}}" aria-label="Size per file">
|
||||
<select name="unit" class="unit" aria-label="Size unit">
|
||||
{{range .Units}}<option{{if eq . $.Data.Form.Unit}} selected{{end}}>{{.}}</option>{{end}}
|
||||
</select>
|
||||
per file
|
||||
<span class="hint">1 MB = 1,000,000 bytes. A packet bigger than this gets a file to itself.</span>
|
||||
</label>
|
||||
</fieldset>
|
||||
<label for="file">pcap file <span class="hint">classic pcap, up to {{.MaxUpload}}. Convert pcapng with <code>editcap -F pcap</code></span></label>
|
||||
<input id="file" name="file" type="file" accept=".pcap,.cap,.dmp,application/vnd.tcpdump.pcap" required>
|
||||
|
||||
<p class="note">
|
||||
At most {{.MaxParts}} output files. If the capture ends with a truncated packet, that packet is dropped.
|
||||
</p>
|
||||
<fieldset class="modes">
|
||||
<legend>Split by</legend>
|
||||
<label class="check">
|
||||
<input type="radio" name="mode" value="packets"{{if eq .Form.Mode "packets"}} checked{{end}}>
|
||||
At most
|
||||
<input name="packets" class="num" inputmode="numeric" value="{{.Form.Packets}}" aria-label="Packets per file">
|
||||
packets per file
|
||||
</label>
|
||||
<label class="check">
|
||||
<input type="radio" name="mode" value="size"{{if eq .Form.Mode "size"}} checked{{end}}>
|
||||
At most
|
||||
<input name="size" class="num" inputmode="decimal" value="{{.Form.Size}}" aria-label="Size per file">
|
||||
<select name="unit" class="unit" aria-label="Size unit">
|
||||
{{range .Units}}<option{{if eq . $.Data.Form.Unit}} selected{{end}}>{{.}}</option>{{end}}
|
||||
</select>
|
||||
per file
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
<div class="actions">
|
||||
<button type="submit" class="primary">Split and download zip</button>
|
||||
<p class="note">
|
||||
1 MB = 1,000,000 bytes. A packet bigger than the size limit gets a file to itself.
|
||||
At most {{.MaxParts}} output files. If the capture ends with a truncated packet, that packet is dropped.
|
||||
</p>
|
||||
|
||||
<div class="actions">
|
||||
<button type="submit" class="btn primary">Split and download zip</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</form>
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
Reference in New Issue
Block a user