1  #include <stdio.h>
       2  #include <string.h>
       3  #include <arpa/inet.h>
       4  #include <netinet/ip6.h>
       5  
       6  static int
       7  do_test (void)
       8  {
       9    int res = 0;
      10    char buf[1000];
      11    void *p = inet6_rth_init (buf, 24, IPV6_RTHDR_TYPE_0, 0);
      12    if (p == NULL)
      13      {
      14        puts ("first inet6_rth_init failed");
      15        res = 1;
      16      }
      17    else if (inet6_rth_add (p, &in6addr_any) == 0)
      18      {
      19        puts ("first inet6_rth_add succeeded");
      20        res = 1;
      21      }
      22  
      23    p = inet6_rth_init (buf, 24, IPV6_RTHDR_TYPE_0, 1);
      24    if (p == NULL)
      25      {
      26        puts ("second inet6_rth_init failed");
      27        res = 1;
      28      }
      29    else if (inet6_rth_add (p, &in6addr_any) != 0)
      30      {
      31        puts ("second inet6_rth_add failed");
      32        res = 1;
      33      }
      34  
      35    for (int nseg = 4; nseg < 6; ++nseg)
      36      {
      37        printf ("nseg = %d\n", nseg);
      38  
      39        p = inet6_rth_init (buf, sizeof (buf), IPV6_RTHDR_TYPE_0, nseg);
      40        if (p == NULL)
      41  	{
      42  	  puts ("third inet6_rth_init failed");
      43  	  res = 1;
      44  	}
      45        else
      46  	{
      47  	  struct in6_addr tmp;
      48  	  memset (&tmp, '\0', sizeof (tmp));
      49  
      50  	  for (int i = 0; i < nseg; ++i)
      51  	    {
      52  	      tmp.s6_addr[0] = i;
      53  	      if (inet6_rth_add (p, &tmp) != 0)
      54  		{
      55  		  printf ("call %d of third inet6_rth_add failed\n", i + 1);
      56  		  res = 1;
      57  		  goto out;
      58  		}
      59  	    }
      60  	  ((struct ip6_rthdr0 *) p)->ip6r0_segleft = 0;
      61  	  if (inet6_rth_segments (p) != nseg)
      62  	    {
      63  	      puts ("\
      64  inet6_rth_segments returned wrong value after loop with third inet6_rth_add");
      65  	      res = 1;
      66  	      goto out;
      67  	    }
      68  
      69            union
      70            {
      71              char buffer[1000];
      72              struct ip6_rthdr0 rthdr0;
      73            } buf2;
      74  	  if (inet6_rth_reverse (p, buf2.buffer) != 0)
      75  	    {
      76  	      puts ("first inet6_rth_reverse call failed");
      77  	      res = 1;
      78  	      goto out;
      79  	    }
      80  	  if (buf2.rthdr0.ip6r0_segleft != nseg)
      81  	    {
      82  	      puts ("segleft after first inet6_rth_reverse wrong");
      83  	      res = 1;
      84  	    }
      85  
      86  	  if (inet6_rth_segments (p) != inet6_rth_segments (buf2.buffer))
      87  	    {
      88  	      puts ("number of seconds after first inet6_rth_reverse differs");
      89  	      res = 1;
      90  	      goto out;
      91  	    }
      92  
      93  	  for (int i = 0; i < nseg; ++i)
      94  	    {
      95  	      struct in6_addr *addr = inet6_rth_getaddr (buf2.buffer, i);
      96  	      if (addr == NULL)
      97  		{
      98  		  printf ("call %d of first inet6_rth_getaddr failed\n",
      99  			  i + 1);
     100  		  res = 1;
     101  		}
     102  	      else if (addr->s6_addr[0] != nseg - 1 - i
     103  		       || memcmp (&addr->s6_addr[1], &in6addr_any.s6_addr[1],
     104  				  sizeof (in6addr_any)
     105  				  - sizeof (in6addr_any.s6_addr[0])) != 0)
     106  		{
     107  		  char addrbuf[100];
     108  		  inet_ntop (AF_INET6, addr, addrbuf, sizeof (addrbuf));
     109  		  printf ("\
     110  address %d after first inet6_rth_reverse wrong (%s)\n",
     111  			  i + 1, addrbuf);
     112  		  res = 1;
     113  		}
     114  	    }
     115  	out:
     116  	  ;
     117  	}
     118  
     119        p = inet6_rth_init (buf, sizeof (buf), IPV6_RTHDR_TYPE_0, nseg);
     120        if (p == NULL)
     121  	{
     122  	  puts ("fourth inet6_rth_init failed");
     123  	  res = 1;
     124  	}
     125        else
     126  	{
     127  	  struct in6_addr tmp;
     128  	  memset (&tmp, '\0', sizeof (tmp));
     129  
     130  	  for (int i = 0; i < nseg; ++i)
     131  	    {
     132  	      tmp.s6_addr[0] = i;
     133  	      if (inet6_rth_add (p, &tmp) != 0)
     134  		{
     135  		  printf ("call %d of fourth inet6_rth_add failed\n", i + 1);
     136  		  res = 1;
     137  		  goto out2;
     138  		}
     139  	    }
     140  	  ((struct ip6_rthdr0 *) p)->ip6r0_segleft = 0;
     141  	  if (inet6_rth_segments (p) != nseg)
     142  	    {
     143  	      puts ("\
     144  inet6_rth_segments returned wrong value after loop with fourth inet6_rth_add");
     145  	      res = 1;
     146  	      goto out2;
     147  	    }
     148  
     149  	  if (inet6_rth_reverse (p, p) != 0)
     150  	    {
     151  	      puts ("second inet6_rth_reverse call failed");
     152  	      res = 1;
     153  	      goto out2;
     154  	    }
     155  	  if (((struct ip6_rthdr0 *) p)->ip6r0_segleft != nseg)
     156  	    {
     157  	      puts ("segleft after second inet6_rth_reverse wrong");
     158  	      res = 1;
     159  	    }
     160  
     161  	  for (int i = 0; i < nseg; ++i)
     162  	    {
     163  	      struct in6_addr *addr = inet6_rth_getaddr (p, i);
     164  	      if (addr == NULL)
     165  		{
     166  		  printf ("call %d of second inet6_rth_getaddr failed\n",
     167  			  i + 1);
     168  		  res = 1;
     169  		}
     170  	      else if (addr->s6_addr[0] != nseg - 1 - i
     171  		       || memcmp (&addr->s6_addr[1], &in6addr_any.s6_addr[1],
     172  				  sizeof (in6addr_any)
     173  				  - sizeof (in6addr_any.s6_addr[0])) != 0)
     174  		{
     175  		  char addrbuf[100];
     176  		  inet_ntop (AF_INET6, addr, addrbuf, sizeof (addrbuf));
     177  		  printf ("\
     178  address %d after second inet6_rth_reverse wrong (%s)\n",
     179  			  i + 1, addrbuf);
     180  		  res = 1;
     181  		}
     182  	    }
     183  	out2:
     184  	  ;
     185  	}
     186      }
     187  
     188    return res;
     189  }
     190  
     191  #define TEST_FUNCTION do_test ()
     192  #include "../test-skeleton.c"