1 /*
2 
3     Construct a TCP packet based upon a template.
4 
5     The (eventual) idea of this module is to make this scanner extensible
6     by providing an arbitrary packet template. Thus, the of this module
7     is to take an existing packet template, parse it, then make
8     appropriate changes.
9 */
10 #include "templ-pkt.h"
11 #include "massip-port.h"
12 #include "proto-preprocess.h"
13 #include "proto-sctp.h"
14 #include "string_s.h"
15 #include "pixie-timer.h"
16 #include "logger.h"
17 #include "templ-payloads.h"
18 #include "syn-cookie.h"
19 #include "unusedparm.h"
20 #include "vulncheck.h"
21 #include "util-checksum.h"
22 #include "util-malloc.h"
23 #include "stub-pcap-dlt.h" /* data link types, like NULL, RAW, or ETHERNET */
24 #include <assert.h>
25 #include <string.h>
26 #include <stdlib.h>
27 
28 static unsigned char default_tcp_template[] =
29     "\0\1\2\3\4\5"  /* Ethernet: destination */
30     "\6\7\x8\x9\xa\xb"  /* Ethernet: source */
31     "\x08\x00"      /* Ethernet type: IPv4 */
32     "\x45"          /* IP type */
33     "\x00"
34     "\x00\x28"      /* total length = 40 bytes */
35     "\x00\x00"      /* identification */
36     "\x00\x00"      /* fragmentation flags */
37     "\xFF\x06"      /* TTL=255, proto=TCP */
38     "\xFF\xFF"      /* checksum */
39     "\0\0\0\0"      /* source address */
40     "\0\0\0\0"      /* destination address */
41 
42     "\0\0"          /* source port */
43     "\0\0"          /* destination port */
44     "\0\0\0\0"      /* sequence number */
45     "\0\0\0\0"      /* ack number */
46     "\x50"          /* header length */
47     "\x02"          /* SYN */
48     "\x04\x0"        /* window fixed to 1024 */
49     "\xFF\xFF"      /* checksum */
50     "\x00\x00"      /* urgent pointer */
51     "\x02\x04\x05\xb4"  /* added options [mss 1460] */
52 ;
53 
54 static unsigned char default_udp_template[] =
55     "\0\1\2\3\4\5"  /* Ethernet: destination */
56     "\6\7\x8\x9\xa\xb"  /* Ethernet: source */
57     "\x08\x00"      /* Ethernet type: IPv4 */
58     "\x45"          /* IP type */
59     "\x00"
60     "\x00\x1c"      /* total length = 28 bytes */
61     "\x00\x00"      /* identification */
62     "\x00\x00"      /* fragmentation flags */
63     "\xFF\x11"      /* TTL=255, proto=UDP */
64     "\xFF\xFF"      /* checksum */
65     "\0\0\0\0"      /* source address */
66     "\0\0\0\0"      /* destination address */
67 
68     "\xfe\xdc"      /* source port */
69     "\x00\x00"      /* destination port */
70     "\x00\x08"      /* length */
71     "\x00\x00"      /* checksum */
72 ;
73 
74 static unsigned char default_sctp_template[] =
75     "\0\1\2\3\4\5"  /* Ethernet: destination */
76     "\6\7\x8\x9\xa\xb"  /* Ethernet: source */
77     "\x08\x00"      /* Ethernet type: IPv4 */
78     "\x45"          /* IP type */
79     "\x00"
80     "\x00\x34"      /* total length = 52 bytes */
81     "\x00\x00"      /* identification */
82     "\x00\x00"      /* fragmentation flags */
83     "\xFF\x84"      /* TTL=255, proto = SCTP */
84     "\x00\x00"      /* checksum */
85     "\0\0\0\0"      /* source address */
86     "\0\0\0\0"      /* destination address */
87 
88     "\x00\x00"          /* source port */
89     "\x00\x00"          /* destination port */
90     "\x00\x00\x00\x00"  /* verification tag */
91     "\x58\xe4\x5d\x36"  /* checksum */
92     "\x01"              /* type = init */
93     "\x00"              /* flags = none */
94     "\x00\x14"          /* length = 20 */
95     "\x9e\x8d\x52\x25"  /* initiate tag */
96     "\x00\x00\x80\x00"  /* receiver window credit */
97     "\x00\x0a"          /* outbound streams = 10 */
98     "\x08\x00"          /* inbound streams = 2048 */
99     "\x46\x1a\xdf\x3d"  /* initial TSN */
100 ;
101 
102 
103 static unsigned char default_icmp_ping_template[] =
104     "\0\1\2\3\4\5"  /* Ethernet: destination */
105     "\6\7\x8\x9\xa\xb"  /* Ethernet: source */
106     "\x08\x00"      /* Ethernet type: IPv4 */
107     "\x45"          /* IP type */
108     "\x00"
109     "\x00\x4c"      /* total length = 76 bytes */
110     "\x00\x00"      /* identification */
111     "\x00\x00"      /* fragmentation flags */
112     "\xFF\x01"      /* TTL=255, proto=ICMP */
113     "\xFF\xFF"      /* checksum */
114     "\0\0\0\0"      /* source address */
115     "\0\0\0\0"      /* destination address */
116 
117     "\x08\x00"      /* Ping Request */
118     "\x00\x00"      /* checksum */
119 
120     "\x00\x00\x00\x00" /* ID, seqno */
121 
122     "\x08\x09\x0a\x0b" /* payload */
123     "\x0c\x0d\x0e\x0f"
124     "\x10\x11\x12\x13"
125     "\x14\x15\x16\x17"
126     "\x18\x19\x1a\x1b"
127     "\x1c\x1d\x1e\x1f"
128     "\x20\x21\x22\x23"
129     "\x24\x25\x26\x27"
130     "\x28\x29\x2a\x2b"
131     "\x2c\x2d\x2e\x2f"
132     "\x30\x31\x32\x33"
133     "\x34\x35\x36\x37"
134 ;
135 
136 static unsigned char default_icmp_timestamp_template[] =
137 "\0\1\2\3\4\5"  /* Ethernet: destination */
138     "\6\7\x8\x9\xa\xb"  /* Ethernet: source */
139 "\x08\x00"      /* Ethernet type: IPv4 */
140 "\x45"          /* IP type */
141 "\x00"
142 "\x00\x28"      /* total length = 84 bytes */
143 "\x00\x00"      /* identification */
144 "\x00\x00"      /* fragmentation flags */
145 "\xFF\x01"      /* TTL=255, proto=UDP */
146 "\xFF\xFF"      /* checksum */
147 "\0\0\0\0"      /* source address */
148 "\0\0\0\0"      /* destination address */
149 
150 "\x0d\x00"  /* timestamp request */
151 "\x00\x00"  /* checksum */
152 "\x00\x00"  /* identifier */
153 "\x00\x00"  /* sequence number */
154 "\x00\x00\x00\x00"
155 "\x00\x00\x00\x00"
156 "\x00\x00\x00\x00"
157 ;
158 
159 
160 static unsigned char default_arp_template[] =
161     "\xff\xff\xff\xff\xff\xff"  /* Ethernet: destination */
162     "\x00\x00\x00\x00\x00\x00"  /* Ethernet: source */
163     "\x08\x06"      /* Ethernet type: ARP */
164     "\x00\x01" /* hardware = Ethernet */
165     "\x08\x00" /* protocol = IPv4 */
166     "\x06\x04" /* MAC length = 6, IPv4 length = 4 */
167     "\x00\x01" /* opcode = request */
168 
169     "\x00\x00\x00\x00\x00\x00"
170     "\x00\x00\x00\x00"
171 
172     "\x00\x00\x00\x00\x00\x00"
173     "\x00\x00\x00\x00"
174 ;
175 
176 
177 /***************************************************************************
178  * Checksum the IP header. This is a "partial" checksum, so we
179  * don't reverse the bits ~.
180  ***************************************************************************/
181 static unsigned
ip_header_checksum(const unsigned char * px,unsigned offset,unsigned max_offset)182 ip_header_checksum(const unsigned char *px, unsigned offset, unsigned max_offset)
183 {
184     unsigned header_length = (px[offset]&0xF) * 4;
185     unsigned xsum = 0;
186     unsigned i;
187 
188     /* restrict check only over packet */
189     if (max_offset > offset + header_length)
190         max_offset = offset + header_length;
191 
192     /* add all the two-byte words together */
193     xsum = 0;
194     for (i = offset; i < max_offset; i += 2) {
195         xsum += px[i]<<8 | px[i+1];
196     }
197 
198     /* if more than 16 bits in result, reduce to 16 bits */
199     xsum = (xsum & 0xFFFF) + (xsum >> 16);
200     xsum = (xsum & 0xFFFF) + (xsum >> 16);
201     xsum = (xsum & 0xFFFF) + (xsum >> 16);
202 
203     return xsum;
204 }
205 
206 /***************************************************************************
207  ***************************************************************************/
208 static unsigned
tcp_checksum2(const unsigned char * px,unsigned offset_ip,unsigned offset_tcp,size_t tcp_length)209 tcp_checksum2(const unsigned char *px, unsigned offset_ip,
210               unsigned offset_tcp, size_t tcp_length)
211 {
212     uint64_t xsum = 0;
213     unsigned i;
214 
215     /* pseudo checksum */
216     xsum = 6;
217     xsum += tcp_length;
218     xsum += px[offset_ip + 12] << 8 | px[offset_ip + 13];
219     xsum += px[offset_ip + 14] << 8 | px[offset_ip + 15];
220     xsum += px[offset_ip + 16] << 8 | px[offset_ip + 17];
221     xsum += px[offset_ip + 18] << 8 | px[offset_ip + 19];
222 
223     /* tcp checksum */
224     for (i=0; i<tcp_length; i += 2) {
225         xsum += px[offset_tcp + i]<<8 | px[offset_tcp + i + 1];
226     }
227 
228     xsum -= (tcp_length & 1) * px[offset_tcp + i - 1]; /* yea I know going off end of packet is bad so sue me */
229     xsum = (xsum & 0xFFFF) + (xsum >> 16);
230     xsum = (xsum & 0xFFFF) + (xsum >> 16);
231     xsum = (xsum & 0xFFFF) + (xsum >> 16);
232 
233     return (unsigned)xsum;
234 }
235 
236 /***************************************************************************
237  ***************************************************************************/
238 /***************************************************************************
239  ***************************************************************************/
240 static unsigned
tcp_ipv4_checksum(struct TemplatePacket * tmpl)241 tcp_ipv4_checksum(struct TemplatePacket *tmpl)
242 {
243     const unsigned char *px = tmpl->ipv4.packet;
244     unsigned offset_ip = tmpl->ipv4.offset_ip;
245     unsigned offset_app = tmpl->ipv4.offset_app;
246     unsigned offset_tcp = tmpl->ipv4.offset_tcp;
247     unsigned xsum = 0;
248     unsigned i;
249 
250 
251 
252     /* pseudo checksum */
253     xsum = 6;
254     xsum += offset_app - offset_tcp;
255     xsum += px[offset_ip + 12] << 8 | px[offset_ip + 13];
256     xsum += px[offset_ip + 14] << 8 | px[offset_ip + 15];
257     xsum += px[offset_ip + 16] << 8 | px[offset_ip + 17];
258     xsum += px[offset_ip + 18] << 8 | px[offset_ip + 19];
259 
260     /* tcp checksum */
261     for (i=offset_tcp; i<offset_app; i += 2) {
262         xsum += px[i]<<8 | px[i+1];
263     }
264     xsum = (xsum & 0xFFFF) + (xsum >> 16);
265     xsum = (xsum & 0xFFFF) + (xsum >> 16);
266     xsum = (xsum & 0xFFFF) + (xsum >> 16);
267 
268     return xsum;
269 }
270 
271 
272 
273 /***************************************************************************
274  ***************************************************************************/
275 unsigned
udp_checksum2(const unsigned char * px,unsigned offset_ip,unsigned offset_tcp,size_t tcp_length)276 udp_checksum2(const unsigned char *px, unsigned offset_ip,
277               unsigned offset_tcp, size_t tcp_length)
278 {
279     uint64_t xsum = 0;
280     unsigned i;
281 
282     /* pseudo checksum */
283     xsum = 17;
284     xsum += tcp_length;
285     xsum += px[offset_ip + 12] << 8 | px[offset_ip + 13];
286     xsum += px[offset_ip + 14] << 8 | px[offset_ip + 15];
287     xsum += px[offset_ip + 16] << 8 | px[offset_ip + 17];
288     xsum += px[offset_ip + 18] << 8 | px[offset_ip + 19];
289 
290     /* tcp checksum */
291     for (i=0; i<tcp_length; i += 2) {
292         xsum += px[offset_tcp + i]<<8 | px[offset_tcp + i + 1];
293     }
294 
295     xsum -= (tcp_length & 1) * px[offset_tcp + i - 1]; /* yea I know going off end of packet is bad so sue me */
296     xsum = (xsum & 0xFFFF) + (xsum >> 16);
297     xsum = (xsum & 0xFFFF) + (xsum >> 16);
298     xsum = (xsum & 0xFFFF) + (xsum >> 16);
299 
300     return (unsigned)xsum;
301 }
302 
303 /***************************************************************************
304  ***************************************************************************/
305 static unsigned
udp_ipv4_checksum(struct TemplatePacket * tmpl)306 udp_ipv4_checksum(struct TemplatePacket *tmpl)
307 {
308     return udp_checksum2(
309                          tmpl->ipv4.packet,
310                          tmpl->ipv4.offset_ip,
311                          tmpl->ipv4.offset_tcp,
312                          tmpl->ipv4.length - tmpl->ipv4.offset_tcp);
313 }
314 
315 /***************************************************************************
316  ***************************************************************************/
317 static unsigned
icmp_checksum2(const unsigned char * px,unsigned offset_icmp,size_t icmp_length)318 icmp_checksum2(const unsigned char *px,
319               unsigned offset_icmp, size_t icmp_length)
320 {
321     uint64_t xsum = 0;
322     unsigned i;
323 
324     for (i=0; i<icmp_length; i += 2) {
325         xsum += px[offset_icmp + i]<<8 | px[offset_icmp + i + 1];
326     }
327 
328     xsum -= (icmp_length & 1) * px[offset_icmp + i - 1]; /* yea I know going off end of packet is bad so sue me */
329     xsum = (xsum & 0xFFFF) + (xsum >> 16);
330     xsum = (xsum & 0xFFFF) + (xsum >> 16);
331     xsum = (xsum & 0xFFFF) + (xsum >> 16);
332 
333     return (unsigned)xsum;
334 }
335 
336 /***************************************************************************
337  ***************************************************************************/
338 static unsigned
icmp_ipv4_checksum(struct TemplatePacket * tmpl)339 icmp_ipv4_checksum(struct TemplatePacket *tmpl)
340 {
341     return icmp_checksum2(
342                          tmpl->ipv4.packet,
343                          tmpl->ipv4.offset_tcp,
344                          tmpl->ipv4.length - tmpl->ipv4.offset_tcp);
345 }
346 
347 
348 /***************************************************************************
349  ***************************************************************************/
templ_copy(const struct TemplateSet * templset)350 struct TemplateSet templ_copy(const struct TemplateSet *templset)
351 {
352     struct TemplateSet result;
353     unsigned i;
354 
355     memcpy(&result, templset, sizeof(result));
356 
357     for (i=0; i<templset->count; i++) {
358         const struct TemplatePacket *p1 = &templset->pkts[i];
359         struct TemplatePacket *p2 = &result.pkts[i];
360         p2->ipv4.packet = MALLOC(p2->ipv4.length);
361         memcpy(p2->ipv4.packet, p1->ipv4.packet, p2->ipv4.length);
362         p2->ipv6.packet = MALLOC(p2->ipv6.length);
363         memcpy(p2->ipv6.packet, p1->ipv6.packet, p2->ipv6.length);
364     }
365 
366     return result;
367 }
368 
369 /***************************************************************************
370  ***************************************************************************/
371 void
tcp_set_window(unsigned char * px,size_t px_length,unsigned window)372 tcp_set_window(unsigned char *px, size_t px_length, unsigned window)
373 {
374     struct PreprocessedInfo parsed;
375     unsigned x;
376     size_t offset;
377     unsigned xsum;
378 
379     /* Parse the frame looking for hte TCP header */
380     x = preprocess_frame(px, (unsigned)px_length, 1 /*enet*/, &parsed);
381     if (!x || parsed.found == FOUND_NOTHING)
382         return;
383     if (parsed.ip_protocol != 6)
384         return;
385     offset = parsed.transport_offset;
386     if (offset + 20 > px_length)
387         return;
388 
389 
390     /* set the new window */
391 #if 0
392     xsum = px[offset + 16] << 8 | px[offset + 17];
393     xsum = (~xsum)&0xFFFF;
394     xsum += window & 0xFFFF;
395     xsum -= px[offset + 14] << 8 | px[offset + 15];
396     xsum = ((xsum)&0xFFFF) + (xsum >> 16);
397     xsum = ((xsum)&0xFFFF) + (xsum >> 16);
398     xsum = ((xsum)&0xFFFF) + (xsum >> 16);
399     xsum = (~xsum)&0xFFFF;
400 #endif
401 
402     px[offset + 14] = (unsigned char)(window>>8);
403     px[offset + 15] = (unsigned char)(window>>0);
404     px[offset + 16] = (unsigned char)(0);
405     px[offset + 17] = (unsigned char)(0);
406 
407 
408     xsum = ~tcp_checksum2(px, parsed.ip_offset, parsed.transport_offset,
409                             parsed.transport_length);
410 
411     px[offset + 16] = (unsigned char)(xsum>>8);
412     px[offset + 17] = (unsigned char)(xsum>>0);
413 }
414 
415 /***************************************************************************
416  ***************************************************************************/
417 size_t
tcp_create_packet(struct TemplatePacket * tmpl,ipaddress ip_them,unsigned port_them,ipaddress ip_me,unsigned port_me,unsigned seqno,unsigned ackno,unsigned flags,const unsigned char * payload,size_t payload_length,unsigned char * px,size_t px_length)418 tcp_create_packet(
419         struct TemplatePacket *tmpl,
420         ipaddress ip_them, unsigned port_them,
421         ipaddress ip_me, unsigned port_me,
422         unsigned seqno, unsigned ackno,
423         unsigned flags,
424         const unsigned char *payload, size_t payload_length,
425         unsigned char *px, size_t px_length)
426 {
427     uint64_t xsum;
428 
429     if (ip_them.version == 4) {
430         unsigned ip_id = ip_them.ipv4 ^ port_them ^ seqno;
431         unsigned offset_ip = tmpl->ipv4.offset_ip;
432         unsigned offset_tcp = tmpl->ipv4. offset_tcp;
433         unsigned offset_payload = offset_tcp + ((tmpl->ipv4.packet[offset_tcp+12]&0xF0)>>2);
434         size_t new_length = offset_payload + payload_length;
435         size_t ip_len = (offset_payload - offset_ip) + payload_length;
436         unsigned old_len;
437 
438         if (new_length > px_length) {
439             fprintf(stderr, "tcp: err generating packet: too much payload\n");
440             return 0;
441         }
442 
443         memcpy(px + 0,              tmpl->ipv4.packet,   tmpl->ipv4.length);
444         memcpy(px + offset_payload, payload,        payload_length);
445         old_len = px[offset_ip+2]<<8 | px[offset_ip+3];
446 
447         /*
448          * Fill in the empty fields in the IP header and then re-calculate
449          * the checksum.
450          */
451         px[offset_ip+2] = (unsigned char)(ip_len>> 8);
452         px[offset_ip+3] = (unsigned char)(ip_len & 0xFF);
453         px[offset_ip+4] = (unsigned char)(ip_id >> 8);
454         px[offset_ip+5] = (unsigned char)(ip_id & 0xFF);
455         px[offset_ip+12] = (unsigned char)((ip_me.ipv4 >> 24) & 0xFF);
456         px[offset_ip+13] = (unsigned char)((ip_me.ipv4 >> 16) & 0xFF);
457         px[offset_ip+14] = (unsigned char)((ip_me.ipv4 >>  8) & 0xFF);
458         px[offset_ip+15] = (unsigned char)((ip_me.ipv4 >>  0) & 0xFF);
459         px[offset_ip+16] = (unsigned char)((ip_them.ipv4 >> 24) & 0xFF);
460         px[offset_ip+17] = (unsigned char)((ip_them.ipv4 >> 16) & 0xFF);
461         px[offset_ip+18] = (unsigned char)((ip_them.ipv4 >>  8) & 0xFF);
462         px[offset_ip+19] = (unsigned char)((ip_them.ipv4 >>  0) & 0xFF);
463 
464         xsum = tmpl->ipv4.checksum_ip;
465         xsum += (ip_id&0xFFFF);
466         xsum += ip_me.ipv4;
467         xsum += ip_them.ipv4;
468         xsum += ip_len - old_len;
469         xsum = (xsum >> 16) + (xsum & 0xFFFF);
470         xsum = (xsum >> 16) + (xsum & 0xFFFF);
471         xsum = ~xsum;
472 
473         px[offset_ip+10] = (unsigned char)(xsum >> 8);
474         px[offset_ip+11] = (unsigned char)(xsum & 0xFF);
475 
476         /*
477          * now do the same for TCP
478          */
479         px[offset_tcp+ 0] = (unsigned char)(port_me >> 8);
480         px[offset_tcp+ 1] = (unsigned char)(port_me & 0xFF);
481         px[offset_tcp+ 2] = (unsigned char)(port_them >> 8);
482         px[offset_tcp+ 3] = (unsigned char)(port_them & 0xFF);
483         px[offset_tcp+ 4] = (unsigned char)(seqno >> 24);
484         px[offset_tcp+ 5] = (unsigned char)(seqno >> 16);
485         px[offset_tcp+ 6] = (unsigned char)(seqno >>  8);
486         px[offset_tcp+ 7] = (unsigned char)(seqno >>  0);
487 
488         px[offset_tcp+ 8] = (unsigned char)(ackno >> 24);
489         px[offset_tcp+ 9] = (unsigned char)(ackno >> 16);
490         px[offset_tcp+10] = (unsigned char)(ackno >>  8);
491         px[offset_tcp+11] = (unsigned char)(ackno >>  0);
492 
493         px[offset_tcp+13] = (unsigned char)flags;
494 
495         px[offset_tcp+14] = (unsigned char)(1200>>8);
496         px[offset_tcp+15] = (unsigned char)(1200 & 0xFF);
497 
498         px[offset_tcp+16] = (unsigned char)(0 >>  8);
499         px[offset_tcp+17] = (unsigned char)(0 >>  0);
500 
501         xsum = tcp_checksum2(px, tmpl->ipv4.offset_ip, tmpl->ipv4.offset_tcp,
502                              new_length - tmpl->ipv4.offset_tcp);
503         xsum = ~xsum;
504 
505         px[offset_tcp+16] = (unsigned char)(xsum >>  8);
506         px[offset_tcp+17] = (unsigned char)(xsum >>  0);
507 
508         if (new_length < 60) {
509             memset(px+new_length, 0, 60-new_length);
510             new_length = 60;
511         }
512         return new_length;
513     } else {
514         unsigned offset_ip = tmpl->ipv6.offset_ip;
515         unsigned offset_tcp = tmpl->ipv6.offset_tcp;
516         unsigned offset_app = tmpl->ipv6.offset_app;
517 
518         /* Make sure the new packet won't exceed buffer size */
519         if (offset_app + payload_length > px_length) {
520             fprintf(stderr, "tcp: err generating packet: too much payload\n");
521             return 0;
522         }
523 
524         /* Copy over everything up to the new application-layer-payload */
525         memcpy(px, tmpl->ipv6.packet, tmpl->ipv6.offset_app);
526 
527         /* Replace the template's application-layer-payload with the new app-payload */
528         memcpy(px + tmpl->ipv6.offset_app, payload, payload_length);
529 
530         /* Fixup the "payload length" field in the IPv6 header. This is everything
531          * after the IPv6 header. There may be additional headers between the IPv6
532          * and TCP headers, so the calculation isn't simply the length of the TCP portion */
533         {
534             size_t len = tmpl->ipv6.offset_app + payload_length - tmpl->ipv6.offset_ip - 40;
535             px[offset_ip + 4] = (unsigned char)(len>>8) & 0xFF;
536             px[offset_ip + 5] = (unsigned char)(len>>0) & 0xFF;
537         }
538 
539         /* Copy over the IP addresses */
540         px[offset_ip+ 8] = (unsigned char)((ip_me.ipv6.hi >> 56ULL) & 0xFF);
541         px[offset_ip+ 9] = (unsigned char)((ip_me.ipv6.hi >> 48ULL) & 0xFF);
542         px[offset_ip+10] = (unsigned char)((ip_me.ipv6.hi >> 40ULL) & 0xFF);
543         px[offset_ip+11] = (unsigned char)((ip_me.ipv6.hi >> 32ULL) & 0xFF);
544         px[offset_ip+12] = (unsigned char)((ip_me.ipv6.hi >> 24ULL) & 0xFF);
545         px[offset_ip+13] = (unsigned char)((ip_me.ipv6.hi >> 16ULL) & 0xFF);
546         px[offset_ip+14] = (unsigned char)((ip_me.ipv6.hi >>  8ULL) & 0xFF);
547         px[offset_ip+15] = (unsigned char)((ip_me.ipv6.hi >>  0ULL) & 0xFF);
548 
549         px[offset_ip+16] = (unsigned char)((ip_me.ipv6.lo >> 56ULL) & 0xFF);
550         px[offset_ip+17] = (unsigned char)((ip_me.ipv6.lo >> 48ULL) & 0xFF);
551         px[offset_ip+18] = (unsigned char)((ip_me.ipv6.lo >> 40ULL) & 0xFF);
552         px[offset_ip+19] = (unsigned char)((ip_me.ipv6.lo >> 32ULL) & 0xFF);
553         px[offset_ip+20] = (unsigned char)((ip_me.ipv6.lo >> 24ULL) & 0xFF);
554         px[offset_ip+21] = (unsigned char)((ip_me.ipv6.lo >> 16ULL) & 0xFF);
555         px[offset_ip+22] = (unsigned char)((ip_me.ipv6.lo >>  8ULL) & 0xFF);
556         px[offset_ip+23] = (unsigned char)((ip_me.ipv6.lo >>  0ULL) & 0xFF);
557 
558         px[offset_ip+24] = (unsigned char)((ip_them.ipv6.hi >> 56ULL) & 0xFF);
559         px[offset_ip+25] = (unsigned char)((ip_them.ipv6.hi >> 48ULL) & 0xFF);
560         px[offset_ip+26] = (unsigned char)((ip_them.ipv6.hi >> 40ULL) & 0xFF);
561         px[offset_ip+27] = (unsigned char)((ip_them.ipv6.hi >> 32ULL) & 0xFF);
562         px[offset_ip+28] = (unsigned char)((ip_them.ipv6.hi >> 24ULL) & 0xFF);
563         px[offset_ip+29] = (unsigned char)((ip_them.ipv6.hi >> 16ULL) & 0xFF);
564         px[offset_ip+30] = (unsigned char)((ip_them.ipv6.hi >>  8ULL) & 0xFF);
565         px[offset_ip+31] = (unsigned char)((ip_them.ipv6.hi >>  0ULL) & 0xFF);
566 
567         px[offset_ip+32] = (unsigned char)((ip_them.ipv6.lo >> 56ULL) & 0xFF);
568         px[offset_ip+33] = (unsigned char)((ip_them.ipv6.lo >> 48ULL) & 0xFF);
569         px[offset_ip+34] = (unsigned char)((ip_them.ipv6.lo >> 40ULL) & 0xFF);
570         px[offset_ip+35] = (unsigned char)((ip_them.ipv6.lo >> 32ULL) & 0xFF);
571         px[offset_ip+36] = (unsigned char)((ip_them.ipv6.lo >> 24ULL) & 0xFF);
572         px[offset_ip+37] = (unsigned char)((ip_them.ipv6.lo >> 16ULL) & 0xFF);
573         px[offset_ip+38] = (unsigned char)((ip_them.ipv6.lo >>  8ULL) & 0xFF);
574         px[offset_ip+39] = (unsigned char)((ip_them.ipv6.lo >>  0ULL) & 0xFF);
575 
576 
577         /*
578          * now do the same for TCP
579          */
580         px[offset_tcp+ 0] = (unsigned char)(port_me >> 8);
581         px[offset_tcp+ 1] = (unsigned char)(port_me & 0xFF);
582         px[offset_tcp+ 2] = (unsigned char)(port_them >> 8);
583         px[offset_tcp+ 3] = (unsigned char)(port_them & 0xFF);
584         px[offset_tcp+ 4] = (unsigned char)(seqno >> 24);
585         px[offset_tcp+ 5] = (unsigned char)(seqno >> 16);
586         px[offset_tcp+ 6] = (unsigned char)(seqno >>  8);
587         px[offset_tcp+ 7] = (unsigned char)(seqno >>  0);
588 
589         px[offset_tcp+ 8] = (unsigned char)(ackno >> 24);
590         px[offset_tcp+ 9] = (unsigned char)(ackno >> 16);
591         px[offset_tcp+10] = (unsigned char)(ackno >>  8);
592         px[offset_tcp+11] = (unsigned char)(ackno >>  0);
593 
594         px[offset_tcp+13] = (unsigned char)flags;
595 
596         px[offset_tcp+14] = (unsigned char)(1200>>8);
597         px[offset_tcp+15] = (unsigned char)(1200 & 0xFF);
598 
599         px[offset_tcp+16] = (unsigned char)(0 >>  8);
600         px[offset_tcp+17] = (unsigned char)(0 >>  0);
601 
602         xsum = checksum_ipv6(px + offset_ip + 8, px + offset_ip + 24, 6, (offset_app - offset_tcp) + payload_length, px + offset_tcp);
603         px[offset_tcp+16] = (unsigned char)(xsum >>  8);
604         px[offset_tcp+17] = (unsigned char)(xsum >>  0);
605 
606         px[offset_tcp+16] = (unsigned char)(xsum >>  8);
607         px[offset_tcp+17] = (unsigned char)(xsum >>  0);
608 
609         return offset_app + payload_length;
610     }
611 }
612 
613 /***************************************************************************
614  ***************************************************************************/
615 static void
udp_payload_fixup(struct TemplatePacket * tmpl,unsigned port,unsigned seqno)616 udp_payload_fixup(struct TemplatePacket *tmpl, unsigned port, unsigned seqno)
617 {
618     const unsigned char *px2 = 0;
619     unsigned length2 = 0;
620     unsigned source_port2 = 0x1000;
621     uint64_t xsum2 = 0;
622     //unsigned char *px = tmpl->packet;
623     SET_COOKIE set_cookie = 0;
624 
625     UNUSEDPARM(seqno);
626 
627     payloads_udp_lookup(tmpl->payloads,
628                     port,
629                     &px2,
630                     &length2,
631                     &source_port2,
632                     &xsum2,
633                     &set_cookie);
634 
635     /* Copy over the payloads */
636     memcpy( tmpl->ipv4.packet + tmpl->ipv4.offset_app,
637             px2,
638             length2);
639     memcpy( tmpl->ipv6.packet + tmpl->ipv6.offset_app,
640             px2,
641             length2);
642 
643     /* Change the cookie values */
644     if (set_cookie) {
645         set_cookie(
646                         tmpl->ipv4.packet + tmpl->ipv4.offset_app,
647                         length2,
648                         seqno);
649         set_cookie(
650                         tmpl->ipv6.packet + tmpl->ipv6.offset_app,
651                         length2,
652                         seqno);
653     }
654 
655     tmpl->ipv4.length = tmpl->ipv4.offset_app + length2;
656     tmpl->ipv6.length = tmpl->ipv6.offset_app + length2;
657 }
658 
659 void
template_set_target_ipv6(struct TemplateSet * tmplset,ipv6address ip_them,unsigned port_them,ipv6address ip_me,unsigned port_me,unsigned seqno,unsigned char * px,size_t sizeof_px,size_t * r_length)660 template_set_target_ipv6(
661     struct TemplateSet *tmplset,
662     ipv6address ip_them, unsigned port_them,
663     ipv6address ip_me, unsigned port_me,
664     unsigned seqno,
665     unsigned char *px, size_t sizeof_px, size_t *r_length
666     )
667 {
668     unsigned offset_ip;
669     unsigned offset_tcp;
670     uint64_t xsum;
671     struct TemplatePacket *tmpl = NULL;
672     uint64_t entropy = tmplset->entropy;
673     unsigned payload_length;
674 
675     *r_length = sizeof_px;
676 
677     /*
678      * Find out which packet template to use. This is because we can
679      * simultaneously scan for both TCP and UDP (and others). We've
680      * just overloaded the "port" field to signal which protocol we
681      * are using
682      */
683     if (port_them < Templ_TCP + 65536)
684         tmpl = &tmplset->pkts[Proto_TCP];
685     else if (port_them < Templ_UDP + 65536) {
686         tmpl = &tmplset->pkts[Proto_UDP];
687         port_them &= 0xFFFF;
688         udp_payload_fixup(tmpl, port_them, seqno);
689     } else if (port_them < Templ_SCTP + 65536) {
690         tmpl = &tmplset->pkts[Proto_SCTP];
691         port_them &= 0xFFFF;
692     } else if (port_them == Templ_ICMP_echo) {
693         tmpl = &tmplset->pkts[Proto_ICMP_ping];
694     } else if (port_them == Templ_ICMP_timestamp) {
695         tmpl = &tmplset->pkts[Proto_ICMP_timestamp];
696     } else if (port_them == Templ_ARP) {
697         tmpl = &tmplset->pkts[Proto_ARP];
698         if (*r_length > tmpl->ipv6.length)
699             *r_length = tmpl->ipv6.length;
700         memcpy(px, tmpl->ipv6.packet, *r_length);
701         return;
702     } else if (port_them == Templ_VulnCheck) {
703         tmpl = &tmplset->pkts[Proto_VulnCheck];
704         port_them &= 0xFFFF;
705     } else {
706         return;
707     }
708 
709     /* Create some shorter local variables to work with */
710     if (*r_length > tmpl->ipv6.length)
711         *r_length = tmpl->ipv6.length;
712     memcpy(px, tmpl->ipv6.packet, *r_length);
713     offset_ip = tmpl->ipv6.offset_ip;
714     offset_tcp = tmpl->ipv6.offset_tcp;
715     //ip_id = ip_them ^ port_them ^ seqno;
716 
717 /*
718 
719    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
720    |Version| Traffic Class |           Flow Label                  |
721    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
722    |         Payload Length        |  Next Header  |   Hop Limit   |
723    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
724    |                                                               |
725    +                                                               +
726    |                                                               |
727    +                         Source Address                        +
728    |                                                               |
729    +                                                               +
730    |                                                               |
731    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
732    |                                                               |
733    +                                                               +
734    |                                                               |
735    +                      Destination Address                      +
736    |                                                               |
737    +                                                               +
738    |                                                               |
739    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
740 */
741     /*
742      * Fill in the empty fields in the IP header and then re-calculate
743      * the checksum.
744      */
745     payload_length = tmpl->ipv6.length - tmpl->ipv6.offset_ip - 40;
746     px[offset_ip+4] = (unsigned char)(payload_length>>8);
747     px[offset_ip+5] = (unsigned char)(payload_length>>0);
748     px[offset_ip+ 8] = (unsigned char)((ip_me.hi >> 56ULL) & 0xFF);
749     px[offset_ip+ 9] = (unsigned char)((ip_me.hi >> 48ULL) & 0xFF);
750     px[offset_ip+10] = (unsigned char)((ip_me.hi >> 40ULL) & 0xFF);
751     px[offset_ip+11] = (unsigned char)((ip_me.hi >> 32ULL) & 0xFF);
752     px[offset_ip+12] = (unsigned char)((ip_me.hi >> 24ULL) & 0xFF);
753     px[offset_ip+13] = (unsigned char)((ip_me.hi >> 16ULL) & 0xFF);
754     px[offset_ip+14] = (unsigned char)((ip_me.hi >>  8ULL) & 0xFF);
755     px[offset_ip+15] = (unsigned char)((ip_me.hi >>  0ULL) & 0xFF);
756 
757     px[offset_ip+16] = (unsigned char)((ip_me.lo >> 56ULL) & 0xFF);
758     px[offset_ip+17] = (unsigned char)((ip_me.lo >> 48ULL) & 0xFF);
759     px[offset_ip+18] = (unsigned char)((ip_me.lo >> 40ULL) & 0xFF);
760     px[offset_ip+19] = (unsigned char)((ip_me.lo >> 32ULL) & 0xFF);
761     px[offset_ip+20] = (unsigned char)((ip_me.lo >> 24ULL) & 0xFF);
762     px[offset_ip+21] = (unsigned char)((ip_me.lo >> 16ULL) & 0xFF);
763     px[offset_ip+22] = (unsigned char)((ip_me.lo >>  8ULL) & 0xFF);
764     px[offset_ip+23] = (unsigned char)((ip_me.lo >>  0ULL) & 0xFF);
765 
766     px[offset_ip+24] = (unsigned char)((ip_them.hi >> 56ULL) & 0xFF);
767     px[offset_ip+25] = (unsigned char)((ip_them.hi >> 48ULL) & 0xFF);
768     px[offset_ip+26] = (unsigned char)((ip_them.hi >> 40ULL) & 0xFF);
769     px[offset_ip+27] = (unsigned char)((ip_them.hi >> 32ULL) & 0xFF);
770     px[offset_ip+28] = (unsigned char)((ip_them.hi >> 24ULL) & 0xFF);
771     px[offset_ip+29] = (unsigned char)((ip_them.hi >> 16ULL) & 0xFF);
772     px[offset_ip+30] = (unsigned char)((ip_them.hi >>  8ULL) & 0xFF);
773     px[offset_ip+31] = (unsigned char)((ip_them.hi >>  0ULL) & 0xFF);
774 
775     px[offset_ip+32] = (unsigned char)((ip_them.lo >> 56ULL) & 0xFF);
776     px[offset_ip+33] = (unsigned char)((ip_them.lo >> 48ULL) & 0xFF);
777     px[offset_ip+34] = (unsigned char)((ip_them.lo >> 40ULL) & 0xFF);
778     px[offset_ip+35] = (unsigned char)((ip_them.lo >> 32ULL) & 0xFF);
779     px[offset_ip+36] = (unsigned char)((ip_them.lo >> 24ULL) & 0xFF);
780     px[offset_ip+37] = (unsigned char)((ip_them.lo >> 16ULL) & 0xFF);
781     px[offset_ip+38] = (unsigned char)((ip_them.lo >>  8ULL) & 0xFF);
782     px[offset_ip+39] = (unsigned char)((ip_them.lo >>  0ULL) & 0xFF);
783 
784     /*
785      * Now do the checksum for the higher layer protocols
786      */
787     switch (tmpl->proto) {
788     case Proto_TCP:
789         px[offset_tcp+ 0] = (unsigned char)(port_me >> 8);
790         px[offset_tcp+ 1] = (unsigned char)(port_me & 0xFF);
791         px[offset_tcp+ 2] = (unsigned char)(port_them >> 8);
792         px[offset_tcp+ 3] = (unsigned char)(port_them & 0xFF);
793         px[offset_tcp+ 4] = (unsigned char)(seqno >> 24);
794         px[offset_tcp+ 5] = (unsigned char)(seqno >> 16);
795         px[offset_tcp+ 6] = (unsigned char)(seqno >>  8);
796         px[offset_tcp+ 7] = (unsigned char)(seqno >>  0);
797 
798         xsum = checksum_ipv6(px + offset_ip + 8, px + offset_ip + 24, 6,  tmpl->ipv6.length - offset_tcp, px + offset_tcp);
799         px[offset_tcp+16] = (unsigned char)(xsum >>  8);
800         px[offset_tcp+17] = (unsigned char)(xsum >>  0);
801         break;
802     case Proto_UDP:
803             /* TODO: IPv6 */
804         px[offset_tcp+ 0] = (unsigned char)(port_me >> 8);
805         px[offset_tcp+ 1] = (unsigned char)(port_me & 0xFF);
806         px[offset_tcp+ 2] = (unsigned char)(port_them >> 8);
807         px[offset_tcp+ 3] = (unsigned char)(port_them & 0xFF);
808         px[offset_tcp+ 4] = (unsigned char)((tmpl->ipv6.length - tmpl->ipv6.offset_app + 8)>>8);
809         px[offset_tcp+ 5] = (unsigned char)((tmpl->ipv6.length - tmpl->ipv6.offset_app + 8)&0xFF);
810 
811         px[offset_tcp+6] = (unsigned char)(0);
812         px[offset_tcp+7] = (unsigned char)(0);
813         xsum = checksum_ipv6(px + offset_ip + 8, px + offset_ip + 24, 17,  tmpl->ipv6.length - offset_tcp, px + offset_tcp);
814         px[offset_tcp+6] = (unsigned char)(xsum >>  8);
815         px[offset_tcp+7] = (unsigned char)(xsum >>  0);
816         break;
817     case Proto_SCTP:
818             /* TODO: IPv6 */
819         px[offset_tcp+ 0] = (unsigned char)(port_me >> 8);
820         px[offset_tcp+ 1] = (unsigned char)(port_me & 0xFF);
821         px[offset_tcp+ 2] = (unsigned char)(port_them >> 8);
822         px[offset_tcp+ 3] = (unsigned char)(port_them & 0xFF);
823 
824         px[offset_tcp+16] = (unsigned char)(seqno >> 24);
825         px[offset_tcp+17] = (unsigned char)(seqno >> 16);
826         px[offset_tcp+18] = (unsigned char)(seqno >>  8);
827         px[offset_tcp+19] = (unsigned char)(seqno >>  0);
828 
829         xsum = sctp_checksum(px + offset_tcp, tmpl->ipv6.length - offset_tcp);
830         px[offset_tcp+ 8] = (unsigned char)(xsum >>  24);
831         px[offset_tcp+ 9] = (unsigned char)(xsum >>  16);
832         px[offset_tcp+10] = (unsigned char)(xsum >>   8);
833         px[offset_tcp+11] = (unsigned char)(xsum >>   0);
834         break;
835     case Proto_ICMP_ping:
836     case Proto_ICMP_timestamp:
837             /* TODO: IPv6 */
838             seqno = (unsigned)syn_cookie_ipv6(ip_them, port_them, ip_me, 0, entropy);
839             px[offset_tcp+ 4] = (unsigned char)(seqno >> 24);
840             px[offset_tcp+ 5] = (unsigned char)(seqno >> 16);
841             px[offset_tcp+ 6] = (unsigned char)(seqno >>  8);
842             px[offset_tcp+ 7] = (unsigned char)(seqno >>  0);
843             xsum = checksum_ipv6(px + offset_ip + 8, px + offset_ip + 24, 58,  tmpl->ipv6.length - offset_tcp, px + offset_tcp);
844             px[offset_tcp+2] = (unsigned char)(xsum >>  8);
845             px[offset_tcp+3] = (unsigned char)(xsum >>  0);
846         break;
847     case Proto_VulnCheck:
848             /* TODO: IPv6 */
849             /*tmplset->vulncheck->set_target(tmpl,
850                                      ip_them, port_them,
851                                      ip_me, port_me,
852                                      seqno,
853                                      px, sizeof_px, r_length);*/
854             break;
855     case Proto_ARP:
856             /* TODO: IPv6 */
857         /* don't do any checksumming */
858         break;
859     case Proto_Oproto:
860             /* TODO: IPv6 */
861         /* TODO: probably need to add checksums for certain protocols */
862         break;
863     case Proto_Count:
864         break;
865     }
866 }
867 
868 
869 /***************************************************************************
870  * This is the function that formats the transmitted packets for probing
871  * machines. It takes a template for the protocol (usually a TCP SYN
872  * packet), then sets the destination IP address and port numbers.
873  ***************************************************************************/
874 void
template_set_target_ipv4(struct TemplateSet * tmplset,ipv4address ip_them,unsigned port_them,ipv4address ip_me,unsigned port_me,unsigned seqno,unsigned char * px,size_t sizeof_px,size_t * r_length)875 template_set_target_ipv4(
876     struct TemplateSet *tmplset,
877     ipv4address ip_them, unsigned port_them,
878     ipv4address ip_me, unsigned port_me,
879     unsigned seqno,
880     unsigned char *px, size_t sizeof_px, size_t *r_length
881     )
882 {
883     unsigned offset_ip;
884     unsigned offset_tcp;
885     uint64_t xsum;
886     unsigned ip_id;
887     struct TemplatePacket *tmpl = NULL;
888     unsigned xsum2;
889     uint64_t entropy = tmplset->entropy;
890 
891     *r_length = sizeof_px;
892 
893     /*
894      * Find out which packet template to use. This is because we can
895      * simultaneously scan for both TCP and UDP (and others). We've
896      * just overloaded the "port" field to signal which protocol we
897      * are using
898      */
899     if (port_them < Templ_TCP + 65536)
900         tmpl = &tmplset->pkts[Proto_TCP];
901     else if (port_them < Templ_UDP + 65536) {
902         tmpl = &tmplset->pkts[Proto_UDP];
903         port_them &= 0xFFFF;
904         udp_payload_fixup(tmpl, port_them, seqno);
905     } else if (port_them < Templ_SCTP + 65536) {
906         tmpl = &tmplset->pkts[Proto_SCTP];
907         port_them &= 0xFFFF;
908     } else if (port_them == Templ_ICMP_echo) {
909         tmpl = &tmplset->pkts[Proto_ICMP_ping];
910     } else if (port_them == Templ_ICMP_timestamp) {
911         tmpl = &tmplset->pkts[Proto_ICMP_timestamp];
912     } else if (port_them == Templ_ARP) {
913         tmpl = &tmplset->pkts[Proto_ARP];
914         if (*r_length > tmpl->ipv4.length)
915             *r_length = tmpl->ipv4.length;
916         memcpy(px, tmpl->ipv4.packet, *r_length);
917         px = px + tmpl->ipv4.offset_ip;
918         px[14] = (unsigned char)((ip_me >> 24) & 0xFF);
919         px[15] = (unsigned char)((ip_me >> 16) & 0xFF);
920         px[16] = (unsigned char)((ip_me >>  8) & 0xFF);
921         px[17] = (unsigned char)((ip_me >>  0) & 0xFF);
922         px[24] = (unsigned char)((ip_them >> 24) & 0xFF);
923         px[25] = (unsigned char)((ip_them >> 16) & 0xFF);
924         px[26] = (unsigned char)((ip_them >>  8) & 0xFF);
925         px[27] = (unsigned char)((ip_them >>  0) & 0xFF);
926         return;
927     } else if (port_them == Templ_VulnCheck) {
928         tmpl = &tmplset->pkts[Proto_VulnCheck];
929         port_them &= 0xFFFF;
930     } else {
931         return;
932     }
933 
934     /* Create some shorter local variables to work with */
935     if (*r_length > tmpl->ipv4.length)
936         *r_length = tmpl->ipv4.length;
937     memcpy(px, tmpl->ipv4.packet, *r_length);
938     offset_ip = tmpl->ipv4.offset_ip;
939     offset_tcp = tmpl->ipv4.offset_tcp;
940     ip_id = ip_them ^ port_them ^ seqno;
941 
942     /*
943 
944     0                   1                   2                   3
945     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
946    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
947    |Version|  IHL  |Type of Service|          Total Length         |
948    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
949    |         Identification        |Flags|      Fragment Offset    |
950    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
951    |  Time to Live |    Protocol   |         Header Checksum       |
952    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
953    |                       Source Address                          |
954    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
955    |                    Destination Address                        |
956    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
957    |                    Options                    |    Padding    |
958    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
959 
960 */
961 
962     /*
963      * Fill in the empty fields in the IP header and then re-calculate
964      * the checksum.
965      */
966     {
967         unsigned total_length = tmpl->ipv4.length - tmpl->ipv4.offset_ip;
968         px[offset_ip+2] = (unsigned char)(total_length>>8);
969         px[offset_ip+3] = (unsigned char)(total_length>>0);
970     }
971     px[offset_ip+4] = (unsigned char)(ip_id >> 8);
972     px[offset_ip+5] = (unsigned char)(ip_id & 0xFF);
973     px[offset_ip+12] = (unsigned char)((ip_me >> 24) & 0xFF);
974     px[offset_ip+13] = (unsigned char)((ip_me >> 16) & 0xFF);
975     px[offset_ip+14] = (unsigned char)((ip_me >>  8) & 0xFF);
976     px[offset_ip+15] = (unsigned char)((ip_me >>  0) & 0xFF);
977     px[offset_ip+16] = (unsigned char)((ip_them >> 24) & 0xFF);
978     px[offset_ip+17] = (unsigned char)((ip_them >> 16) & 0xFF);
979     px[offset_ip+18] = (unsigned char)((ip_them >>  8) & 0xFF);
980     px[offset_ip+19] = (unsigned char)((ip_them >>  0) & 0xFF);
981 
982 
983     px[offset_ip+10] = (unsigned char)(0);
984     px[offset_ip+11] = (unsigned char)(0);
985 
986     xsum2 = (unsigned)~ip_header_checksum(px, offset_ip, tmpl->ipv4.length);
987 
988     px[offset_ip+10] = (unsigned char)(xsum2 >> 8);
989     px[offset_ip+11] = (unsigned char)(xsum2 & 0xFF);
990 
991 
992     /*
993      * Now do the checksum for the higher layer protocols
994      */
995     xsum = 0;
996     switch (tmpl->proto) {
997     case Proto_TCP:
998         px[offset_tcp+ 0] = (unsigned char)(port_me >> 8);
999         px[offset_tcp+ 1] = (unsigned char)(port_me & 0xFF);
1000         px[offset_tcp+ 2] = (unsigned char)(port_them >> 8);
1001         px[offset_tcp+ 3] = (unsigned char)(port_them & 0xFF);
1002         px[offset_tcp+ 4] = (unsigned char)(seqno >> 24);
1003         px[offset_tcp+ 5] = (unsigned char)(seqno >> 16);
1004         px[offset_tcp+ 6] = (unsigned char)(seqno >>  8);
1005         px[offset_tcp+ 7] = (unsigned char)(seqno >>  0);
1006 
1007         xsum += (uint64_t)tmpl->ipv4.checksum_tcp
1008                 + (uint64_t)ip_me
1009                 + (uint64_t)ip_them
1010                 + (uint64_t)port_me
1011                 + (uint64_t)port_them
1012                 + (uint64_t)seqno;
1013         xsum = (xsum >> 16) + (xsum & 0xFFFF);
1014         xsum = (xsum >> 16) + (xsum & 0xFFFF);
1015         xsum = (xsum >> 16) + (xsum & 0xFFFF);
1016         xsum = ~xsum;
1017 
1018         px[offset_tcp+16] = (unsigned char)(xsum >>  8);
1019         px[offset_tcp+17] = (unsigned char)(xsum >>  0);
1020         break;
1021     case Proto_UDP:
1022         px[offset_tcp+ 0] = (unsigned char)(port_me >> 8);
1023         px[offset_tcp+ 1] = (unsigned char)(port_me & 0xFF);
1024         px[offset_tcp+ 2] = (unsigned char)(port_them >> 8);
1025         px[offset_tcp+ 3] = (unsigned char)(port_them & 0xFF);
1026         px[offset_tcp+ 4] = (unsigned char)((tmpl->ipv4.length - tmpl->ipv4.offset_app + 8)>>8);
1027         px[offset_tcp+ 5] = (unsigned char)((tmpl->ipv4.length - tmpl->ipv4.offset_app + 8)&0xFF);
1028 
1029         px[offset_tcp+6] = (unsigned char)(0);
1030         px[offset_tcp+7] = (unsigned char)(0);
1031         xsum = udp_checksum2(px, offset_ip, offset_tcp, tmpl->ipv4.length - offset_tcp);
1032         /*xsum += (uint64_t)tmpl->checksum_tcp
1033                 + (uint64_t)ip_me
1034                 + (uint64_t)ip_them
1035                 + (uint64_t)port_me
1036                 + (uint64_t)port_them
1037                 + (uint64_t)2*(tmpl->length - tmpl->offset_app);
1038         xsum = (xsum >> 16) + (xsum & 0xFFFF);
1039         xsum = (xsum >> 16) + (xsum & 0xFFFF);
1040         xsum = (xsum >> 16) + (xsum & 0xFFFF);
1041         printf("%04x\n", xsum);*/
1042         xsum = ~xsum;
1043         px[offset_tcp+6] = (unsigned char)(xsum >>  8);
1044         px[offset_tcp+7] = (unsigned char)(xsum >>  0);
1045         break;
1046     case Proto_SCTP:
1047         px[offset_tcp+ 0] = (unsigned char)(port_me >> 8);
1048         px[offset_tcp+ 1] = (unsigned char)(port_me & 0xFF);
1049         px[offset_tcp+ 2] = (unsigned char)(port_them >> 8);
1050         px[offset_tcp+ 3] = (unsigned char)(port_them & 0xFF);
1051 
1052         px[offset_tcp+16] = (unsigned char)(seqno >> 24);
1053         px[offset_tcp+17] = (unsigned char)(seqno >> 16);
1054         px[offset_tcp+18] = (unsigned char)(seqno >>  8);
1055         px[offset_tcp+19] = (unsigned char)(seqno >>  0);
1056 
1057         xsum = sctp_checksum(px + offset_tcp, tmpl->ipv4.length - offset_tcp);
1058         px[offset_tcp+ 8] = (unsigned char)(xsum >>  24);
1059         px[offset_tcp+ 9] = (unsigned char)(xsum >>  16);
1060         px[offset_tcp+10] = (unsigned char)(xsum >>   8);
1061         px[offset_tcp+11] = (unsigned char)(xsum >>   0);
1062         break;
1063     case Proto_ICMP_ping:
1064     case Proto_ICMP_timestamp:
1065             seqno = (unsigned)syn_cookie_ipv4(ip_them, port_them, ip_me, 0, entropy);
1066             px[offset_tcp+ 4] = (unsigned char)(seqno >> 24);
1067             px[offset_tcp+ 5] = (unsigned char)(seqno >> 16);
1068             px[offset_tcp+ 6] = (unsigned char)(seqno >>  8);
1069             px[offset_tcp+ 7] = (unsigned char)(seqno >>  0);
1070             xsum = (uint64_t)tmpl->ipv4.checksum_tcp
1071                     + (uint64_t)seqno;
1072             xsum = (xsum >> 16) + (xsum & 0xFFFF);
1073             xsum = (xsum >> 16) + (xsum & 0xFFFF);
1074             xsum = (xsum >> 16) + (xsum & 0xFFFF);
1075             xsum = ~xsum;
1076             px[offset_tcp+2] = (unsigned char)(xsum >>  8);
1077             px[offset_tcp+3] = (unsigned char)(xsum >>  0);
1078         break;
1079     case Proto_VulnCheck:
1080             tmplset->vulncheck->set_target(tmpl,
1081                                      ip_them, port_them,
1082                                      ip_me, port_me,
1083                                      seqno,
1084                                      px, sizeof_px, r_length);
1085             break;
1086     case Proto_ARP:
1087         /* don't do any checksumming */
1088         break;
1089     case Proto_Oproto:
1090         /* TODO: probably need to add checksums for certain protocols */
1091         break;
1092     case Proto_Count:
1093         break;
1094     }
1095 }
1096 
1097 #if defined(WIN32) || defined(_WIN32)
1098 #define AF_INET6 23
1099 #else
1100 #include <sys/socket.h>
1101 #endif
1102 
1103 /***************************************************************************
1104  * Creates an IPv6 packet from an IPv4 template, by simply replacing
1105  * the IPv4 header with the IPv6 header.
1106  ***************************************************************************/
1107 static void
_template_init_ipv6(struct TemplatePacket * tmpl,macaddress_t router_mac_ipv6,unsigned data_link_type)1108 _template_init_ipv6(struct TemplatePacket *tmpl, macaddress_t router_mac_ipv6, unsigned data_link_type)
1109 {
1110     struct PreprocessedInfo parsed;
1111     unsigned x;
1112     unsigned payload_length;
1113     unsigned offset_ip;
1114     unsigned offset_tcp;
1115     unsigned offset_tcp6;
1116     unsigned char *buf;
1117 
1118     /* Zero out everything and start from scratch */
1119     if (tmpl->ipv6.packet) {
1120         free(tmpl->ipv6.packet);
1121         memset(&tmpl->ipv6, 0, sizeof(tmpl->ipv6));
1122     }
1123 
1124     /* Parse the existing IPv4 packet */
1125     x = preprocess_frame(tmpl->ipv4.packet, tmpl->ipv4.length, data_link_type, &parsed);
1126     if (!x || parsed.found == FOUND_NOTHING) {
1127         LOG(0, "ERROR: bad packet template\n");
1128         exit(1);
1129     }
1130 
1131     /* The "payload" in this case is everything past the IP header,
1132      * so TCP or UDP headers are inside the IP payload */
1133     payload_length = tmpl->ipv4.length - tmpl->ipv4.offset_tcp;
1134     offset_ip = tmpl->ipv4.offset_ip;
1135     offset_tcp = tmpl->ipv4.offset_tcp;
1136 
1137     /* Create a copy of the IPv4 packet */
1138     buf = MALLOC(tmpl->ipv4.length + 40);
1139     memcpy(buf, tmpl->ipv4.packet, tmpl->ipv4.length);
1140     tmpl->ipv6.packet = buf;
1141 
1142 
1143     /* destination = end of IPv6 header
1144      * source = end of IPv4 header
1145      * contents = everything after IPv4/IPv6 header */
1146     offset_tcp6 = offset_ip + 40;
1147     memmove(buf + offset_tcp6,
1148             buf + offset_tcp,
1149             payload_length
1150             );
1151 
1152     /* fill the IPv6 header with zeroes */
1153     memset(buf + offset_ip, 0, 40);
1154     tmpl->ipv6.length = offset_ip + 40 + payload_length;
1155 
1156     switch (data_link_type) {
1157         case PCAP_DLT_NULL: /* Null VPN tunnel */
1158             /* FIXME: insert platform dependent value here */
1159             *(int*)buf = AF_INET6;
1160             break;
1161 	case PCAP_DLT_RAW: /* Raw (nothing before IP header) */
1162 	    break;
1163         case PCAP_DLT_ETHERNET: /* Etherent */
1164             /* Reset the destination MAC address to be the IPv6 router
1165              * instead of the IPv4 router, which sometimes are different */
1166             memcpy(buf + 0, router_mac_ipv6.addr, 6);
1167 
1168             /* Reset the Ethertype field to 0x86dd (meaning IPv6) */
1169             buf[12] = 0x86;
1170             buf[13] = 0xdd;
1171             break;
1172     }
1173 
1174 
1175     /* IP.version = 6 */
1176     buf[offset_ip + 0] = 0x60;
1177 
1178     /* Set payload length field. In IPv4, this field included the header,
1179      * but in IPv6, it's everything after the header. In other words,
1180      * the size of an IPv6 packet is 40+payload_length, whereas in IPv4
1181      * it was total_length. */
1182     buf[offset_ip + 4] = (unsigned char)(payload_length >> 8);
1183     buf[offset_ip + 5] = (unsigned char)(payload_length >> 0);
1184 
1185     /* Set the "next header" field.
1186      * TODO: need to fix ICMP */
1187     buf[offset_ip + 6] = (unsigned char)parsed.ip_protocol;
1188     if (parsed.ip_protocol == 1) {
1189         buf[offset_ip + 6] = 58; /* ICMPv6 */
1190         if (payload_length > 0 && buf[offset_tcp6 + 0] == 8) {
1191             /* PING -> PINGv6 */
1192             buf[offset_tcp6 + 0] = 128;
1193         }
1194     }
1195 
1196     /* Hop limit starts out as 255 */
1197     buf[offset_ip + 7] = 0xFF;
1198 
1199     /* Parse our newly construct IPv6 packet */
1200     x = preprocess_frame(buf, tmpl->ipv6.length, data_link_type, &parsed);
1201     if (!x || parsed.found == FOUND_NOTHING) {
1202         LOG(0, "[-] FAILED: bad packet template\n");
1203         exit(1);
1204     }
1205     tmpl->ipv6.offset_ip = parsed.ip_offset;
1206     tmpl->ipv6.offset_tcp = parsed.transport_offset;
1207     tmpl->ipv6.offset_app = parsed.app_offset;
1208 
1209 
1210 }
1211 
1212 /***************************************************************************
1213  * Here we take a packet template, parse it, then make it easier to work
1214  * with.
1215  ***************************************************************************/
1216 static void
_template_init(struct TemplatePacket * tmpl,macaddress_t source_mac,macaddress_t router_mac_ipv4,macaddress_t router_mac_ipv6,const void * packet_bytes,size_t packet_size,unsigned data_link_type)1217 _template_init(
1218     struct TemplatePacket *tmpl,
1219     macaddress_t source_mac,
1220     macaddress_t router_mac_ipv4,
1221     macaddress_t router_mac_ipv6,
1222     const void *packet_bytes,
1223     size_t packet_size,
1224     unsigned data_link_type
1225     )
1226 {
1227     unsigned char *px;
1228     struct PreprocessedInfo parsed;
1229     unsigned x;
1230 
1231     /*
1232      * Create the new template structure:
1233      * - zero it out
1234      * - make copy of the old packet to serve as new template
1235      */
1236     memset(tmpl, 0, sizeof(*tmpl));
1237     tmpl->ipv4.length = (unsigned)packet_size;
1238 
1239     tmpl->ipv4.packet = MALLOC(2048 + packet_size);
1240     memcpy(tmpl->ipv4.packet, packet_bytes, tmpl->ipv4.length);
1241     px = tmpl->ipv4.packet;
1242 
1243     /*
1244      * Parse the existing packet template. We support TCP, UDP, ICMP,
1245      * and ARP packets.
1246      */
1247     x = preprocess_frame(px, tmpl->ipv4.length, 1 /*enet*/, &parsed);
1248     if (!x || parsed.found == FOUND_NOTHING) {
1249         LOG(0, "ERROR: bad packet template\n");
1250         exit(1);
1251     }
1252     tmpl->ipv4.offset_ip = parsed.ip_offset;
1253     tmpl->ipv4.offset_tcp = parsed.transport_offset;
1254     tmpl->ipv4.offset_app = parsed.app_offset;
1255     if (parsed.found == FOUND_ARP) {
1256         tmpl->ipv4.length = parsed.ip_offset + 28;
1257     } else
1258         tmpl->ipv4.length = parsed.ip_offset + parsed.ip_length;
1259 
1260     /*
1261      * Overwrite the MAC and IP addresses
1262      */
1263     memcpy(px+0, router_mac_ipv4.addr, 6);
1264     memcpy(px+6, source_mac.addr, 6);
1265     memset((void*)parsed._ip_src, 0, 4);
1266     memset((void*)parsed._ip_dst, 0, 4);
1267 
1268 
1269     /*
1270      * ARP
1271      *
1272      * If this is an ARP template (for doing arpscans), then just set our
1273      * configured source IP and MAC addresses.
1274      */
1275     if (parsed.found == FOUND_ARP) {
1276         memcpy((char*)parsed._ip_src - 6, source_mac.addr, 6);
1277         tmpl->proto = Proto_ARP;
1278         return;
1279     }
1280 
1281     /*
1282      * IPv4
1283      *
1284      * Calculate the partial checksum. We zero out the fields that will be
1285      * added later the packet, then calculate the checksum as if they were
1286      * zero. This makes recalculation of the checksum easier when we transmit
1287      */
1288     memset(px + tmpl->ipv4.offset_ip + 4, 0, 2);  /* IP ID field */
1289     memset(px + tmpl->ipv4.offset_ip + 10, 0, 2); /* checksum */
1290     memset(px + tmpl->ipv4.offset_ip + 12, 0, 8); /* addresses */
1291     tmpl->ipv4.checksum_ip = ip_header_checksum( tmpl->ipv4.packet,
1292                                             tmpl->ipv4.offset_ip,
1293                                             tmpl->ipv4.length);
1294 
1295     /*
1296      * Higher layer protocols: zero out dest/checksum fields, then calculate
1297      * a partial checksum
1298      */
1299     switch (parsed.ip_protocol) {
1300     case 1: /* ICMP */
1301             tmpl->ipv4.offset_app = tmpl->ipv4.length;
1302             tmpl->ipv4.checksum_tcp = icmp_ipv4_checksum(tmpl);
1303             switch (px[tmpl->ipv4.offset_tcp]) {
1304                 case 8:
1305                     tmpl->proto = Proto_ICMP_ping;
1306                     break;
1307                 case 13:
1308                     tmpl->proto = Proto_ICMP_timestamp;
1309                     break;
1310             }
1311             break;
1312         break;
1313     case 6: /* TCP */
1314         /* zero out fields that'll be overwritten */
1315         memset(px + tmpl->ipv4.offset_tcp + 0, 0, 8); /* destination port and seqno */
1316         memset(px + tmpl->ipv4.offset_tcp + 16, 0, 2); /* checksum */
1317         tmpl->ipv4.checksum_tcp = tcp_ipv4_checksum(tmpl);
1318         tmpl->proto = Proto_TCP;
1319         break;
1320     case 17: /* UDP */
1321         memset(px + tmpl->ipv4.offset_tcp + 6, 0, 2); /* checksum */
1322         tmpl->ipv4.checksum_tcp = udp_ipv4_checksum(tmpl);
1323         tmpl->proto = Proto_UDP;
1324         break;
1325     case 132: /* SCTP */
1326         tmpl->ipv4.checksum_tcp = sctp_checksum(
1327                                     tmpl->ipv4.packet + tmpl->ipv4.offset_tcp,
1328                                     tmpl->ipv4.length - tmpl->ipv4.offset_tcp);
1329         tmpl->proto = Proto_SCTP;
1330         break;
1331     }
1332 
1333     /*
1334      * DATALINK KLUDGE
1335      *
1336      * Adjust the data link header in case of Raw IP packets. This isn't
1337      * the correct way to do this, but I'm too lazy to refactor code
1338      * for the right way, so we'll do it this way now.
1339      */
1340     if (data_link_type == PCAP_DLT_NULL /* Null VPN tunnel */) {
1341         int linkproto = 2; /* AF_INET */
1342         tmpl->ipv4.length -= tmpl->ipv4.offset_ip - sizeof(int);
1343         tmpl->ipv4.offset_tcp -= tmpl->ipv4.offset_ip - sizeof(int);
1344         tmpl->ipv4.offset_app -= tmpl->ipv4.offset_ip - sizeof(int);
1345         memmove(tmpl->ipv4.packet + sizeof(int),
1346                 tmpl->ipv4.packet + tmpl->ipv4.offset_ip,
1347                 tmpl->ipv4.length);
1348         tmpl->ipv4.offset_ip = 4;
1349         memcpy(tmpl->ipv4.packet, &linkproto, sizeof(int));
1350     } else if (data_link_type == PCAP_DLT_RAW /* Raw IP */) {
1351         tmpl->ipv4.length -= tmpl->ipv4.offset_ip;
1352         tmpl->ipv4.offset_tcp -= tmpl->ipv4.offset_ip;
1353         tmpl->ipv4.offset_app -= tmpl->ipv4.offset_ip;
1354         memmove(tmpl->ipv4.packet,
1355                 tmpl->ipv4.packet + tmpl->ipv4.offset_ip,
1356                 tmpl->ipv4.length);
1357         tmpl->ipv4.offset_ip = 0;
1358     } else if (data_link_type == PCAP_DLT_ETHERNET) {
1359 	/* the default, do nothing */
1360     } else {
1361 	LOG(0, "[-] FAILED: bad packet template, unknown data link type\n");
1362         LOG(0, "    [hint] masscan doesn't know how to format packets for this interface\n");
1363 	exit(1);
1364     }
1365 
1366     /* Now create an IPv6 template based upon the IPv4 template */
1367     _template_init_ipv6(tmpl, router_mac_ipv6, data_link_type);
1368 }
1369 
1370 /***************************************************************************
1371  ***************************************************************************/
1372 void
template_packet_init(struct TemplateSet * templset,macaddress_t source_mac,macaddress_t router_mac_ipv4,macaddress_t router_mac_ipv6,struct PayloadsUDP * udp_payloads,struct PayloadsUDP * oproto_payloads,int data_link,uint64_t entropy)1373 template_packet_init(
1374     struct TemplateSet *templset,
1375     macaddress_t source_mac,
1376     macaddress_t router_mac_ipv4,
1377     macaddress_t router_mac_ipv6,
1378     struct PayloadsUDP *udp_payloads,
1379     struct PayloadsUDP *oproto_payloads,
1380     int data_link,
1381     uint64_t entropy)
1382 {
1383     templset->count = 0;
1384     templset->entropy = entropy;
1385 
1386     /* [SCTP] */
1387     _template_init(&templset->pkts[Proto_SCTP],
1388                    source_mac, router_mac_ipv4, router_mac_ipv6,
1389                    default_sctp_template,
1390                    sizeof(default_sctp_template)-1,
1391                    data_link);
1392     templset->count++;
1393 
1394     /* [TCP] */
1395     _template_init(&templset->pkts[Proto_TCP],
1396                    source_mac, router_mac_ipv4, router_mac_ipv6,
1397                    default_tcp_template,
1398                    sizeof(default_tcp_template)-1,
1399                    data_link);
1400     templset->count++;
1401 
1402     /* [UDP] */
1403     _template_init(&templset->pkts[Proto_UDP],
1404                    source_mac, router_mac_ipv4, router_mac_ipv6,
1405                    default_udp_template,
1406                    sizeof(default_udp_template)-1,
1407                    data_link);
1408     templset->pkts[Proto_UDP].payloads = udp_payloads;
1409     templset->count++;
1410 
1411     /* [UDP oproto] */
1412     _template_init(&templset->pkts[Proto_Oproto],
1413                    source_mac, router_mac_ipv4, router_mac_ipv6,
1414                    default_udp_template,
1415                    sizeof(default_udp_template)-1,
1416                    data_link);
1417     templset->pkts[Proto_Oproto].payloads = oproto_payloads;
1418     templset->count++;
1419 
1420 
1421     /* [ICMP ping] */
1422     _template_init(&templset->pkts[Proto_ICMP_ping],
1423                    source_mac, router_mac_ipv4, router_mac_ipv6,
1424                    default_icmp_ping_template,
1425                    sizeof(default_icmp_ping_template)-1,
1426                    data_link);
1427     templset->count++;
1428 
1429     /* [ICMP timestamp] */
1430     _template_init(&templset->pkts[Proto_ICMP_timestamp],
1431                    source_mac, router_mac_ipv4, router_mac_ipv6,
1432                    default_icmp_timestamp_template,
1433                    sizeof(default_icmp_timestamp_template)-1,
1434                    data_link);
1435     templset->count++;
1436 
1437     /* [ARP] */
1438     _template_init( &templset->pkts[Proto_ARP],
1439                     source_mac, router_mac_ipv4, router_mac_ipv6,
1440                     default_arp_template,
1441                     sizeof(default_arp_template)-1,
1442                     data_link);
1443     templset->count++;
1444 
1445     /* [VulnCheck] */
1446     if (templset->vulncheck) {
1447         _template_init( &templset->pkts[Proto_VulnCheck],
1448                        source_mac, router_mac_ipv4, router_mac_ipv6,
1449                        templset->vulncheck->packet,
1450                        templset->vulncheck->packet_length,
1451                        data_link);
1452         templset->count++;
1453     }
1454 }
1455 
1456 
1457 
1458 
1459 /***************************************************************************
1460  * Overwrites the TTL of the packet
1461  ***************************************************************************/
1462 void
template_set_ttl(struct TemplateSet * tmplset,unsigned ttl)1463 template_set_ttl(struct TemplateSet *tmplset, unsigned ttl)
1464 {
1465     unsigned i;
1466 
1467     for (i=0; i<tmplset->count; i++) {
1468         struct TemplatePacket *tmpl = &tmplset->pkts[i];
1469         unsigned char *px = tmpl->ipv4.packet;
1470         unsigned offset = tmpl->ipv4.offset_ip;
1471 
1472         px[offset+8] = (unsigned char)(ttl);
1473         tmpl->ipv4.checksum_ip = ip_header_checksum(    tmpl->ipv4.packet,
1474                                                     tmpl->ipv4.offset_ip,
1475                                                     tmpl->ipv4.length);
1476     }
1477 }
1478 
1479 void
template_set_vlan(struct TemplateSet * tmplset,unsigned vlan)1480 template_set_vlan(struct TemplateSet *tmplset, unsigned vlan)
1481 {
1482     unsigned i;
1483 
1484     for (i=0; i<tmplset->count; i++) {
1485         struct TemplatePacket *tmpl = &tmplset->pkts[i];
1486         unsigned char *px;
1487 
1488         if (tmpl->ipv4.length < 14)
1489             continue;
1490 
1491         px = MALLOC(tmpl->ipv4.length + 4);
1492         memcpy(px, tmpl->ipv4.packet, 12);
1493         memcpy(px+16, tmpl->ipv4.packet+12, tmpl->ipv4.length - 12);
1494 
1495         px[12] = 0x81;
1496         px[13] = 0x00;
1497         px[14] = (unsigned char)(vlan>>8);
1498         px[15] = (unsigned char)(vlan>>0);
1499 
1500         tmpl->ipv4.packet = px;
1501         tmpl->ipv4.length += 4;
1502 
1503         tmpl->ipv4.offset_ip += 4;
1504         tmpl->ipv4.offset_tcp += 4;
1505         tmpl->ipv4.offset_app += 4;
1506     }
1507 }
1508 
1509 
1510 
1511 /***************************************************************************
1512  ***************************************************************************/
1513 int
template_selftest(void)1514 template_selftest(void)
1515 {
1516     struct TemplateSet tmplset[1];
1517     int failures = 0;
1518 
1519     memset(tmplset, 0, sizeof(tmplset[0]));
1520     template_packet_init(
1521             tmplset,
1522             macaddress_from_bytes("\x00\x11\x22\x33\x44\x55"),
1523             macaddress_from_bytes("\x66\x55\x44\x33\x22\x11"),
1524             macaddress_from_bytes("\x66\x55\x44\x33\x22\x11"),
1525             0,  /* UDP payloads = empty */
1526             0,  /* Oproto payloads = empty */
1527             1,  /* Ethernet */
1528             0   /* no entropy */
1529             );
1530     failures += tmplset->pkts[Proto_TCP].proto  != Proto_TCP;
1531     failures += tmplset->pkts[Proto_UDP].proto  != Proto_UDP;
1532     //failures += tmplset->pkts[Proto_SCTP].proto != Proto_SCTP;
1533     failures += tmplset->pkts[Proto_ICMP_ping].proto != Proto_ICMP_ping;
1534     //failures += tmplset->pkts[Proto_ICMP_timestamp].proto != Proto_ICMP_timestamp;
1535     //failures += tmplset->pkts[Proto_ARP].proto  != Proto_ARP;
1536 
1537     if (failures)
1538         fprintf(stderr, "template: failed\n");
1539     return failures;
1540 }
1541 
1542