2016-07-06 18:49:23 +03:00
/*
* Check decoding of netlink protocol .
*
2017-04-17 07:37:41 +03:00
* Copyright ( c ) 2014 - 2017 Dmitry V . Levin < ldv @ altlinux . org >
2016-07-06 18:49:23 +03:00
* Copyright ( c ) 2016 Fabien Siron < fabien . siron @ epita . fr >
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* 2. Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ` ` AS IS ' ' AND ANY EXPRESS OR
* IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED .
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT , INDIRECT ,
* INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT
* NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
* DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*/
# include "tests.h"
2016-07-21 21:18:40 +03:00
# ifdef HAVE_SYS_XATTR_H
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <unistd.h>
# include <sys / xattr.h>
# include <netinet / in.h>
2017-06-25 03:40:29 +03:00
# include "netlink.h"
2016-07-21 21:18:40 +03:00
# include <linux / sock_diag.h>
# include <linux / netlink_diag.h>
2016-07-06 18:49:23 +03:00
static void
send_query ( const int fd )
{
2016-07-07 12:49:26 +03:00
static const struct req {
2016-07-06 18:49:23 +03:00
struct nlmsghdr nlh ;
2016-07-07 12:49:26 +03:00
const char magic [ 4 ] ;
} c_req = {
2016-07-06 18:49:23 +03:00
. nlh = {
2016-07-07 12:49:26 +03:00
. nlmsg_len = sizeof ( struct req ) ,
2016-07-06 18:49:23 +03:00
. nlmsg_type = NLMSG_NOOP ,
. nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST
} ,
. magic = " abcd "
} ;
2016-07-07 12:49:26 +03:00
struct req * const req = tail_memdup ( & c_req , sizeof ( c_req ) ) ;
2016-09-20 15:02:06 +03:00
long rc ;
const char * errstr ;
2016-07-07 12:49:26 +03:00
/* zero address */
2016-09-20 15:02:06 +03:00
rc = sendto ( fd , NULL , sizeof ( * req ) , MSG_DONTWAIT , NULL , 0 ) ;
printf ( " sendto(%d, NULL, %u, MSG_DONTWAIT, NULL, 0) = %s \n " ,
fd , ( unsigned ) sizeof ( * req ) , sprintrc ( rc ) ) ;
2016-07-07 12:49:26 +03:00
/* zero length */
2016-09-20 15:02:06 +03:00
rc = sendto ( fd , req , 0 , MSG_DONTWAIT , NULL , 0 ) ;
printf ( " sendto(%d, \" \" , 0, MSG_DONTWAIT, NULL, 0) = %s \n " ,
fd , sprintrc ( rc ) ) ;
2016-07-07 12:49:26 +03:00
/* zero address and length */
2016-09-20 15:02:06 +03:00
rc = sendto ( fd , NULL , 0 , MSG_DONTWAIT , NULL , 0 ) ;
printf ( " sendto(%d, NULL, 0, MSG_DONTWAIT, NULL, 0) = %s \n " ,
fd , sprintrc ( rc ) ) ;
2016-07-06 18:49:23 +03:00
2016-07-07 12:49:26 +03:00
/* unfetchable struct nlmsghdr */
2016-07-06 18:49:23 +03:00
const void * const efault = tail_alloc ( sizeof ( struct nlmsghdr ) - 1 ) ;
2016-09-20 15:02:06 +03:00
rc = sendto ( fd , efault , sizeof ( struct nlmsghdr ) , MSG_DONTWAIT , NULL , 0 ) ;
printf ( " sendto(%d, %p, %u, MSG_DONTWAIT, NULL, 0) = %s \n " ,
fd , efault , ( unsigned ) sizeof ( struct nlmsghdr ) , sprintrc ( rc ) ) ;
2016-07-07 12:49:26 +03:00
/* whole message length < sizeof(struct nlmsghdr) */
2016-09-20 15:02:06 +03:00
rc = sendto ( fd , req - > magic , sizeof ( req - > magic ) , MSG_DONTWAIT , NULL , 0 ) ;
2017-07-07 04:44:09 +03:00
printf ( " sendto(%d, \" \\ x61 \\ x62 \\ x63 \\ x64 \" "
" , %u, MSG_DONTWAIT, NULL, 0) = %s \n " ,
2016-09-20 15:02:06 +03:00
fd , ( unsigned ) sizeof ( req - > magic ) , sprintrc ( rc ) ) ;
2016-07-07 12:49:26 +03:00
/* a single message with some data */
2016-09-20 15:02:06 +03:00
rc = sendto ( fd , req , sizeof ( * req ) , MSG_DONTWAIT , NULL , 0 ) ;
2016-07-06 18:49:23 +03:00
printf ( " sendto(%d, {{len=%u, type=NLMSG_NOOP, flags=NLM_F_REQUEST|0x%x "
2017-07-07 04:34:59 +03:00
" , seq=0, pid=0}, \" \\ x61 \\ x62 \\ x63 \\ x64 \" } "
" , %u, MSG_DONTWAIT, NULL, 0) = %s \n " ,
2016-07-07 12:49:26 +03:00
fd , req - > nlh . nlmsg_len , NLM_F_DUMP ,
2016-09-20 15:02:06 +03:00
( unsigned ) sizeof ( * req ) , sprintrc ( rc ) ) ;
2016-07-06 18:49:23 +03:00
2016-07-07 12:49:26 +03:00
/* a single message without data */
req - > nlh . nlmsg_len = sizeof ( req - > nlh ) ;
2016-09-20 15:02:06 +03:00
rc = sendto ( fd , & req - > nlh , sizeof ( req - > nlh ) , MSG_DONTWAIT , NULL , 0 ) ;
2017-06-19 00:43:39 +03:00
printf ( " sendto(%d, {len=%u, type=NLMSG_NOOP, flags=NLM_F_REQUEST|0x%x "
" , seq=0, pid=0}, %u, MSG_DONTWAIT, NULL, 0) = %s \n " ,
2016-07-07 12:49:26 +03:00
fd , req - > nlh . nlmsg_len , NLM_F_DUMP ,
2016-09-20 15:02:06 +03:00
( unsigned ) sizeof ( req - > nlh ) , sprintrc ( rc ) ) ;
2016-07-06 18:49:23 +03:00
2016-07-07 12:49:26 +03:00
/* nlmsg_len > whole message length */
req - > nlh . nlmsg_len = sizeof ( * req ) + 8 ;
2016-09-20 15:02:06 +03:00
rc = sendto ( fd , req , sizeof ( * req ) , MSG_DONTWAIT , NULL , 0 ) ;
2016-07-07 12:49:26 +03:00
printf ( " sendto(%d, {{len=%u, type=NLMSG_NOOP, flags=NLM_F_REQUEST|0x%x "
2017-07-07 04:34:59 +03:00
" , seq=0, pid=0}, \" \\ x61 \\ x62 \\ x63 \\ x64 \" } "
" , %u, MSG_DONTWAIT, NULL, 0) = %s \n " ,
2016-07-07 12:49:26 +03:00
fd , req - > nlh . nlmsg_len , NLM_F_DUMP ,
2016-09-20 15:02:06 +03:00
( unsigned ) sizeof ( * req ) , sprintrc ( rc ) ) ;
2016-07-08 19:01:49 +03:00
/* nlmsg_len < sizeof(struct nlmsghdr) */
req - > nlh . nlmsg_len = 8 ;
2016-09-20 15:02:06 +03:00
rc = sendto ( fd , req , sizeof ( * req ) , MSG_DONTWAIT , NULL , 0 ) ;
2017-06-19 00:43:39 +03:00
printf ( " sendto(%d, {len=%u, type=NLMSG_NOOP, flags=NLM_F_REQUEST|0x%x "
" , seq=0, pid=0}, %u, MSG_DONTWAIT, NULL, 0) = %s \n " ,
2016-07-08 19:01:49 +03:00
fd , req - > nlh . nlmsg_len , NLM_F_DUMP ,
2016-09-20 15:02:06 +03:00
( unsigned ) sizeof ( * req ) , sprintrc ( rc ) ) ;
2016-07-08 19:01:49 +03:00
/* a sequence of two nlmsg objects */
struct reqs {
struct req req1 ;
char padding [ NLMSG_ALIGN ( sizeof ( struct req ) ) - sizeof ( struct req ) ] ;
struct req req2 ;
} * const reqs = tail_alloc ( sizeof ( * reqs ) ) ;
memcpy ( & reqs - > req1 , & c_req , sizeof ( c_req ) ) ;
memcpy ( & reqs - > req2 , & c_req , sizeof ( c_req ) ) ;
2016-09-20 15:02:06 +03:00
rc = sendto ( fd , reqs , sizeof ( * reqs ) , MSG_DONTWAIT , NULL , 0 ) ;
2016-07-08 19:01:49 +03:00
printf ( " sendto(%d, [{{len=%u, type=NLMSG_NOOP, flags=NLM_F_REQUEST|0x%x "
2017-07-07 04:34:59 +03:00
" , seq=0, pid=0}, \" \\ x61 \\ x62 \\ x63 \\ x64 \" } "
" , {{len=%u, type=NLMSG_NOOP, flags=NLM_F_REQUEST|0x%x "
" , seq=0, pid=0}, \" \\ x61 \\ x62 \\ x63 \\ x64 \" }] "
2016-09-20 15:02:06 +03:00
" , %u, MSG_DONTWAIT, NULL, 0) = %s \n " ,
2016-07-08 19:01:49 +03:00
fd , reqs - > req1 . nlh . nlmsg_len , NLM_F_DUMP ,
reqs - > req2 . nlh . nlmsg_len , NLM_F_DUMP ,
2016-09-20 15:02:06 +03:00
( unsigned ) sizeof ( * reqs ) , sprintrc ( rc ) ) ;
2016-07-08 19:01:49 +03:00
/* unfetchable second struct nlmsghdr */
void * const efault2 = tail_memdup ( & reqs - > req1 , sizeof ( reqs - > req1 ) ) ;
2016-09-20 15:02:06 +03:00
rc = sendto ( fd , efault2 , sizeof ( * reqs ) , MSG_DONTWAIT , NULL , 0 ) ;
2016-07-08 19:01:49 +03:00
printf ( " sendto(%d, [{{len=%u, type=NLMSG_NOOP, flags=NLM_F_REQUEST|0x%x "
2017-07-07 04:34:59 +03:00
" , seq=0, pid=0}, \" \\ x61 \\ x62 \\ x63 \\ x64 \" } "
" , %p], %u, MSG_DONTWAIT, NULL, 0) = %s \n " ,
2016-07-08 19:01:49 +03:00
fd , reqs - > req1 . nlh . nlmsg_len , NLM_F_DUMP ,
2016-09-20 15:02:06 +03:00
& ( ( struct reqs * ) efault2 ) - > req2 , ( unsigned ) sizeof ( * reqs ) ,
sprintrc ( rc ) ) ;
2016-07-08 19:01:49 +03:00
/* message length is not enough for the second struct nlmsghdr */
2016-09-20 15:02:06 +03:00
rc = sendto ( fd , reqs , sizeof ( * reqs ) - sizeof ( req - > nlh ) , MSG_DONTWAIT ,
NULL , 0 ) ;
errstr = sprintrc ( rc ) ;
2016-07-08 19:01:49 +03:00
printf ( " sendto(%d, [{{len=%u, type=NLMSG_NOOP, flags=NLM_F_REQUEST|0x%x "
2017-07-07 04:34:59 +03:00
" , seq=0, pid=0}, \" \\ x61 \\ x62 \\ x63 \\ x64 \" }, " ,
2016-07-08 19:01:49 +03:00
fd , reqs - > req1 . nlh . nlmsg_len , NLM_F_DUMP ) ;
2017-07-08 17:57:44 +03:00
print_quoted_hex ( & reqs - > req2 . nlh ,
2017-07-07 04:44:09 +03:00
sizeof ( reqs - > req2 ) - sizeof ( req - > nlh ) ) ;
2017-07-04 09:46:21 +03:00
printf ( " ], %u, MSG_DONTWAIT, NULL, 0) = %s \n " ,
2016-09-20 15:02:06 +03:00
( unsigned ) ( sizeof ( * reqs ) - sizeof ( req - > nlh ) ) , errstr ) ;
2016-07-08 19:01:49 +03:00
/* second nlmsg_len < sizeof(struct nlmsghdr) */
reqs - > req2 . nlh . nlmsg_len = 4 ;
2016-09-20 15:02:06 +03:00
rc = sendto ( fd , reqs , sizeof ( * reqs ) , MSG_DONTWAIT , NULL , 0 ) ;
2016-07-08 19:01:49 +03:00
printf ( " sendto(%d, [{{len=%u, type=NLMSG_NOOP, flags=NLM_F_REQUEST|0x%x "
2017-07-07 04:34:59 +03:00
" , seq=0, pid=0}, \" \\ x61 \\ x62 \\ x63 \\ x64 \" } "
" , {len=%u, type=NLMSG_NOOP, flags=NLM_F_REQUEST|0x%x "
" , seq=0, pid=0}], %u, MSG_DONTWAIT, NULL, 0) = %s \n " ,
2016-07-08 19:01:49 +03:00
fd , reqs - > req1 . nlh . nlmsg_len , NLM_F_DUMP ,
reqs - > req2 . nlh . nlmsg_len , NLM_F_DUMP ,
2016-09-20 15:02:06 +03:00
( unsigned ) sizeof ( * reqs ) , sprintrc ( rc ) ) ;
2016-07-08 19:01:49 +03:00
/* abbreviated output */
2016-07-21 21:18:40 +03:00
# define ABBREV_LEN (DEFAULT_STRLEN + 1)
2016-07-08 19:01:49 +03:00
const unsigned int msg_len = sizeof ( struct nlmsghdr ) * ABBREV_LEN ;
struct nlmsghdr * const msgs = tail_alloc ( msg_len ) ;
unsigned int i ;
for ( i = 0 ; i < ABBREV_LEN ; + + i ) {
msgs [ i ] . nlmsg_len = sizeof ( * msgs ) ;
msgs [ i ] . nlmsg_type = NLMSG_NOOP ;
msgs [ i ] . nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST ;
msgs [ i ] . nlmsg_seq = i ;
msgs [ i ] . nlmsg_pid = 0 ;
}
2016-09-20 15:02:06 +03:00
rc = sendto ( fd , msgs , msg_len , MSG_DONTWAIT , NULL , 0 ) ;
errstr = sprintrc ( rc ) ;
2016-07-08 19:01:49 +03:00
printf ( " sendto(%d, [ " , fd ) ;
for ( i = 0 ; i < DEFAULT_STRLEN ; + + i ) {
if ( i )
printf ( " , " ) ;
2017-06-19 00:43:39 +03:00
printf ( " {len=%u, type=NLMSG_NOOP, flags=NLM_F_REQUEST|0x%x "
" , seq=%u, pid=0} " ,
2016-07-08 19:01:49 +03:00
msgs [ i ] . nlmsg_len , NLM_F_DUMP , msgs [ i ] . nlmsg_seq ) ;
}
2016-09-20 15:02:06 +03:00
printf ( " , ...], %u, MSG_DONTWAIT, NULL, 0) = %s \n " , msg_len , errstr ) ;
2016-07-06 18:49:23 +03:00
}
2017-04-17 07:37:41 +03:00
static void
test_nlmsgerr ( const int fd )
{
struct nlmsgerr * err ;
struct nlmsghdr * nlh ;
void * const nlh0 = tail_alloc ( NLMSG_HDRLEN ) ;
long rc ;
/* error message without enough room for the error code */
nlh = nlh0 ;
nlh - > nlmsg_len = NLMSG_HDRLEN + 4 ;
nlh - > nlmsg_type = NLMSG_ERROR ;
nlh - > nlmsg_flags = NLM_F_REQUEST ;
nlh - > nlmsg_seq = 0 ;
nlh - > nlmsg_pid = 0 ;
rc = sendto ( fd , nlh , nlh - > nlmsg_len , MSG_DONTWAIT , NULL , 0 ) ;
printf ( " sendto(%d, {{len=%u, type=NLMSG_ERROR, flags=NLM_F_REQUEST "
" , seq=0, pid=0}, %p}, %u, MSG_DONTWAIT, NULL, 0) = %s \n " ,
fd , nlh - > nlmsg_len , nlh0 + NLMSG_HDRLEN ,
nlh - > nlmsg_len , sprintrc ( rc ) ) ;
nlh - > nlmsg_len = NLMSG_HDRLEN + 2 ;
2017-04-22 02:01:22 +03:00
nlh = nlh0 - 2 ;
memmove ( nlh , nlh0 , sizeof ( * nlh ) ) ;
2017-04-17 07:37:41 +03:00
memcpy ( NLMSG_DATA ( nlh ) , " 42 " , 2 ) ;
2017-04-22 02:01:22 +03:00
rc = sendto ( fd , nlh , NLMSG_HDRLEN + 2 , MSG_DONTWAIT , NULL , 0 ) ;
2017-04-17 07:37:41 +03:00
printf ( " sendto(%d, {{len=%u, type=NLMSG_ERROR, flags=NLM_F_REQUEST "
2017-07-07 04:10:17 +03:00
" , seq=0, pid=0}, \" \\ x34 \\ x32 \" } "
" , %u, MSG_DONTWAIT, NULL, 0) = %s \n " ,
2017-04-22 02:01:22 +03:00
fd , NLMSG_HDRLEN + 2 , NLMSG_HDRLEN + 2 , sprintrc ( rc ) ) ;
2017-04-17 07:37:41 +03:00
/* error message with room for the error code only */
nlh = nlh0 - sizeof ( err - > error ) ;
nlh - > nlmsg_len = NLMSG_HDRLEN + sizeof ( err - > error ) ;
nlh - > nlmsg_type = NLMSG_ERROR ;
nlh - > nlmsg_flags = NLM_F_REQUEST ;
nlh - > nlmsg_seq = 0 ;
nlh - > nlmsg_pid = 0 ;
err = NLMSG_DATA ( nlh ) ;
err - > error = 42 ;
rc = sendto ( fd , nlh , nlh - > nlmsg_len , MSG_DONTWAIT , NULL , 0 ) ;
printf ( " sendto(%d, {{len=%u, type=NLMSG_ERROR, flags=NLM_F_REQUEST "
" , seq=0, pid=0}, {error=42}}, %u, MSG_DONTWAIT, NULL, 0) "
" = %s \n " , fd , nlh - > nlmsg_len , nlh - > nlmsg_len , sprintrc ( rc ) ) ;
err - > error = - 1 ;
rc = sendto ( fd , nlh , nlh - > nlmsg_len , MSG_DONTWAIT , NULL , 0 ) ;
printf ( " sendto(%d, {{len=%u, type=NLMSG_ERROR, flags=NLM_F_REQUEST "
" , seq=0, pid=0}, {error=-EPERM}}, %u, MSG_DONTWAIT, NULL, 0) "
" = %s \n " , fd , nlh - > nlmsg_len , nlh - > nlmsg_len , sprintrc ( rc ) ) ;
err - > error = - 32767 ;
nlh - > nlmsg_len + = sizeof ( err - > msg . nlmsg_len ) ;
rc = sendto ( fd , nlh , nlh - > nlmsg_len , MSG_DONTWAIT , NULL , 0 ) ;
printf ( " sendto(%d, {{len=%u, type=NLMSG_ERROR, flags=NLM_F_REQUEST "
" , seq=0, pid=0}, {error=-32767, msg=%p}} "
" , %u, MSG_DONTWAIT, NULL, 0) = %s \n " ,
fd , nlh - > nlmsg_len , nlh0 + NLMSG_HDRLEN ,
nlh - > nlmsg_len , sprintrc ( rc ) ) ;
/* error message with room for the error code and a header */
nlh = nlh0 - sizeof ( * err ) ;
nlh - > nlmsg_len = NLMSG_HDRLEN + sizeof ( * err ) ;
nlh - > nlmsg_type = NLMSG_ERROR ;
nlh - > nlmsg_flags = NLM_F_REQUEST ;
nlh - > nlmsg_seq = 0 ;
nlh - > nlmsg_pid = 0 ;
err = NLMSG_DATA ( nlh ) ;
err - > error = - 13 ;
err - > msg . nlmsg_len = NLMSG_HDRLEN ;
err - > msg . nlmsg_type = NLMSG_NOOP ;
err - > msg . nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST ;
err - > msg . nlmsg_seq = 42 ;
err - > msg . nlmsg_pid = 1234 ;
rc = sendto ( fd , nlh , nlh - > nlmsg_len , MSG_DONTWAIT , NULL , 0 ) ;
printf ( " sendto(%d, {{len=%u, type=NLMSG_ERROR, flags=NLM_F_REQUEST "
" , seq=0, pid=0}, {error=-EACCES "
2017-06-19 00:43:39 +03:00
" , msg={len=%u, type=NLMSG_NOOP, flags=NLM_F_REQUEST|0x%x "
" , seq=%u, pid=%u}}}, %u, MSG_DONTWAIT, NULL, 0) = %s \n " ,
2017-04-17 07:37:41 +03:00
fd , nlh - > nlmsg_len , err - > msg . nlmsg_len , NLM_F_DUMP ,
err - > msg . nlmsg_seq , err - > msg . nlmsg_pid ,
nlh - > nlmsg_len , sprintrc ( rc ) ) ;
/* error message with room for the error code, a header, and some data */
nlh = nlh0 - sizeof ( * err ) - 4 ;
nlh - > nlmsg_len = NLMSG_HDRLEN + sizeof ( * err ) + 4 ;
nlh - > nlmsg_type = NLMSG_ERROR ;
nlh - > nlmsg_flags = NLM_F_REQUEST ;
nlh - > nlmsg_seq = 0 ;
nlh - > nlmsg_pid = 0 ;
err = NLMSG_DATA ( nlh ) ;
err - > error = - 13 ;
err - > msg . nlmsg_len = NLMSG_HDRLEN + 4 ;
err - > msg . nlmsg_type = NLMSG_NOOP ;
err - > msg . nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST ;
err - > msg . nlmsg_seq = 421 ;
err - > msg . nlmsg_pid = 12345 ;
memcpy ( NLMSG_DATA ( & err - > msg ) , " abcd " , 4 ) ;
rc = sendto ( fd , nlh , nlh - > nlmsg_len , MSG_DONTWAIT , NULL , 0 ) ;
printf ( " sendto(%d, {{len=%u, type=NLMSG_ERROR, flags=NLM_F_REQUEST "
" , seq=0, pid=0}, {error=-EACCES "
" , msg={{len=%u, type=NLMSG_NOOP, flags=NLM_F_REQUEST|0x%x "
2017-07-07 04:34:59 +03:00
" , seq=%u, pid=%u}, \" \\ x61 \\ x62 \\ x63 \\ x64 \" }}} "
" , %u, MSG_DONTWAIT, NULL, 0) = %s \n " ,
2017-04-17 07:37:41 +03:00
fd , nlh - > nlmsg_len , err - > msg . nlmsg_len , NLM_F_DUMP ,
err - > msg . nlmsg_seq , err - > msg . nlmsg_pid ,
nlh - > nlmsg_len , sprintrc ( rc ) ) ;
}
2017-05-05 13:21:17 +03:00
static void
test_nlmsg_done ( const int fd )
{
struct nlmsghdr * nlh ;
void * const nlh0 = tail_alloc ( NLMSG_HDRLEN ) ;
long rc ;
2017-06-04 16:40:17 +03:00
const int num = 0xfacefeed ;
2017-05-05 13:21:17 +03:00
2017-06-04 16:40:17 +03:00
/* NLMSG_DONE message without enough room for an integer payload */
2017-05-05 13:21:17 +03:00
nlh = nlh0 ;
2017-06-04 16:40:17 +03:00
* nlh = ( struct nlmsghdr ) {
. nlmsg_len = NLMSG_HDRLEN + sizeof ( num ) ,
. nlmsg_type = NLMSG_DONE ,
. nlmsg_flags = NLM_F_MULTI
} ;
2017-05-05 13:21:17 +03:00
rc = sendto ( fd , nlh , nlh - > nlmsg_len , MSG_DONTWAIT , NULL , 0 ) ;
printf ( " sendto(%d, {{len=%u, type=NLMSG_DONE, flags=NLM_F_MULTI "
" , seq=0, pid=0}, %p}, %u, MSG_DONTWAIT, NULL, 0) = %s \n " ,
fd , nlh - > nlmsg_len , nlh0 + NLMSG_HDRLEN ,
nlh - > nlmsg_len , sprintrc ( rc ) ) ;
2017-06-04 16:40:17 +03:00
/* NLMSG_DONE message with enough room for an oddly short payload */
nlh - > nlmsg_len = NLMSG_HDRLEN + 2 ;
nlh = nlh0 - 2 ;
/* Beware of unaligned access to nlh members. */
memmove ( nlh , nlh0 , sizeof ( * nlh ) ) ;
memcpy ( NLMSG_DATA ( nlh ) , " 42 " , 2 ) ;
rc = sendto ( fd , nlh , NLMSG_HDRLEN + 2 , MSG_DONTWAIT , NULL , 0 ) ;
2017-07-07 04:34:59 +03:00
printf ( " sendto(%d, {{len=%u, type=NLMSG_DONE, flags=NLM_F_MULTI, seq=0 "
" , pid=0}, \" \\ x34 \\ x32 \" }, %u, MSG_DONTWAIT, NULL, 0) = %s \n " ,
2017-06-04 16:40:17 +03:00
fd , NLMSG_HDRLEN + 2 , NLMSG_HDRLEN + 2 , sprintrc ( rc ) ) ;
/* NLMSG_DONE message with enough room for an integer payload */
nlh = nlh0 - sizeof ( num ) ;
* nlh = ( struct nlmsghdr ) {
. nlmsg_len = NLMSG_HDRLEN + sizeof ( num ) ,
. nlmsg_type = NLMSG_DONE ,
. nlmsg_flags = NLM_F_MULTI
} ;
memcpy ( NLMSG_DATA ( nlh ) , & num , sizeof ( num ) ) ;
2017-05-05 13:21:17 +03:00
rc = sendto ( fd , nlh , nlh - > nlmsg_len , MSG_DONTWAIT , NULL , 0 ) ;
printf ( " sendto(%d, {{len=%u, type=NLMSG_DONE, flags=NLM_F_MULTI "
" , seq=0, pid=0}, %d}, %u, MSG_DONTWAIT, NULL, 0) = %s \n " ,
2017-06-04 16:40:17 +03:00
fd , nlh - > nlmsg_len , num , nlh - > nlmsg_len , sprintrc ( rc ) ) ;
2017-05-05 13:21:17 +03:00
}
2017-07-19 12:17:35 +03:00
# if defined NLM_F_CAPPED || defined NLM_F_ACK_TLVS
static void
test_ack_flags ( const int fd )
{
long rc ;
struct nlmsghdr nlh = {
. nlmsg_len = sizeof ( nlh ) ,
. nlmsg_type = NLMSG_ERROR ,
} ;
# ifdef NLM_F_CAPPED
nlh . nlmsg_flags = NLM_F_REQUEST | NLM_F_CAPPED ,
rc = sendto ( fd , & nlh , sizeof ( nlh ) , MSG_DONTWAIT , NULL , 0 ) ;
printf ( " sendto(%d, {len=%u, type=NLMSG_ERROR "
" , flags=NLM_F_REQUEST|NLM_F_CAPPED, seq=0, pid=0} "
" , %u, MSG_DONTWAIT, NULL, 0) = %s \n " ,
fd , nlh . nlmsg_len , ( unsigned ) sizeof ( nlh ) , sprintrc ( rc ) ) ;
# endif
# ifdef NLM_F_ACK_TLVS
nlh . nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK_TLVS ;
rc = sendto ( fd , & nlh , sizeof ( nlh ) , MSG_DONTWAIT , NULL , 0 ) ;
printf ( " sendto(%d, {len=%u, type=NLMSG_ERROR "
" , flags=NLM_F_REQUEST|NLM_F_ACK_TLVS, seq=0, pid=0} "
" , %u, MSG_DONTWAIT, NULL, 0) = %s \n " ,
fd , nlh . nlmsg_len , ( unsigned ) sizeof ( nlh ) , sprintrc ( rc ) ) ;
# endif
# if defined NLM_F_CAPPED && defined NLM_F_ACK_TLVS
nlh . nlmsg_flags = NLM_F_REQUEST | NLM_F_CAPPED | NLM_F_ACK_TLVS ;
rc = sendto ( fd , & nlh , sizeof ( nlh ) , MSG_DONTWAIT , NULL , 0 ) ;
printf ( " sendto(%d, {len=%u, type=NLMSG_ERROR "
" , flags=NLM_F_REQUEST|NLM_F_CAPPED|NLM_F_ACK_TLVS, seq=0, pid=0} "
" , %u, MSG_DONTWAIT, NULL, 0) = %s \n " ,
fd , nlh . nlmsg_len , ( unsigned ) sizeof ( nlh ) , sprintrc ( rc ) ) ;
# endif
}
# endif
2016-07-06 18:49:23 +03:00
int main ( void )
{
2017-06-05 16:11:44 +03:00
const int fd = create_nl_socket ( NETLINK_SOCK_DIAG ) ;
2016-07-06 18:49:23 +03:00
2016-07-21 21:18:40 +03:00
char * path ;
if ( asprintf ( & path , " /proc/self/fd/%u " , fd ) < 0 )
perror_msg_and_fail ( " asprintf " ) ;
char buf [ 256 ] ;
if ( getxattr ( path , " system.sockprotoname " , buf , sizeof ( buf ) - 1 ) < 0 )
perror_msg_and_skip ( " getxattr " ) ;
free ( path ) ;
2016-07-06 18:49:23 +03:00
send_query ( fd ) ;
2017-04-17 07:37:41 +03:00
test_nlmsgerr ( fd ) ;
2017-05-05 13:21:17 +03:00
test_nlmsg_done ( fd ) ;
2017-07-19 12:17:35 +03:00
# if defined NLM_F_CAPPED || defined NLM_F_ACK_TLVS
test_ack_flags ( fd ) ;
# endif
2016-07-06 18:49:23 +03:00
2017-06-05 16:11:44 +03:00
puts ( " +++ exited with 0 +++ " ) ;
2016-07-06 18:49:23 +03:00
return 0 ;
}
2016-07-21 21:18:40 +03:00
# else
SKIP_MAIN_UNDEFINED ( " HAVE_SYS_XATTR_H " )
# endif