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