mirror of
				https://sourceware.org/git/glibc.git
				synced 2025-10-30 10:45:40 +03:00 
			
		
		
		
	2007-03-15 Jakub Jelinek <jakub@redhat.com> [BZ #4181] * inet/inet6_opt.c (add_padding): Only insert padding if npad > 0. (inet6_opt_append): Don't check extlen is big enough if extbuf is NULL. (inet6_opt_finish): Likewise. * inet/Makefile (tests): Add test-inet6_opt. * inet/test-inet6_opt.c: New test. * sysdeps/unix/sysv/linux/ifaddrs.c (__netlink_request): Never reallocate the buffer, instead fail for MSG_TRUNC or for EBUSY NLMSG_ERR. Instead use a page sized buffer. * sysdeps/unix/sysv/linux/check_pf.c (make_request): Use page sized buffer.
		
			
				
	
	
		
			208 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			208 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include <netinet/in.h>
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| 
 | |
| #define OPT_X	42
 | |
| #define OPT_Y	43
 | |
| #define OPT_Z	44
 | |
| 
 | |
| static void *
 | |
| encode_inet6_opt (socklen_t *elp)
 | |
| {
 | |
|   void *eb = NULL;
 | |
|   socklen_t el;
 | |
|   int cl;
 | |
|   void *db;
 | |
|   int offset;
 | |
|   uint8_t val1;
 | |
|   uint16_t val2;
 | |
|   uint32_t val4;
 | |
|   uint64_t val8;
 | |
| 
 | |
|   *elp = 0;
 | |
| #define CHECK() \
 | |
|   if (cl == -1)						\
 | |
|     {							\
 | |
|       printf ("cl == -1 on line %d\n", __LINE__);	\
 | |
|       free (eb);					\
 | |
|       return NULL;					\
 | |
|     }
 | |
| 
 | |
|   /* Estimate the length */
 | |
|   cl = inet6_opt_init (NULL, 0);
 | |
|   CHECK ();
 | |
|   cl = inet6_opt_append (NULL, 0, cl, OPT_X, 12, 8, NULL);
 | |
|   CHECK ();
 | |
|   cl = inet6_opt_append (NULL, 0, cl, OPT_Y, 7, 4, NULL);
 | |
|   CHECK ();
 | |
|   cl = inet6_opt_append (NULL, 0, cl, OPT_Z, 7, 1, NULL);
 | |
|   CHECK ();
 | |
|   cl = inet6_opt_finish (NULL, 0, cl);
 | |
|   CHECK ();
 | |
|   el = cl;
 | |
| 
 | |
|   eb = malloc (el + 8);
 | |
|   if (eb == NULL)
 | |
|     {
 | |
|       puts ("malloc failed");
 | |
|       return NULL;
 | |
|     }
 | |
|   /* Canary.  */
 | |
|   memcpy (eb + el, "deadbeef", 8);
 | |
| 
 | |
|   cl = inet6_opt_init (eb, el);
 | |
|   CHECK ();
 | |
| 
 | |
|   cl = inet6_opt_append (eb, el, cl, OPT_X, 12, 8, &db);
 | |
|   CHECK ();
 | |
|   val4 = 0x12345678;
 | |
|   offset = inet6_opt_set_val (db, 0, &val4, sizeof  (val4));
 | |
|   val8 = 0x0102030405060708LL;
 | |
|   inet6_opt_set_val (db, offset, &val8, sizeof  (val8));
 | |
| 
 | |
|   cl = inet6_opt_append (eb, el, cl, OPT_Y, 7, 4, &db);
 | |
|   CHECK ();
 | |
|   val1 = 0x01;
 | |
|   offset = inet6_opt_set_val (db, 0, &val1, sizeof  (val1));
 | |
|   val2 = 0x1331;
 | |
|   offset = inet6_opt_set_val (db, offset, &val2, sizeof  (val2));
 | |
|   val4 = 0x01020304;
 | |
|   inet6_opt_set_val (db, offset, &val4, sizeof  (val4));
 | |
| 
 | |
|   cl = inet6_opt_append (eb, el, cl, OPT_Z, 7, 1, &db);
 | |
|   CHECK ();
 | |
|   inet6_opt_set_val (db, 0, (void *) "abcdefg", 7);
 | |
| 
 | |
|   cl = inet6_opt_finish (eb, el, cl);
 | |
|   CHECK ();
 | |
| 
 | |
|   if (memcmp (eb + el, "deadbeef", 8) != 0)
 | |
|     {
 | |
|       puts ("Canary corrupted");
 | |
|       free (eb);
 | |
|       return NULL;
 | |
|     }
 | |
|   *elp = el;
 | |
|   return eb;
 | |
| }
 | |
| 
 | |
| int
 | |
| decode_inet6_opt (void *eb, socklen_t el)
 | |
| {
 | |
|   int ret = 0;
 | |
|   int seq = 0;
 | |
|   int cl = 0;
 | |
|   int offset;
 | |
|   uint8_t type;
 | |
|   socklen_t len;
 | |
|   uint8_t val1;
 | |
|   uint16_t val2;
 | |
|   uint32_t val4;
 | |
|   uint64_t val8;
 | |
|   void *db;
 | |
|   char buf[8];
 | |
| 
 | |
|   while ((cl = inet6_opt_next (eb, el, cl, &type, &len, &db)) != -1)
 | |
|     switch (type)
 | |
|       {
 | |
|       case OPT_X:
 | |
| 	if (seq++ != 0)
 | |
| 	  {
 | |
| 	    puts ("OPT_X is not first");
 | |
| 	    ret = 1;
 | |
| 	  }
 | |
| 	if (len != 12)
 | |
| 	  {
 | |
| 	    printf ("OPT_X's length %d != 12\n", len);
 | |
| 	    ret = 1;
 | |
| 	  }
 | |
| 	offset = inet6_opt_get_val (db, 0, &val4, sizeof (val4));
 | |
| 	if (val4 != 0x12345678)
 | |
| 	  {
 | |
| 	    printf ("OPT_X's val4 %x != 0x12345678\n", val4);
 | |
| 	    ret = 1;
 | |
| 	  }
 | |
| 	offset = inet6_opt_get_val (db, offset, &val8, sizeof (val8));
 | |
| 	if (offset != len || val8 != 0x0102030405060708LL)
 | |
| 	  {
 | |
| 	    printf ("OPT_X's val8 %llx != 0x0102030405060708\n",
 | |
| 		    (long long) val8);
 | |
| 	    ret = 1;
 | |
| 	  }
 | |
| 	break;
 | |
|       case OPT_Y:
 | |
| 	if (seq++ != 1)
 | |
| 	  {
 | |
| 	    puts ("OPT_Y is not second");
 | |
| 	    ret = 1;
 | |
| 	  }
 | |
| 	if (len != 7)
 | |
| 	  {
 | |
| 	    printf ("OPT_Y's length %d != 7\n", len);
 | |
| 	    ret = 1;
 | |
| 	  }
 | |
| 	offset = inet6_opt_get_val (db, 0, &val1, sizeof (val1));
 | |
| 	if (val1 != 0x01)
 | |
| 	  {
 | |
| 	    printf ("OPT_Y's val1 %x != 0x01\n", val1);
 | |
| 	    ret = 1;
 | |
| 	  }
 | |
| 	offset = inet6_opt_get_val (db, offset, &val2, sizeof (val2));
 | |
| 	if (val2 != 0x1331)
 | |
| 	  {
 | |
| 	    printf ("OPT_Y's val2 %x != 0x1331\n", val2);
 | |
| 	    ret = 1;
 | |
| 	  }
 | |
| 	offset = inet6_opt_get_val (db, offset, &val4, sizeof (val4));
 | |
| 	if (offset != len || val4 != 0x01020304)
 | |
| 	  {
 | |
| 	    printf ("OPT_Y's val4 %x != 0x01020304\n", val4);
 | |
| 	    ret = 1;
 | |
| 	  }
 | |
| 	break;
 | |
|       case OPT_Z:
 | |
| 	if (seq++ != 2)
 | |
| 	  {
 | |
| 	    puts ("OPT_Z is not third");
 | |
| 	    ret = 1;
 | |
| 	  }
 | |
| 	if (len != 7)
 | |
| 	  {
 | |
| 	    printf ("OPT_Z's length %d != 7\n", len);
 | |
| 	    ret = 1;
 | |
| 	  }
 | |
| 	offset = inet6_opt_get_val (db, 0, buf, 7);
 | |
| 	if (offset != len || memcmp (buf, "abcdefg", 7) != 0)
 | |
| 	  {
 | |
| 	    buf[7] = '\0';
 | |
| 	    printf ("OPT_Z's buf \"%s\" != \"abcdefg\"\n", buf);
 | |
| 	    ret = 1;
 | |
| 	  }
 | |
| 	break;
 | |
|       default:
 | |
| 	printf ("Unknown option %d\n", type);
 | |
| 	ret = 1;
 | |
| 	break;
 | |
|       }
 | |
|   if (seq != 3)
 | |
|     {
 | |
|       puts ("Didn't see all of OPT_X, OPT_Y and OPT_Z");
 | |
|       ret = 1;
 | |
|     }
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| int
 | |
| main (void)
 | |
| {
 | |
|   void *eb;
 | |
|   socklen_t el;
 | |
|   eb = encode_inet6_opt (&el);
 | |
|   if (eb == NULL)
 | |
|     return 1;
 | |
|   if (decode_inet6_opt (eb, el))
 | |
|     return 1;
 | |
|   return 0;
 | |
| }
 |