OpenVAS Libraries  9.0.3
nasl_packet_forgery_v6.c
Go to the documentation of this file.
1 /* Nessus Attack Scripting Language
2  *
3  * Copyright (C) 2002 - 2004 Tenable Network Security
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2,
7  * as published by the Free Software Foundation
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  *
18  *
19  * Modified for IPv6 packet forgery - 04/02/2010
20  * Preeti Subramanian <spreeti@secpod.com>
21  * Srinivas NL <nl.srinivas@gmail.com>
22  *
23  * Modified for ICMPv6, IPv6 packet forgery support for IGMP and UDP - 09/02/2010
24  * Preeti Subramanian <spreeti@secpod.com>
25  */
26 
39 #include <arpa/inet.h> /* for inet_aton */
40 #include <ctype.h> /* for isprint */
41 #include <pcap.h> /* for PCAP_ERRBUF_SIZE */
42 #include <stdlib.h> /* for rand */
43 #include <string.h> /* for bcopy */
44 #include <sys/time.h> /* for gettimeofday */
45 #include <unistd.h> /* for close */
46 #include <netinet/icmp6.h> /* ICMPv6 */
47 
48 #include "../misc/bpf_share.h" /* for bpf_open_live */
49 #include "../misc/pcap_openvas.h" /* for routethrough */
50 #include "../misc/plugutils.h" /* plug_get_host_ip */
51 
52 #include "nasl_raw.h"
53 
54 #include "nasl_tree.h"
55 #include "nasl_global_ctxt.h"
56 #include "nasl_func.h"
57 #include "nasl_var.h"
58 #include "nasl_lex_ctxt.h"
59 #include "exec.h"
60 #include "nasl_socket.h"
61 
62 #include "nasl_debug.h"
63 #include "capture_packet.h"
64 #include "nasl_packet_forgery_v6.h"
65 
68 #ifdef BSD_BYTE_ORDERING
69 #define FIX(n) (n)
70 #define UNFIX(n) (n)
71 #else
72 #define FIX(n) htons(n)
73 #define UNFIX(n) ntohs(n)
74 #endif
75 
76 /*--------------[ cksum ]-----------------------------------------*/
77 
78 /*
79  * Checksum routine for Internet Protocol family headers (C Version)
80  * From ping examples in W.Richard Stevens "UNIX NETWORK PROGRAMMING" book.
81  */
82 static int
83 np_in_cksum (p, n)
84  u_short *p;
85  int n;
86 {
87  register u_short answer = 0;
88  register long sum = 0;
89  u_short odd_byte = 0;
90 
91  while (n > 1)
92  {
93  sum += *p++;
94  n -= 2;
95  }
96 
97  /* mop up an odd byte, if necessary */
98  if (n == 1)
99  {
100  *(u_char *) (&odd_byte) = *(u_char *) p;
101  sum += odd_byte;
102  }
103 
104  sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
105  sum += (sum >> 16); /* add carry */
106  answer = (int) ~sum; /* ones-complement, truncate */
107  return (answer);
108 }
109 
110 
111 /*--------------[ IP ]--------------------------------------------*/
119 tree_cell *
121 {
122  tree_cell *retc;
123  struct ip6_hdr *pkt;
124  char *s;
125  struct arglist *script_infos = lexic->script_infos;
126  struct in6_addr *dst_addr;
127  char *data;
128  int data_len;
129  int version;
130  int tc;
131  int fl;
132 
133  dst_addr = plug_get_host_ip (script_infos);
134 
135  if (dst_addr == NULL || (IN6_IS_ADDR_V4MAPPED (dst_addr) == 1))
136  return NULL;
137 
138  data = get_str_local_var_by_name (lexic, "data");
139  data_len = get_local_var_size_by_name (lexic, "data");
140 
141  retc = alloc_tree_cell (0, NULL);
142  retc->type = CONST_DATA;
143  retc->size = sizeof (struct ip6_hdr) + data_len;
144 
145  pkt = (struct ip6_hdr *) g_malloc0 (sizeof (struct ip6_hdr) + data_len);
146  retc->x.str_val = (char *) pkt;
147 
148  version = get_int_local_var_by_name (lexic, "ip6_v", 6);
149  tc = get_int_local_var_by_name (lexic, "ip6_tc", 0);
150  fl = get_int_local_var_by_name (lexic, "ip6_fl", 0);
151 
152  pkt->ip6_ctlun.ip6_un1.ip6_un1_flow = version | tc | fl;
153 
154  pkt->ip6_plen = FIX (data_len); /* No extension headers ? */
155  pkt->ip6_nxt = get_int_local_var_by_name (lexic, "ip6_p", 0);
156  pkt->ip6_hlim = get_int_local_var_by_name (lexic, "ip6_hlim", 64);
157 
158  /* source */
159  s = get_str_local_var_by_name (lexic, "ip6_src");
160  if (s != NULL)
161  inet_pton (AF_INET6, s, &pkt->ip6_src);
162  /* else this host address? */
163 
164  s = get_str_local_var_by_name (lexic, "ip6_dst");
165  if (s != NULL)
166  inet_pton (AF_INET6, s, &pkt->ip6_dst);
167  else
168  pkt->ip6_dst = *dst_addr;
169 
170  if (data != NULL)
171  {
172  bcopy (data, retc->x.str_val + sizeof (struct ip6_hdr), data_len);
173  }
174 
175  /*
176  There is no checksum for ipv6. Only upper layer
177  calculates a checksum using pseudoheader
178  */
179  return retc;
180 }
181 
189 tree_cell *
191 {
192  tree_cell *retc;
193  struct ip6_hdr *ip6 =
194  (struct ip6_hdr *) get_str_local_var_by_name (lexic, "ipv6");
195  char *element = get_str_local_var_by_name (lexic, "element");
196  char ret_ascii[INET6_ADDRSTRLEN];
197  int ret_int = 0;
198  int flag = 0;
199 
200  if (ip6 == NULL)
201  {
202  nasl_perror (lexic, "get_ipv6_element : no valid 'ip' argument!\n");
203  return NULL;
204  }
205 
206  if (element == NULL)
207  {
208  nasl_perror (lexic, "get_ipv6_element : no valid 'element' argument!\n");
209  return NULL;
210  }
211 
212  if (!strcmp (element, "ip6_v"))
213  {
214  ret_int = (ip6->ip6_flow & 0x3ffff);
215  flag++;
216  }
217  else if (!strcmp (element, "ip6_tc"))
218  {
219  ret_int = (ip6->ip6_flow >> 20) & 0xff;
220  flag++;
221  }
222  else if (!strcmp (element, "ip6_fl"))
223  {
224  ret_int = ip6->ip6_flow >> 28;
225  flag++;
226  }
227  else if (!strcmp (element, "ip6_plen"))
228  {
229  ret_int = (ip6->ip6_plen);
230  flag++;
231  }
232  else if (!strcmp (element, "ip6_nxt"))
233  {
234  ret_int = (ip6->ip6_nxt);
235  flag++;
236  }
237  else if (!strcmp (element, "ip6_hlim"))
238  {
239  ret_int = (ip6->ip6_hlim);
240  flag++;
241  }
242 
243  if (flag != 0)
244  {
245  retc = alloc_tree_cell (0, NULL);
246  retc->type = CONST_INT;
247  retc->x.i_val = ret_int;
248  return retc;
249  }
250 
251  if (!strcmp (element, "ip6_src"))
252  {
253  inet_ntop (AF_INET6, &ip6->ip6_src, ret_ascii, sizeof (ret_ascii));
254  flag++;
255  }
256  else if (!strcmp (element, "ip6_dst"))
257  {
258  inet_ntop (AF_INET6, &ip6->ip6_dst, ret_ascii, sizeof (ret_ascii));
259  flag++;
260  }
261 
262  if (flag == 0)
263  {
264  printf ("%s : unknown element\n", element);
265  return NULL;
266  }
267 
268  retc = alloc_tree_cell (0, NULL);
269  retc->type = CONST_DATA;
270  retc->size = strlen (ret_ascii);
271  retc->x.str_val = g_strdup (ret_ascii);
272 
273  return retc;
274 }
275 
283 tree_cell *
285 {
286  struct ip6_hdr *o_pkt =
287  (struct ip6_hdr *) get_str_local_var_by_name (lexic, "ip6");
288  int size = get_var_size_by_name (lexic, "ip6");
289  tree_cell *retc = alloc_tree_cell (0, NULL);
290  struct ip6_hdr *pkt;
291  char *s;
292 
293  if (o_pkt == NULL)
294  {
295  nasl_perror (lexic, "set_ip_elements: missing <ip> field\n");
296  return NULL;
297  }
298 
299  pkt = (struct ip6_hdr *) g_malloc0 (size);
300  bcopy (o_pkt, pkt, size);
301 
302  pkt->ip6_plen = get_int_local_var_by_name (lexic, "ip6_plen", pkt->ip6_plen);
303  pkt->ip6_nxt = get_int_local_var_by_name (lexic, "ip6_nxt", pkt->ip6_nxt);
304  pkt->ip6_hlim = get_int_local_var_by_name (lexic, "ip6_hlim", pkt->ip6_hlim);
305 
306  s = get_str_local_var_by_name (lexic, "ip6_src");
307  if (s != NULL)
308  inet_pton (AF_INET6, s, &pkt->ip6_src);
309 
310  retc->type = CONST_DATA;
311  retc->size = size;
312  retc->x.str_val = (char *) pkt;
313 
314  return retc;
315 }
316 
324 tree_cell *
326 {
327  int i;
328  char addr[INET6_ADDRSTRLEN];
329 
330  for (i = 0;; i++)
331  {
332  struct ip6_hdr *ip6 = (struct ip6_hdr *) get_str_var_by_num (lexic, i);
333 
334  if (ip6 == NULL)
335  break;
336  else
337  {
338  printf ("------\n");
339  printf ("\tip6_v : %d\n", ip6->ip6_flow >> 28);
340  printf ("\tip6_tc: %d\n", (ip6->ip6_flow >> 20) & 0xff);
341  printf ("\tip6_fl: %d\n", (ip6->ip6_flow) & 0x3ffff);
342  printf ("\tip6_plen: %d\n", UNFIX (ip6->ip6_plen));
343  printf ("\tip6_nxt : %d\n", ntohs (ip6->ip6_nxt));
344  printf ("\tip6_hlim : %d\n", ntohs (ip6->ip6_hlim));
345  switch (ip6->ip6_ctlun.ip6_un1.ip6_un1_nxt)
346  {
347  case IPPROTO_TCP:
348  printf ("\tip6_nxt : IPPROTO_TCP (%d)\n", ip6->ip6_nxt);
349  break;
350  case IPPROTO_UDP:
351  printf ("\tip6_nxt : IPPROTO_UDP (%d)\n", ip6->ip6_nxt);
352  break;
353  case IPPROTO_ICMP:
354  printf ("\tip6_nxt : IPPROTO_ICMP (%d)\n", ip6->ip6_nxt);
355  break;
356  default:
357  printf ("\tip6_nxt : %d\n", ip6->ip6_nxt);
358  break;
359  }
360  printf ("\tip6_src: %s\n",
361  inet_ntop (AF_INET6, &ip6->ip6_src, addr, sizeof (addr)));
362  printf ("\tip6_dst: %s\n",
363  inet_ntop (AF_INET6, &ip6->ip6_dst, addr, sizeof (addr)));
364  printf ("\n");
365  }
366  }
367 
368  return FAKE_CELL;
369 }
370 
371 tree_cell *
373 {
374  struct ip6_hdr *ip6 =
375  (struct ip6_hdr *) get_str_local_var_by_name (lexic, "ip6");
376  int code = get_int_local_var_by_name (lexic, "code", 0);
377  int len = get_int_local_var_by_name (lexic, "length", 0);
378  char *value = get_str_local_var_by_name (lexic, "value");
379  int value_size = get_var_size_by_name (lexic, "value");
380  tree_cell *retc;
381  struct ip6_hdr *new_packet;
382  char *p;
383  int size = get_var_size_by_name (lexic, "ip6");
384  u_char uc_code, uc_len;
385  int pad_len;
386  char zero = '0';
387  int i;
388  int pl;
389 
390  if (ip6 == NULL)
391  {
392  nasl_perror (lexic,
393  "Usage : insert_ipv6_options(ip6:<ip6>, code:<code>, length:<len>, value:<value>\n");
394  return NULL;
395  }
396 
397  pad_len = 4 - ((sizeof (uc_code) + sizeof (uc_len) + value_size) % 4);
398  if (pad_len == 4)
399  pad_len = 0;
400 
401  pl = 40 < UNFIX (ip6->ip6_plen) ? 40 : UNFIX (ip6->ip6_plen);
402  new_packet = g_malloc0 (size + 4 + value_size + pad_len);
403  bcopy (ip6, new_packet, pl);
404 
405  uc_code = (u_char) code;
406  uc_len = (u_char) len;
407 
408 
409  p = (char *) new_packet;
410  bcopy (&uc_code, p + pl, sizeof (uc_code));
411  bcopy (&uc_len, p + pl + sizeof (uc_code), sizeof (uc_len));
412  bcopy (value, p + pl + sizeof (uc_code) + sizeof (uc_len), value_size);
413 
414  zero = 0;
415  for (i = 0; i < pad_len; i++)
416  {
417  bcopy (&zero,
418  p + pl + sizeof (uc_code) + sizeof (uc_len) + value_size + i, 1);
419  }
420 
421 
422  p = (char *) ip6;
423  bcopy (p + pl,
424  new_packet + (sizeof (uc_code) + sizeof (uc_len) + value_size +
425  pad_len) + pl, size - pl);
426 
427 
428  new_packet->ip6_plen =
429  FIX (size + sizeof (uc_code) + sizeof (uc_len) + value_size + pad_len);
430 
431  retc = alloc_tree_cell (0, NULL);
432  retc->type = CONST_DATA;
433  retc->size = size + value_size + sizeof (uc_code) + sizeof (uc_len) + pad_len;
434  retc->x.str_val = (char *) new_packet;
435 
436  return retc;
437 }
438 
439 
440 /*--------------[ TCP ]--------------------------------------------*/
441 
443 {
444  struct in6_addr s6addr;
445  struct in6_addr d6addr;
446  u_short length;
447  u_char zero1;
448  u_char zero2;
449  u_char zero3;
450  u_char protocol;
451  struct tcphdr tcpheader;
452 };
453 
454 
462 tree_cell *
464 {
465  tree_cell *retc;
466  char *data;
467  int len;
468  struct ip6_hdr *ip6, *tcp_packet;
469  struct tcphdr *tcp;
470  int ipsz;
471 
472  ip6 = (struct ip6_hdr *) get_str_local_var_by_name (lexic, "ip6");
473  if (ip6 == NULL)
474  {
475  nasl_perror (lexic,
476  "forge_tcp_packet : You must supply the 'ip' argument !");
477  return NULL;
478  }
479 
480  ipsz = get_local_var_size_by_name (lexic, "ip6");
481 
482  // Not considering IP Options.
483  if (ipsz != 40)
484  ipsz = 40;
485 
486  data = get_str_local_var_by_name (lexic, "data");
487  len = data == NULL ? 0 : get_var_size_by_name (lexic, "data");
488 
489  retc = alloc_tree_cell (0, NULL);
490  retc->type = CONST_DATA;
491  tcp_packet = (struct ip6_hdr *) g_malloc0 (ipsz + sizeof (struct tcphdr) + len);
492  retc->x.str_val = (char *) tcp_packet;
493 
494  bcopy (ip6, tcp_packet, ipsz);
495  /* Adjust length in ipv6 header */
496  tcp_packet->ip6_ctlun.ip6_un1.ip6_un1_plen =
497  FIX (sizeof (struct tcphdr) + len);
498  tcp = (struct tcphdr *) ((char *) tcp_packet + 40);
499 
500  tcp->th_sport = ntohs (get_int_local_var_by_name (lexic, "th_sport", 0));
501  tcp->th_dport = ntohs (get_int_local_var_by_name (lexic, "th_dport", 0));
502  tcp->th_seq = htonl (get_int_local_var_by_name (lexic, "th_seq", rand ()));
503  tcp->th_ack = htonl (get_int_local_var_by_name (lexic, "th_ack", 0));
504  tcp->th_x2 = get_int_local_var_by_name (lexic, "th_x2", 0);
505  tcp->th_off = get_int_local_var_by_name (lexic, "th_off", 5);
506  tcp->th_flags = get_int_local_var_by_name (lexic, "th_flags", 0);
507  tcp->th_win = htons (get_int_local_var_by_name (lexic, "th_win", 0));
508  tcp->th_sum = get_int_local_var_by_name (lexic, "th_sum", 0);
509  tcp->th_urp = get_int_local_var_by_name (lexic, "th_urp", 0);
510 
511  if (data != NULL)
512  bcopy (data, (char *) tcp + sizeof (struct tcphdr), len);
513 
514  if (!tcp->th_sum)
515  {
516  struct v6pseudohdr pseudoheader;
517  char *tcpsumdata = g_malloc0 (sizeof (struct v6pseudohdr) + len + 1);
518 
519  bzero (&pseudoheader, 38 + sizeof (struct tcphdr));
520  memcpy (&pseudoheader.s6addr, &ip6->ip6_src, sizeof (struct in6_addr));
521  memcpy (&pseudoheader.d6addr, &ip6->ip6_dst, sizeof (struct in6_addr));
522 
523  pseudoheader.protocol = IPPROTO_TCP;
524  pseudoheader.length = htons (sizeof (struct tcphdr) + len);
525  bcopy ((char *) tcp, (char *) &pseudoheader.tcpheader,
526  sizeof (struct tcphdr));
527  /* fill tcpsumdata with data to checksum */
528  bcopy ((char *) &pseudoheader, tcpsumdata, sizeof (struct v6pseudohdr));
529  if (data != NULL)
530  bcopy ((char *) data, tcpsumdata + sizeof (struct v6pseudohdr), len);
531  tcp->th_sum =
532  np_in_cksum ((unsigned short *) tcpsumdata,
533  38 + sizeof (struct tcphdr) + len);
534  g_free (tcpsumdata);
535  }
536 
537  retc->size = ipsz + sizeof (struct tcphdr) + len;
538  return retc;
539 }
540 
548 tree_cell *
550 {
551  u_char *packet = (u_char *) get_str_local_var_by_name (lexic, "tcp");
552  struct ip6_hdr *ip6;
553  int ipsz;
554  struct tcphdr *tcp;
555  char *element;
556  int ret;
557  tree_cell *retc;
558 
559  ipsz = get_local_var_size_by_name (lexic, "tcp");
560 
561  if (packet == NULL)
562  {
563  nasl_perror (lexic,
564  "get_tcp_element : Error ! No valid 'tcp' argument !\n");
565  return NULL;
566  }
567 
568  ip6 = (struct ip6_hdr *) packet;
569 
570  /* valid ipv6 header check */
571  if (UNFIX (ip6->ip6_plen) > ipsz)
572  return NULL; /* Invalid packet */
573 
574  tcp = (struct tcphdr *) (packet + 40);
575 
576  element = get_str_local_var_by_name (lexic, "element");
577  if (!element)
578  {
579  nasl_perror (lexic,
580  "get_tcp_element : Error ! No valid 'element' argument !\n");
581  return NULL;
582  }
583 
584  if (!strcmp (element, "th_sport"))
585  ret = ntohs (tcp->th_sport);
586  else if (!strcmp (element, "th_dsport"))
587  ret = ntohs (tcp->th_dport);
588  else if (!strcmp (element, "th_seq"))
589  ret = ntohl (tcp->th_seq);
590  else if (!strcmp (element, "th_ack"))
591  ret = ntohl (tcp->th_ack);
592  else if (!strcmp (element, "th_x2"))
593  ret = tcp->th_x2;
594  else if (!strcmp (element, "th_off"))
595  ret = tcp->th_off;
596  else if (!strcmp (element, "th_flags"))
597  ret = tcp->th_flags;
598  else if (!strcmp (element, "th_win"))
599  ret = ntohs (tcp->th_win);
600  else if (!strcmp (element, "th_sum"))
601  ret = tcp->th_sum;
602  else if (!strcmp (element, "th_urp"))
603  ret = tcp->th_urp;
604  else if (!strcmp (element, "data"))
605  {
606  retc = alloc_tree_cell (0, NULL);
607  retc->type = CONST_DATA;
608  retc->size = UNFIX (ip6->ip6_plen) - ntohl (tcp->th_off) * 4;
609  retc->x.str_val = g_malloc0 (retc->size);
610  bcopy (tcp + ntohl (tcp->th_off) * 4, retc->x.str_val, retc->size);
611  return retc;
612  }
613  else
614  {
615  nasl_perror (lexic, "Unknown tcp field %s\n", element);
616  return NULL;
617  }
618 
619  retc = alloc_tree_cell (0, NULL);
620  retc->type = CONST_INT;
621  retc->x.i_val = ret;
622  return retc;
623 }
624 
632 tree_cell *
634 {
635  char *pkt = get_str_local_var_by_name (lexic, "tcp");
636  struct ip6_hdr *ip6 = (struct ip6_hdr *) pkt;
637  int pktsz = get_local_var_size_by_name (lexic, "tcp");
638  struct tcphdr *tcp;
639  tree_cell *retc;
640  char *data = get_str_local_var_by_name (lexic, "data");
641  int data_len = get_local_var_size_by_name (lexic, "data");
642  char *npkt;
643 
644  if (pkt == NULL)
645  {
646  nasl_perror (lexic,
647  "set_tcp_elements : Invalid value for the argument 'tcp'\n");
648  return NULL;
649  }
650 
651  tcp = (struct tcphdr *) (pkt + 40);
652 
653  if (pktsz < UNFIX (ip6->ip6_plen))
654  return NULL;
655 
656  if (data_len == 0)
657  {
658  data_len = UNFIX (ip6->ip6_plen) - (tcp->th_off * 4);
659  data = (char *) ((char *) tcp + tcp->th_off * 4);
660  }
661 
662  npkt = g_malloc0 (40 + tcp->th_off * 4 + data_len);
663  bcopy (pkt, npkt, UNFIX (ip6->ip6_plen) + 40);
664 
665  ip6 = (struct ip6_hdr *) (npkt);
666  tcp = (struct tcphdr *) (npkt + 40);
667 
668  tcp->th_sport =
670  (lexic, "th_sport", ntohs (tcp->th_sport)));
671  tcp->th_dport =
673  (lexic, "th_dport", ntohs (tcp->th_dport)));
674  tcp->th_seq =
675  htonl (get_int_local_var_by_name (lexic, "th_seq", ntohl (tcp->th_seq)));
676  tcp->th_ack =
677  htonl (get_int_local_var_by_name (lexic, "th_ack", ntohl (tcp->th_ack)));
678  tcp->th_x2 = get_int_local_var_by_name (lexic, "th_x2", tcp->th_x2);
679  tcp->th_off = get_int_local_var_by_name (lexic, "th_off", tcp->th_off);
680  tcp->th_flags = get_int_local_var_by_name (lexic, "th_flags", tcp->th_flags);
681  tcp->th_win =
682  htons (get_int_local_var_by_name (lexic, "th_win", ntohs (tcp->th_win)));
683  tcp->th_sum = get_int_local_var_by_name (lexic, "th_sum", 0);
684  tcp->th_urp = get_int_local_var_by_name (lexic, "th_urp", tcp->th_urp);
685 
686  bcopy (data, (char *) tcp + tcp->th_off * 4, data_len);
687 
688  if (get_int_local_var_by_name (lexic, "update_ip_len", 1) != 0)
689  {
690  ip6->ip6_plen = tcp->th_off * 4 + data_len;
691  }
692 
693  if (tcp->th_sum == 0)
694  {
695  struct v6pseudohdr pseudoheader;
696  char *tcpsumdata = g_malloc0 (sizeof (struct v6pseudohdr) + data_len + 1);
697 
698  bzero (&pseudoheader, 38 + sizeof (struct tcphdr));
699  memcpy (&pseudoheader.s6addr, &ip6->ip6_src, sizeof (struct in6_addr));
700  memcpy (&pseudoheader.d6addr, &ip6->ip6_dst, sizeof (struct in6_addr));
701 
702  pseudoheader.protocol = IPPROTO_TCP;
703  pseudoheader.length = htons (sizeof (struct tcphdr) + data_len);
704  bcopy ((char *) tcp, (char *) &pseudoheader.tcpheader,
705  sizeof (struct tcphdr));
706  /* fill tcpsumdata with data to checksum */
707  bcopy ((char *) &pseudoheader, tcpsumdata, sizeof (struct v6pseudohdr));
708  if (data != NULL)
709  bcopy ((char *) data, tcpsumdata + sizeof (struct v6pseudohdr),
710  data_len);
711  tcp->th_sum =
712  np_in_cksum ((unsigned short *) tcpsumdata,
713  38 + sizeof (struct tcphdr) + data_len);
714  g_free (tcpsumdata);
715  }
716 
717  retc = alloc_tree_cell (0, NULL);
718  retc->type = CONST_DATA;
719  retc->size = 40 + (tcp->th_off * 4) + data_len;
720  retc->x.str_val = npkt;
721  return retc;
722 }
723 
731 tree_cell *
733 {
734  int i = 0;
735  u_char *pkt;
736 
737  while ((pkt = (u_char *) get_str_var_by_num (lexic, i++)) != NULL)
738  {
739  int a = 0;
740  struct ip6_hdr *ip6 = (struct ip6_hdr *) pkt;
741  struct tcphdr *tcp = (struct tcphdr *) (pkt + 40);
742  int j;
743  int limit;
744  char *c;
745 
746  limit = get_var_size_by_num (lexic, i - 1);
747 
748  printf ("------\n");
749  printf ("\tth_sport : %d\n", ntohs (tcp->th_sport));
750  printf ("\tth_dport : %d\n", ntohs (tcp->th_dport));
751  printf ("\tth_seq : %u\n", (unsigned int) ntohl (tcp->th_seq));
752  printf ("\tth_ack : %u\n", (unsigned int) ntohl (tcp->th_ack));
753  printf ("\tth_x2 : %d\n", tcp->th_x2);
754  printf ("\tth_off : %d\n", tcp->th_off);
755  printf ("\tth_flags : ");
756  if (tcp->th_flags & TH_FIN)
757  {
758  printf ("TH_FIN");
759  a++;
760  }
761  if (tcp->th_flags & TH_SYN)
762  {
763  if (a)
764  printf ("|");
765  printf ("TH_SYN");
766  a++;
767  }
768  if (tcp->th_flags & TH_RST)
769  {
770  if (a)
771  printf ("|");
772  printf ("TH_RST");
773  a++;
774  }
775  if (tcp->th_flags & TH_PUSH)
776  {
777  if (a)
778  printf ("|");
779  printf ("TH_PUSH");
780  a++;
781  }
782  if (tcp->th_flags & TH_ACK)
783  {
784  if (a)
785  printf ("|");
786  printf ("TH_ACK");
787  a++;
788  }
789  if (tcp->th_flags & TH_URG)
790  {
791  if (a)
792  printf ("|");
793  printf ("TH_URG");
794  a++;
795  }
796  if (!a)
797  printf ("0");
798  else
799  printf (" (%d)", tcp->th_flags);
800  printf ("\n");
801  printf ("\tth_win : %d\n", ntohs (tcp->th_win));
802  printf ("\tth_sum : 0x%x\n", tcp->th_sum);
803  printf ("\tth_urp : %d\n", tcp->th_urp);
804  printf ("\tData : ");
805  c = (char *) ((char *) tcp + sizeof (struct tcphdr));
806  if (UNFIX (ip6->ip6_plen) >
807  (sizeof (struct ip6_hdr) + sizeof (struct tcphdr)))
808  for (j = 0;
809  j < UNFIX (ip6->ip6_plen) - sizeof (struct tcphdr) && j < limit;
810  j++)
811  printf ("%c", isprint (c[j]) ? c[j] : '.');
812  printf ("\n");
813  printf ("\n");
814  }
815  return NULL;
816 }
817 
818 /*--------------[ UDP ]--------------------------------------------*/
819 /*
820  * @brief UDP header.
821  */
822 
824 {
825  struct in6_addr s6addr;
826  struct in6_addr d6addr;
827  char proto;
828  unsigned short len;
829  struct udphdr udpheader;
830 };
831 
832 
833 /*
834  * @brief Forge v6 packet for UDP.
835  *
836  * @param[in] lexic Lexical context of NASL interpreter.
837  *
838  * @return tree_cell with the forged UDP packet containing IPv6 header.
839  */
840 tree_cell *
842 {
843  tree_cell *retc;
844  struct ip6_hdr *ip6 =
845  (struct ip6_hdr *) get_str_local_var_by_name (lexic, "ip6");
846 
847  if (ip6 != NULL)
848  {
849  char *data = get_str_local_var_by_name (lexic, "data");
850  int data_len = get_local_var_size_by_name (lexic, "data");
851  u_char *pkt;
852  struct ip6_hdr *udp_packet;
853  struct udphdr *udp;
854 
855  pkt = g_malloc0 (sizeof (struct udphdr) + 40 + data_len);
856  udp_packet = (struct ip6_hdr *) pkt;
857  udp = (struct udphdr *) (pkt + 40);
858 
859  udp->uh_sum = get_int_local_var_by_name (lexic, "uh_sum", 0);
860  bcopy ((char *) ip6, pkt, 40);
861 
862  udp->uh_sport = htons (get_int_local_var_by_name (lexic, "uh_sport", 0));
863  udp->uh_dport = htons (get_int_local_var_by_name (lexic, "uh_dport", 0));
864  udp->uh_ulen =
866  (lexic, "uh_ulen", data_len + sizeof (struct udphdr)));
867 
868  if (data_len != 0 && data != NULL)
869  bcopy (data, (pkt + 40 + sizeof (struct udphdr)), data_len);
870 
871  if (!udp->uh_sum)
872  {
874  char *udpsumdata = g_malloc0 (sizeof (struct v6pseudo_udp_hdr)
875  + data_len + 1);
876 
877  bzero (&pseudohdr, sizeof (struct v6pseudo_udp_hdr));
878  memcpy (&pseudohdr.s6addr, &ip6->ip6_src, sizeof (struct in6_addr));
879  memcpy (&pseudohdr.d6addr, &ip6->ip6_dst, sizeof (struct in6_addr));
880 
881  pseudohdr.proto = IPPROTO_UDP;
882  pseudohdr.len = htons (sizeof (struct udphdr) + data_len);
883  bcopy ((char *) udp, (char *) &pseudohdr.udpheader,
884  sizeof (struct udphdr));
885  bcopy ((char *) &pseudohdr, udpsumdata, sizeof (pseudohdr));
886  if (data != NULL)
887  {
888  bcopy ((char *) data, udpsumdata + sizeof (pseudohdr), data_len);
889  }
890  udp->uh_sum =
891  np_in_cksum ((unsigned short *) udpsumdata,
892  38 + sizeof (struct udphdr) + data_len);
893  g_free (udpsumdata);
894  }
895 
896 
897  if (UNFIX (udp_packet->ip6_ctlun.ip6_un1.ip6_un1_plen) <= 40)
898  {
899  int v = get_int_local_var_by_name (lexic, "update_ip6_len", 1);
900  if (v != 0)
901  {
902  udp_packet->ip6_ctlun.ip6_un1.ip6_un1_plen =
903  FIX (ntohs (udp->uh_ulen));
904  }
905  }
906 
907  retc = alloc_tree_cell (0, NULL);
908  retc->type = CONST_DATA;
909  retc->x.str_val = (char *) pkt;
910  retc->size = 8 + 40 + data_len;
911 
912  return retc;
913  }
914  else
915  printf ("Error ! You must supply the 'ip6' argument !\n");
916 
917  return NULL;
918 }
919 
920 
921 /*
922  * @brief Get UDP Header element.
923  *
924  * @param[in] lexic Lexical context of NASL interpreter.
925  *
926  * @return tree_cell with the forged UDP packet.
927  */
928 tree_cell *
930 {
931  tree_cell *retc;
932  char *udp;
933  char *element;
934  int ipsz;
935  struct udphdr *udphdr;
936  int ret;
937 
938  udp = get_str_local_var_by_name (lexic, "udp");
939  ipsz = get_local_var_size_by_name (lexic, "udp");
940 
941  element = get_str_local_var_by_name (lexic, "element");
942  if (udp == NULL || element == NULL)
943  {
944  printf ("get_udp_v6_element() usage :\n");
945  printf ("element = get_udp_v6_element(udp:<udp>,element:<element>\n");
946  return NULL;
947  }
948 
949  if (40 + sizeof (struct udphdr) > ipsz)
950  return NULL;
951 
952  udphdr = (struct udphdr *) (udp + 40);
953  if (!strcmp (element, "uh_sport"))
954  ret = ntohs (udphdr->uh_sport);
955  else if (!strcmp (element, "uh_dport"))
956  ret = ntohs (udphdr->uh_dport);
957  else if (!strcmp (element, "uh_ulen"))
958  ret = ntohs (udphdr->uh_ulen);
959  else if (!strcmp (element, "uh_sum"))
960  ret = ntohs (udphdr->uh_sum);
961  else if (!strcmp (element, "data"))
962  {
963  int sz;
964  retc = alloc_tree_cell (0, NULL);
965  retc->type = CONST_DATA;
966  sz = ntohs (udphdr->uh_ulen) - sizeof (struct udphdr);
967 
968  if (ntohs (udphdr->uh_ulen) - 40 - sizeof (struct udphdr) > ipsz)
969  sz = ipsz - 40 - sizeof (struct udphdr);
970 
971  retc->x.str_val = g_malloc0 (sz);
972  retc->size = sz;
973  bcopy (udp + 40 + sizeof (struct udphdr), retc->x.str_val, sz);
974  return retc;
975  }
976  else
977  {
978  printf ("%s is not a value of a udp packet\n", element);
979  return NULL;
980  }
981 
982  retc = alloc_tree_cell (0, NULL);
983  retc->type = CONST_INT;
984  retc->x.i_val = ret;
985  return retc;
986 }
987 
988 
989 /*
990  * @brief Set UDP Header element.
991  *
992  * @param[in] lexic Lexical context of NASL interpreter.
993  *
994  * @return tree_cell with the forged UDP packet and IPv6.
995  */
996 tree_cell *
998 {
999  struct ip6_hdr *ip6 =
1000  (struct ip6_hdr *) get_str_local_var_by_name (lexic, "udp");
1001  int sz = get_local_var_size_by_name (lexic, "udp");
1002  char *data = get_str_local_var_by_name (lexic, "data");
1003  int data_len = get_local_var_size_by_name (lexic, "data");
1004 
1005  if (ip6 != NULL)
1006  {
1007  char *pkt;
1008  struct udphdr *udp;
1009  tree_cell *retc;
1010  int old_len;
1011 
1012  if (40 + sizeof (struct udphdr) > sz)
1013  {
1014  return NULL;
1015  }
1016  if (data != NULL)
1017  {
1018  sz = 40 + sizeof (struct udphdr) + data_len;
1019  pkt = g_malloc0 (sz);
1020  bcopy (ip6, pkt, 40 + sizeof (struct udphdr));
1021  }
1022  else
1023  {
1024  pkt = g_malloc0 (sz);
1025  bcopy (ip6, pkt, sz);
1026  }
1027 
1028  ip6 = (struct ip6_hdr *) pkt;
1029  if (data != NULL)
1030  {
1031  ip6->ip6_ctlun.ip6_un1.ip6_un1_plen = FIX (sz - 40);
1032  }
1033  udp = (struct udphdr *) (pkt + 40);
1034 
1035  udp->uh_sport =
1037  (lexic, "uh_sport", ntohs (udp->uh_sport)));
1038  udp->uh_dport =
1040  (lexic, "uh_dport", ntohs (udp->uh_dport)));
1041 
1042  old_len = ntohs (udp->uh_ulen);
1043  udp->uh_ulen =
1045  (lexic, "uh_ulen", ntohs (udp->uh_ulen)));
1046  udp->uh_sum = get_int_local_var_by_name (lexic, "uh_sum", 0);
1047 
1048  if (data != NULL)
1049  {
1050  bcopy (data, pkt + 40 + sizeof (struct udphdr), data_len);
1051  udp->uh_ulen = htons (sizeof (struct udphdr) + data_len);
1052  }
1053 
1054  if (!udp->uh_sum)
1055  {
1056  struct v6pseudo_udp_hdr pseudohdr;
1057  int len = old_len - sizeof (struct udphdr);
1058  char *udpsumdata;
1059  char *ptr = NULL;
1060 
1061  if (data != NULL)
1062  {
1063  len = data_len;
1064  }
1065 
1066  if (len > 0)
1067  {
1068  ptr = (char *) udp + sizeof (struct udphdr);
1069  }
1070 
1071  udpsumdata = g_malloc0 (sizeof (struct v6pseudo_udp_hdr) + len + 1);
1072  bzero (&pseudohdr, sizeof (struct v6pseudo_udp_hdr));
1073 
1074  pseudohdr.proto = IPPROTO_UDP;
1075  pseudohdr.len = htons (sizeof (struct udphdr) + data_len);
1076  bcopy ((char *) udp, (char *) &pseudohdr.udpheader,
1077  sizeof (struct udphdr));
1078  memcpy (&pseudohdr.s6addr, &ip6->ip6_src, sizeof (struct in6_addr));
1079  memcpy (&pseudohdr.d6addr, &ip6->ip6_dst, sizeof (struct in6_addr));
1080  bcopy ((char *) &pseudohdr, udpsumdata, sizeof (pseudohdr));
1081  if (ptr != NULL)
1082  {
1083  bcopy ((char *) ptr, udpsumdata + sizeof (pseudohdr), data_len);
1084  }
1085  udp->uh_sum =
1086  np_in_cksum ((unsigned short *) udpsumdata,
1087  38 + sizeof (struct udphdr)
1088  + ((len % 2) ? len + 1 : len));
1089  g_free (udpsumdata);
1090  }
1091  retc = alloc_tree_cell (0, NULL);
1092  retc->type = CONST_DATA;
1093  retc->size = sz;
1094  retc->x.str_val = pkt;
1095  return retc;
1096  }
1097  else
1098  printf ("Error ! You must supply the 'udp' argument !\n");
1099 
1100  return NULL;
1101 }
1102 
1103 
1104 /*
1105  * @brief Print UDP/IPv6 packet.
1106  *
1107  * @param[in] lexic Lexical context of NASL interpreter.
1108  *
1109  * @return Print and return FAKE_CELL.
1110  */
1111 tree_cell *
1113 {
1114  int i = 0;
1115  u_char *pkt;
1116  while ((pkt = (u_char *) get_str_var_by_num (lexic, i++)) != NULL)
1117  {
1118  struct udphdr *udp = (struct udphdr *) (pkt + sizeof (struct ip6_hdr));
1119  int j;
1120  char *c;
1121  int limit = get_var_size_by_num (lexic, i - 1);
1122  printf ("------\n");
1123  printf ("\tuh_sport : %d\n", ntohs (udp->uh_sport));
1124  printf ("\tuh_dport : %d\n", ntohs (udp->uh_dport));
1125  printf ("\tuh_sum : 0x%x\n", udp->uh_sum);
1126  printf ("\tuh_ulen : %d\n", ntohs (udp->uh_ulen));
1127  printf ("\tdata : ");
1128  c = (char *) (udp + sizeof (struct udphdr));
1129  if (udp->uh_ulen > sizeof (struct udphdr))
1130  for (j = 0;
1131  j < (ntohs (udp->uh_ulen) - sizeof (struct udphdr)) && j < limit;
1132  j++)
1133  printf ("%c", isprint (c[j]) ? c[j] : '.');
1134 
1135  printf ("\n");
1136  }
1137  return NULL;
1138 }
1139 
1140 
1141 /*--------------[ ICMP ]--------------------------------------------*/
1142 /*
1143  * @brief ICMPv6 header.
1144 */
1145 
1147 {
1148  struct in6_addr s6addr;
1149  struct in6_addr d6addr;
1150  char proto;
1151  unsigned short len;
1152  struct icmp6_hdr icmpheader;
1153 };
1154 
1155 
1156 /*
1157  * @brief Forge ICMPv6 packet.
1158  *
1159  * @param[in] lexic Lexical context of NASL interpreter.
1160  *
1161  * @return tree_cell with the forged ICMPv6 packet containing IPv6 header.
1162  */
1163 tree_cell *
1165 {
1166  tree_cell *retc = NULL;
1167  struct ip6_hdr *ip6;
1168  struct ip6_hdr *ip6_icmp;
1169  int ip6_sz, size = 0, sz = 0;
1170  struct icmp6_hdr *icmp;
1171  struct nd_router_solicit *routersolicit = NULL;
1172  struct nd_router_advert *routeradvert = NULL;
1173  struct nd_neighbor_solicit *neighborsolicit = NULL;
1174  struct nd_neighbor_advert *neighboradvert = NULL;
1175 
1176  char *data, *p;
1177  int len;
1178  u_char *pkt;
1179  int t;
1180  ip6 = (struct ip6_hdr *) get_str_local_var_by_name (lexic, "ip6");
1181  ip6_sz = get_local_var_size_by_name (lexic, "ip6");
1182 
1183  if (ip6 != NULL)
1184  {
1185  retc = alloc_tree_cell (0, NULL);
1186  retc->type = CONST_DATA;
1187  data = get_str_local_var_by_name (lexic, "data");
1188  len = data == NULL ? 0 : get_var_size_by_name (lexic, "data");
1189  t = get_int_local_var_by_name (lexic, "icmp_type", 0);
1190  if (40 > ip6_sz)
1191  return NULL;
1192 
1193  /* ICMP header size is 8 */
1194  pkt = g_malloc0 (ip6_sz + 8 + len);
1195  ip6_icmp = (struct ip6_hdr *) pkt;
1196 
1197  bcopy (ip6, ip6_icmp, ip6_sz);
1198  p = (char *) (pkt + ip6_sz);
1199 
1200  icmp = (struct icmp6_hdr *) p;
1201 
1202  icmp->icmp6_code = get_int_local_var_by_name (lexic, "icmp_code", 0);
1203  icmp->icmp6_type = t;
1204 
1205  switch (t)
1206  {
1207  case ICMP6_ECHO_REQUEST:
1208  {
1209  if (data != NULL)
1210  bcopy (data, &(p[8]), len);
1211  icmp->icmp6_id = get_int_local_var_by_name (lexic, "icmp_id", 0);
1212  icmp->icmp6_seq = get_int_local_var_by_name (lexic, "icmp_seq", 0);
1213  size = ip6_sz + 8 + len;
1214  sz = 8;
1215  }
1216  break;
1217  case ND_ROUTER_SOLICIT:
1218  {
1219  if (data != NULL)
1220  bcopy (data, &(p[8]), len);
1221  routersolicit = g_malloc0 (sizeof (struct nd_router_solicit));
1222  pkt =
1223  g_realloc (pkt, ip6_sz + sizeof (struct nd_router_solicit) + len);
1224  ip6_icmp = (struct ip6_hdr *) pkt;
1225  p = (char *) (pkt + ip6_sz);
1226  struct icmp6_hdr *rs = &routersolicit->nd_rs_hdr;
1227  routersolicit = (struct nd_router_solicit *) p;
1228  rs->icmp6_type = icmp->icmp6_type;
1229  rs->icmp6_code = icmp->icmp6_code;
1230  rs->icmp6_cksum = icmp->icmp6_cksum;
1231  size = ip6_sz + sizeof (struct nd_router_solicit) + len;
1232  sz = 4; /*type-1 byte, code-1byte, cksum-2bytes */
1233  }
1234  break;
1235  case ND_ROUTER_ADVERT:
1236  {
1237  if (data != NULL)
1238  bcopy (data, &(p[8]), len);
1239  routeradvert = g_malloc0 (sizeof (struct nd_router_advert));
1240  /*do we need lifetime?? Not taking lifetime?? */
1241  pkt = g_realloc (pkt, ip6_sz + sizeof (struct nd_router_advert) - 8 + len); /*not taking lifetime(8 bytes) into consideration */
1242  ip6_icmp = (struct ip6_hdr *) pkt;
1243  p = (char *) (pkt + ip6_sz);
1244  struct icmp6_hdr *ra = &routeradvert->nd_ra_hdr;
1245  routeradvert = (struct nd_router_advert *) p;
1246  ra->icmp6_type = icmp->icmp6_type;
1247  ra->icmp6_code = icmp->icmp6_code;
1248  ra->icmp6_cksum = icmp->icmp6_cksum;
1249  routeradvert->nd_ra_reachable =
1250  get_int_local_var_by_name (lexic, "reacheable_time", 0);
1251  routeradvert->nd_ra_retransmit =
1252  get_int_local_var_by_name (lexic, "retransmit_timer", 0);
1253  routeradvert->nd_ra_curhoplimit = ip6_icmp->ip6_hlim;
1254  routeradvert->nd_ra_flags_reserved =
1255  get_int_local_var_by_name (lexic, "flags", 0);
1256  size = ip6_sz + sizeof (struct nd_router_advert) - 8 + len; /*not taking lifetime(8 bytes) into consideration */
1257  sz = 5; /*type-1 byte, code-1byte, cksum-2bytes, current hoplimit-1byte */
1258  }
1259  break;
1260  case ND_NEIGHBOR_SOLICIT:
1261  {
1262  neighborsolicit = g_malloc0 (sizeof (struct nd_neighbor_solicit));
1263  pkt =
1264  g_realloc (pkt, ip6_sz + sizeof (struct nd_neighbor_solicit) + len);
1265  ip6_icmp = (struct ip6_hdr *) pkt;
1266  p = (char *) (pkt + ip6_sz);
1267  struct icmp6_hdr *ns = &neighborsolicit->nd_ns_hdr;
1268  neighborsolicit = (struct nd_neighbor_solicit *) p;
1269  if (data != NULL)
1270  bcopy (data, &(p[24]), len);
1271  ns->icmp6_type = icmp->icmp6_type;
1272  ns->icmp6_code = icmp->icmp6_code;
1273  ns->icmp6_cksum = icmp->icmp6_cksum;
1274  memcpy (&neighborsolicit->nd_ns_target, &ip6_icmp->ip6_dst, sizeof (struct in6_addr)); /*dst ip should be link local */
1275  size = ip6_sz + sizeof (struct nd_neighbor_solicit) + len;
1276  sz = 4; /*type-1 byte, code-1byte, cksum-2bytes */
1277  }
1278  break;
1279  case ND_NEIGHBOR_ADVERT:
1280  {
1281  neighboradvert = g_malloc0 (sizeof (struct nd_neighbor_advert));
1282  pkt =
1283  g_realloc (pkt, ip6_sz + sizeof (struct nd_neighbor_advert) + len);
1284  ip6_icmp = (struct ip6_hdr *) pkt;
1285  p = (char *) (pkt + 40);
1286  struct icmp6_hdr *na = &neighboradvert->nd_na_hdr;
1287  neighboradvert = (struct nd_neighbor_advert *) p;
1288  na->icmp6_type = icmp->icmp6_type;
1289  na->icmp6_code = icmp->icmp6_code;
1290  na->icmp6_cksum = icmp->icmp6_cksum;
1291  neighboradvert->nd_na_flags_reserved =
1292  get_int_local_var_by_name (lexic, "flags", 0);
1293  if (neighboradvert->nd_na_flags_reserved & 0x00000020)
1294  memcpy (&neighboradvert->nd_na_target, &ip6_icmp->ip6_src, sizeof (struct in6_addr)); /*dst ip should be link local */
1295  else
1296  {
1297  if (get_var_size_by_name (lexic, "target") != 0)
1298  inet_pton (AF_INET6,
1299  get_str_local_var_by_name (lexic, "target"),
1300  &neighboradvert->nd_na_target);
1301  else
1302  {
1303  nasl_perror (lexic,
1304  "forge_icmp_v6_packet: missing 'target' parameter required for constructing response to a Neighbor Solicitation\n");
1305  g_free (ip6_icmp);
1306  return NULL;
1307  }
1308  }
1309  size = ip6_sz + sizeof (struct nd_neighbor_advert) + len;
1310  sz = 4; /*type-1 byte, code-1byte, cksum-2bytes */
1311  }
1312  break;
1313  default:
1314  {
1315  nasl_perror (lexic, "forge_icmp_v6_packet: unknown type\n");
1316  }
1317  }
1318 
1319  if (UNFIX (ip6_icmp->ip6_ctlun.ip6_un1.ip6_un1_plen) <= 40)
1320  {
1321  if (get_int_local_var_by_name (lexic, "update_ip_len", 1) != 0)
1322  {
1323  ip6_icmp->ip6_ctlun.ip6_un1.ip6_un1_plen = FIX (size - ip6_sz);
1324  }
1325  }
1326  if (get_int_local_var_by_name (lexic, "icmp_cksum", -1) == -1)
1327  {
1329  char *icmpsumdata = g_malloc0 (sizeof (struct v6pseudo_icmp_hdr) +
1330  len + 1);
1331 
1332  bzero (&pseudohdr, sizeof (struct v6pseudo_icmp_hdr));
1333  memcpy (&pseudohdr.s6addr, &ip6->ip6_src, sizeof (struct in6_addr));
1334  memcpy (&pseudohdr.d6addr, &ip6->ip6_dst, sizeof (struct in6_addr));
1335 
1336  pseudohdr.proto = 0x3a; /*ICMPv6 */
1337  pseudohdr.len = htons (size - ip6_sz);
1338  bcopy ((char *) icmp, (char *) &pseudohdr.icmpheader, sz);
1339  bcopy ((char *) &pseudohdr, icmpsumdata, sizeof (pseudohdr));
1340  if (data != NULL)
1341  bcopy ((char *) data, icmpsumdata + sizeof (pseudohdr), len);
1342  icmp->icmp6_cksum =
1343  np_in_cksum ((unsigned short *) icmpsumdata, size);
1344  g_free (icmpsumdata);
1345  }
1346  else
1347  icmp->icmp6_cksum =
1348  htons (get_int_local_var_by_name (lexic, "icmp_cksum", 0));
1349  switch (t)
1350  {
1351  case ICMP6_ECHO_REQUEST:
1352  break;
1353  case ND_ROUTER_SOLICIT:
1354  {
1355  routersolicit->nd_rs_hdr.icmp6_cksum = icmp->icmp6_cksum;
1356  }
1357  break;
1358  case ND_ROUTER_ADVERT:
1359  {
1360  routeradvert->nd_ra_hdr.icmp6_cksum = icmp->icmp6_cksum;
1361  }
1362  break;
1363  case ND_NEIGHBOR_SOLICIT:
1364  {
1365  neighborsolicit->nd_ns_hdr.icmp6_cksum = icmp->icmp6_cksum;
1366  }
1367  break;
1368  case ND_NEIGHBOR_ADVERT:
1369  {
1370  neighboradvert->nd_na_hdr.icmp6_cksum = icmp->icmp6_cksum;
1371  }
1372  break;
1373  default:
1374  {
1375  }
1376  }
1377 
1378  retc->x.str_val = (char *) pkt;
1379  retc->size = size;
1380  }
1381  else
1382  nasl_perror (lexic, "forge_icmp_v6_packet: missing 'ip6' parameter\n");
1383 
1384  return retc;
1385 }
1386 
1387 
1388 /*
1389  * @brief Obtain ICMPv6 header element.
1390  *
1391  * @param[in] lexic Lexical context of NASL interpreter.
1392  *
1393  * @return tree_cell with the ICMPv6 header element.
1394  */
1395 tree_cell *
1397 {
1398  struct icmp6_hdr *icmp;
1399  char *p;
1400 
1401 
1402  if ((p = get_str_local_var_by_name (lexic, "icmp")) != NULL)
1403  {
1404  char *elem = get_str_local_var_by_name (lexic, "element");
1405  int value;
1406  tree_cell *retc;
1407 
1408  icmp = (struct icmp6_hdr *) (p + 40);
1409 
1410  if (elem == NULL)
1411  return NULL;
1412 
1413  else if (!strcmp (elem, "icmp_code"))
1414  value = icmp->icmp6_code;
1415  else if (!strcmp (elem, "icmp_type"))
1416  value = icmp->icmp6_type;
1417  else if (!strcmp (elem, "icmp_cksum"))
1418  value = ntohs (icmp->icmp6_cksum);
1419  else if (!strcmp (elem, "icmp_id"))
1420  value = ntohs (icmp->icmp6_id);
1421  else if (!strcmp (elem, "icmp_seq"))
1422  value = ntohs (icmp->icmp6_seq);
1423  else if (!strcmp (elem, "data"))
1424  {
1425  retc = alloc_tree_cell (0, NULL);
1426  retc->type = CONST_DATA;
1427  retc->size = get_var_size_by_name (lexic, "icmp") - 40 - 8;
1428  if (retc->size > 0)
1429  retc->x.str_val = g_memdup (&(p[40 + 8]), retc->size + 1);
1430  else
1431  {
1432  retc->x.str_val = NULL;
1433  retc->size = 0;
1434  }
1435  return retc;
1436  }
1437  else
1438  return NULL;
1439 
1440  retc = alloc_tree_cell (0, NULL);
1441  retc->type = CONST_INT;
1442  retc->x.i_val = value;
1443  return retc;
1444  }
1445 
1446  return NULL;
1447 }
1448 
1449 
1450 /*--------------[ IGMP ]--------------------------------------------*/
1451 /*
1452  * @brief Forge v6 IGMP packet.
1453  */
1454 
1456 {
1457  unsigned char type;
1458  unsigned char code;
1459  unsigned short cksum;
1460  struct in6_addr group;
1461 };
1462 
1463 
1464 /*
1465  * @brief Forge IGMPv6 packet.
1466  *
1467  * @param[in] lexic Lexical context of NASL interpreter.
1468  *
1469  * @return tree_cell with the forged IGMPv6 packet containing IPv6 header.
1470  */
1471 tree_cell *
1473 {
1474  struct ip6_hdr *ip6 =
1475  (struct ip6_hdr *) get_str_local_var_by_name (lexic, "ip6");
1476 
1477  if (ip6 != NULL)
1478  {
1479  char *data = get_str_local_var_by_name (lexic, "data");
1480  int len = data ? get_local_var_size_by_name (lexic, "data") : 0;
1481  u_char *pkt = g_malloc0 (sizeof (struct igmp6_hdr) + 40 + len);
1482  struct ip6_hdr *ip6_igmp = (struct ip6_hdr *) pkt;
1483  struct igmp6_hdr *igmp;
1484  char *p;
1485  char *grp;
1486  tree_cell *retc;
1487  int ipsz = get_local_var_size_by_name (lexic, "ip6");
1488 
1489  bcopy (ip6, ip6_igmp, ipsz);
1490 
1491 
1492  if (UNFIX (ip6_igmp->ip6_ctlun.ip6_un1.ip6_un1_plen) <= 40)
1493  {
1494  int v = get_int_local_var_by_name (lexic, "update_ip6_len", 1);
1495  if (v != 0)
1496  {
1497  ip6_igmp->ip6_ctlun.ip6_un1.ip6_un1_plen =
1498  FIX (40 + sizeof (struct igmp6_hdr) + len);
1499  }
1500  }
1501  p = (char *) (pkt + 40);
1502  igmp = (struct igmp6_hdr *) p;
1503 
1504  igmp->code = get_int_local_var_by_name (lexic, "code", 0);
1505  igmp->type = get_int_local_var_by_name (lexic, "type", 0);
1506  grp = get_str_local_var_by_name (lexic, "group");
1507 
1508  if (grp != NULL)
1509  {
1510  inet_pton (AF_INET6, grp, &igmp->group);
1511  }
1512 
1513  igmp->cksum = np_in_cksum ((u_short *) igmp, sizeof (struct igmp6_hdr));
1514  if (data != NULL)
1515  {
1516  char *p = (char *) (pkt + 40 + sizeof (struct igmp6_hdr));
1517  bcopy (p, data, len);
1518  }
1519  retc = alloc_tree_cell (0, NULL);
1520  retc->type = CONST_DATA;
1521  retc->x.str_val = (char *) pkt;
1522  retc->size = 40 + sizeof (struct igmp6_hdr) + len;
1523  return retc;
1524  }
1525 
1526  return NULL;
1527 }
1528 
1529 
1537 /*---------------------------------------------------------------------------*/
1538 tree_cell *
1540 {
1541  int port;
1542  u_char packet[sizeof (struct ip6_hdr) + sizeof (struct tcphdr)];
1543  int soc;
1544  struct ip6_hdr *ip = (struct ip6_hdr *) packet;
1545  struct tcphdr *tcp = (struct tcphdr *) (packet + sizeof (struct ip6_hdr));
1546  struct arglist *script_infos = lexic->script_infos;
1547  struct in6_addr *dst = plug_get_host_ip (script_infos);
1548  struct in6_addr src;
1549  struct sockaddr_in6 soca;
1550  int flag = 0;
1551  int i = 0;
1552  int bpf;
1553  char filter[255];
1554  tree_cell *retc;
1555  int opt = 1;
1556  struct timeval tv;
1557  int len;
1558 
1559 #define rnd_tcp_port() (rand() % 65535 + 1024)
1560  int sports[] =
1561  { 0, 0, 0, 0, 0, 1023, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 0, 0,
1562 20, 0, 25, 0, 0, 0 };
1563  int ports[] =
1564  { 139, 135, 445, 80, 22, 515, 23, 21, 6000, 1025, 25, 111, 1028, 9100, 1029,
1565 79, 497, 548, 5000, 1917, 53, 161, 9001, 65535, 443, 113, 993, 8080, 0 };
1566  int num_ports = 0;
1567  char addr[INET6_ADDRSTRLEN];
1568 
1569  if (dst == NULL || (IN6_IS_ADDR_V4MAPPED (dst) == 1))
1570  return NULL;
1571 
1572  for (i = 0; i < sizeof (sports) / sizeof (int); i++)
1573  {
1574  if (sports[i] == 0)
1575  sports[i] = rnd_tcp_port ();
1576  }
1577 
1578  for (i = 0; ports[i]; i++)
1579  num_ports++;
1580 
1581  soc = socket (AF_INET6, SOCK_RAW, IPPROTO_RAW);
1582  if (soc < 0)
1583  return NULL;
1584 
1585  if (setsockopt (soc, IPPROTO_IPV6, IP_HDRINCL, (char *) &opt, sizeof (opt)) <
1586  0)
1587  perror ("setsockopt");
1588 
1589  port = get_int_local_var_by_name (lexic, "port", -1);
1590  if (port == -1)
1591  port = plug_get_host_open_port (script_infos);
1592  if (v6_islocalhost (dst) > 0)
1593  src = *dst;
1594  else
1595  {
1596  bzero (&src, sizeof (src));
1597  v6_routethrough (dst, &src);
1598  }
1599 
1600  snprintf (filter, sizeof (filter), "ip6 and src host %s", inet_ntop (AF_INET6, dst, addr, sizeof (addr)));
1601  bpf = init_v6_capture_device (*dst, src, filter);
1602 
1603  if (v6_islocalhost (dst) != 0)
1604  flag++;
1605  else
1606  {
1607  for (i = 0; i < sizeof (sports) / sizeof (int) && !flag; i++)
1608  {
1609  bzero (packet, sizeof (packet));
1610  /* IPv6 */
1611  int version = 0x60, tc = 0, fl = 0;
1612  ip->ip6_ctlun.ip6_un1.ip6_un1_flow = version | tc | fl;
1613  ip->ip6_nxt = 0x06, ip->ip6_hlim = 0x40, ip->ip6_src = src;
1614  ip->ip6_dst = *dst;
1615  ip->ip6_ctlun.ip6_un1.ip6_un1_plen = FIX (sizeof (struct tcphdr));
1616 
1617  /* TCP */
1618  tcp->th_sport =
1619  port ? htons (rnd_tcp_port ()) : htons (sports[i % num_ports]);
1620  tcp->th_flags = TH_SYN;
1621  tcp->th_dport = port ? htons (port) : htons (ports[i % num_ports]);
1622  tcp->th_seq = rand ();
1623  tcp->th_ack = 0;
1624  tcp->th_x2 = 0;
1625  tcp->th_off = 5;
1626  tcp->th_win = htons (512);
1627  tcp->th_urp = 0;
1628  tcp->th_sum = 0;
1629 
1630  /* CKsum */
1631  {
1632  struct v6pseudohdr pseudoheader;
1633 
1634  bzero (&pseudoheader, 38 + sizeof (struct tcphdr));
1635  memcpy (&pseudoheader.s6addr, &ip->ip6_src,
1636  sizeof (struct in6_addr));
1637  memcpy (&pseudoheader.d6addr, &ip->ip6_dst,
1638  sizeof (struct in6_addr));
1639 
1640  pseudoheader.protocol = IPPROTO_TCP;
1641  pseudoheader.length = htons (sizeof (struct tcphdr));
1642  bcopy ((char *) tcp, (char *) &pseudoheader.tcpheader,
1643  sizeof (struct tcphdr));
1644  tcp->th_sum =
1645  np_in_cksum ((unsigned short *) &pseudoheader,
1646  38 + sizeof (struct tcphdr));
1647  }
1648 
1649  bzero (&soca, sizeof (soca));
1650  soca.sin6_family = AF_INET6;
1651  soca.sin6_addr = ip->ip6_dst;
1652  sendto (soc, (const void *) ip,
1653  sizeof (struct tcphdr) + sizeof (struct ip6_hdr), 0,
1654  (struct sockaddr *) &soca, sizeof (struct sockaddr_in6));
1655  tv.tv_sec = 0;
1656  tv.tv_usec = 100000;
1657  if (bpf >= 0 && bpf_next_tv (bpf, &len, &tv))
1658  flag++;
1659  }
1660  }
1661 
1662  retc = alloc_tree_cell (0, NULL);
1663  retc->type = CONST_INT;
1664  retc->x.i_val = flag;
1665  if (bpf >= 0)
1666  bpf_close (bpf);
1667  close (soc);
1668  return retc;
1669 }
1670 
1678 tree_cell *
1680 {
1681  tree_cell *retc = FAKE_CELL;
1682  int bpf = -1;
1683  u_char *answer;
1684  int answer_sz;
1685  struct sockaddr_in6 sockaddr;
1686  char *ip = NULL;
1687  struct ip6_hdr *sip = NULL;
1688  int vi = 0, b = 0, len = 0;
1689  int soc;
1690  int use_pcap = get_int_local_var_by_name (lexic, "pcap_active", 1);
1691  int to = get_int_local_var_by_name (lexic, "pcap_timeout", 5);
1692  char *filter = get_str_local_var_by_name (lexic, "pcap_filter");
1693  int dfl_len = get_int_local_var_by_name (lexic, "length", -1);
1694  struct arglist *script_infos = lexic->script_infos;
1695  struct in6_addr *dstip = plug_get_host_ip (script_infos);
1696  int offset = 1;
1697  char name[INET6_ADDRSTRLEN];
1698 
1699  if (dstip == NULL || (IN6_IS_ADDR_V4MAPPED (dstip) == 1))
1700  return NULL;
1701  soc = socket (AF_INET6, SOCK_RAW, IPPROTO_RAW);
1702  if (soc < 0)
1703  return NULL;
1704 
1705  if (setsockopt
1706  (soc, IPPROTO_IPV6, IP_HDRINCL, (char *) &offset, sizeof (offset)) < 0)
1707  perror ("setsockopt");
1708  while ((ip = get_str_var_by_num (lexic, vi)) != NULL)
1709  {
1710  int sz = get_var_size_by_num (lexic, vi);
1711  vi++;
1712 
1713  if (sz < sizeof (struct ip6_hdr))
1714  {
1715  nasl_perror (lexic, "send_packet(): packet is too short!\n");
1716  continue;
1717  }
1718 
1719  sip = (struct ip6_hdr *) ip;
1720  if (use_pcap != 0 && bpf < 0)
1721  bpf = init_v6_capture_device (sip->ip6_dst, sip->ip6_src, filter);
1722 
1723  bzero (&sockaddr, sizeof (struct sockaddr_in6));
1724  sockaddr.sin6_family = AF_INET6;
1725  sockaddr.sin6_addr = sip->ip6_dst;
1726  if (dstip != NULL && !IN6_ARE_ADDR_EQUAL (&sockaddr.sin6_addr, dstip))
1727  {
1728  char txt1[64], txt2[64];
1729  strncpy (txt1,
1730  inet_ntop (AF_INET6, &sockaddr.sin6_addr, name,
1731  INET6_ADDRSTRLEN), sizeof (txt1));
1732  txt1[sizeof (txt1) - 1] = '\0';
1733  strncpy (txt2, inet_ntop (AF_INET6, dstip, name, INET6_ADDRSTRLEN),
1734  sizeof (txt2));
1735  txt2[sizeof (txt2) - 1] = '\0';
1736  nasl_perror (lexic,
1737  "send_packet: malicious or buggy script is trying to send packet to %s instead of designated target %s\n",
1738  txt1, txt2);
1739  if (bpf >= 0)
1740  bpf_close (bpf);
1741  close (soc);
1742  return NULL;
1743  }
1744 
1745  if (dfl_len > 0 && dfl_len < sz)
1746  len = dfl_len;
1747  else
1748  len = sz;
1749 
1750  b =
1751  sendto (soc, (u_char *) ip, len, 0, (struct sockaddr *) &sockaddr,
1752  sizeof (struct sockaddr_in6));
1753  /* if(b < 0) perror("sendto "); */
1754  if (b >= 0 && use_pcap != 0 && bpf >= 0)
1755  {
1756  if (v6_islocalhost (&sip->ip6_dst))
1757  {
1758  answer = (u_char *) capture_next_v6_packet (bpf, to, &answer_sz);
1759  while (answer != NULL
1760  &&
1761  (!memcmp (answer, (char *) ip, sizeof (struct ip6_hdr))))
1762  {
1763  g_free (answer);
1764  answer =
1765  (u_char *) capture_next_v6_packet (bpf, to, &answer_sz);
1766  }
1767  }
1768  else
1769  {
1770  answer = (u_char *) capture_next_v6_packet (bpf, to, &answer_sz);
1771  }
1772  if (answer)
1773  {
1774  retc = alloc_tree_cell (0, NULL);
1775  retc->type = CONST_DATA;
1776  retc->x.str_val = (char *) answer;
1777  retc->size = answer_sz;
1778  break;
1779  }
1780  }
1781  }
1782  if (bpf >= 0)
1783  bpf_close (bpf);
1784  close (soc);
1785  return retc;
1786 }
unsigned char type
#define FAKE_CELL
Definition: nasl_tree.h:120
int v6_islocalhost(struct in6_addr *addr)
Tests whether a packet sent to IP is LIKELY to route through the kernel localhost interface.
Definition: pcap.c:378
unsigned char code
tree_cell * set_udp_v6_elements(lex_ctxt *lexic)
tree_cell * forge_igmp_v6_packet(lex_ctxt *lexic)
tree_cell * get_ipv6_element(lex_ctxt *lexic)
Obtain IPv6 header element.
char * v6_routethrough(struct in6_addr *dest, struct in6_addr *source)
An awesome function to determine what interface a packet to a given destination should be routed thro...
Definition: pcap.c:1061
struct in6_addr d6addr
tree_cell * get_tcp_v6_element(lex_ctxt *lexic)
Get TCP Header element.
unsigned short cksum
tree_cell * set_tcp_v6_elements(lex_ctxt *lexic)
Set TCP Header element.
short type
Definition: nasl_tree.h:107
char * str_val
Definition: nasl_tree.h:113
tree_cell * insert_ipv6_options(lex_ctxt *lexic)
tree_cell * nasl_send_v6packet(lex_ctxt *lexic)
Send forged IPv6 Packet.
tree_cell * forge_tcp_v6_packet(lex_ctxt *lexic)
Forge TCP packet.
#define rnd_tcp_port()
struct icmp6_hdr icmpheader
struct in6_addr group
void bpf_close(int bpf)
Definition: bpf_share.c:153
long int get_int_local_var_by_name(lex_ctxt *, const char *, int)
Definition: nasl_var.c:1240
tree_cell * get_icmp_v6_element(lex_ctxt *lexic)
int get_local_var_size_by_name(lex_ctxt *, const char *)
Definition: nasl_var.c:1298
char * get_str_local_var_by_name(lex_ctxt *, const char *)
Definition: nasl_var.c:1262
union TC::@7 x
struct in_addr group
tree_cell * forge_udp_v6_packet(lex_ctxt *lexic)
tree_cell * set_ipv6_elements(lex_ctxt *lexic)
Set IPv6 header element.
Definition: nasl_tree.h:105
unsigned char code
int get_var_size_by_num(lex_ctxt *, int)
Definition: nasl_var.c:1305
struct in6_addr * plug_get_host_ip(struct arglist *desc)
Definition: plugutils.c:216
tree_cell * forge_ipv6_packet(lex_ctxt *lexic)
Forge IPv6 packet.
const char * name
Definition: nasl_init.c:524
tree_cell * get_udp_v6_element(lex_ctxt *lexic)
#define FIX(n)
void nasl_perror(lex_ctxt *lexic, char *msg,...)
Definition: nasl_debug.c:94
char * get_str_var_by_num(lex_ctxt *, int)
Definition: nasl_var.c:1248
tree_cell * nasl_tcp_v6_ping(lex_ctxt *lexic)
Performs TCP Connect to test if host is alive.
struct timeval timeval(unsigned long val)
struct in6_addr s6addr
tree_cell * dump_ipv6_packet(lex_ctxt *lexic)
Print IPv6 Header.
int init_v6_capture_device(struct in6_addr src, struct in6_addr dst, char *filter)
long int i_val
Definition: nasl_tree.h:114
tree_cell * alloc_tree_cell(int lnb, char *s)
Definition: nasl_tree.c:37
struct ip6_hdr * capture_next_v6_packet(int bpf, int timeout, int *sz)
unsigned short cksum
unsigned int plug_get_host_open_port(struct arglist *desc)
Definition: plugutils.c:917
tree_cell * forge_icmp_v6_packet(lex_ctxt *lexic)
struct arglist * script_infos
Definition: nasl_lex_ctxt.h:39
u_char * bpf_next_tv(int bpf, int *caplen, struct timeval *tv)
Definition: bpf_share.c:104
tree_cell * dump_tcp_v6_packet(lex_ctxt *lexic)
Print TCP/IPv6 packet.
#define code
#define UNFIX(n)
struct tcphdr tcpheader
unsigned char type
int get_var_size_by_name(lex_ctxt *, const char *)
Definition: nasl_var.c:1291
int size
Definition: nasl_tree.h:110
tree_cell * dump_udp_v6_packet(lex_ctxt *lexic)