1 /* 2 * Copyright (c) 2017 JingPiao Chen <chenjingpiao (at) gmail.com> 3 * Copyright (c) 2017 The strace developers. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "tests.h" 30 31 #include <stdio.h> 32 #include <string.h> 33 #include <stdint.h> 34 #include <net/if.h> 35 #include "test_nlattr.h" 36 #include <sys/socket.h> 37 #include <linux/filter.h> 38 #include <linux/packet_diag.h> 39 #include <linux/rtnetlink.h> 40 #include <linux/sock_diag.h> 41 42 static void 43 init_packet_diag_msg(struct nlmsghdr *const nlh, const unsigned int msg_len) 44 { 45 SET_STRUCT(struct nlmsghdr, nlh, 46 .nlmsg_len = msg_len, 47 .nlmsg_type = SOCK_DIAG_BY_FAMILY, 48 .nlmsg_flags = NLM_F_DUMP 49 ); 50 51 struct packet_diag_msg *const msg = NLMSG_DATA(nlh); 52 SET_STRUCT(struct packet_diag_msg, msg, 53 .pdiag_family = AF_PACKET, 54 .pdiag_type = SOCK_STREAM 55 ); 56 } 57 58 static void 59 print_packet_diag_msg(const unsigned int msg_len) 60 { 61 printf("{len=%u, type=SOCK_DIAG_BY_FAMILY" 62 ", flags=NLM_F_DUMP, seq=0, pid=0}" 63 ", {pdiag_family=AF_PACKET" 64 ", pdiag_type=SOCK_STREAM, pdiag_num=0" 65 ", pdiag_ino=0, pdiag_cookie=[0, 0]}", 66 msg_len); 67 } 68 69 static void 70 print_packet_diag_mclist(const struct packet_diag_mclist *const dml) 71 { 72 printf("{pdmc_index=" IFINDEX_LO_STR); 73 PRINT_FIELD_U(", ", *dml, pdmc_count); 74 PRINT_FIELD_U(", ", *dml, pdmc_type); 75 PRINT_FIELD_U(", ", *dml, pdmc_alen); 76 printf(", pdmc_addr="); 77 print_quoted_hex(dml->pdmc_addr, dml->pdmc_alen); 78 printf("}"); 79 } 80 81 static const struct sock_filter filter[] = { 82 BPF_STMT(BPF_LD|BPF_B|BPF_ABS, SKF_AD_OFF+SKF_AD_PKTTYPE), 83 BPF_STMT(BPF_RET|BPF_K, 0x2a) 84 }; 85 86 static void 87 print_sock_filter(const struct sock_filter *const f) 88 { 89 if (f == filter) 90 printf("BPF_STMT(BPF_LD|BPF_B|BPF_ABS" 91 ", SKF_AD_OFF+SKF_AD_PKTTYPE)"); 92 else 93 printf("BPF_STMT(BPF_RET|BPF_K, 0x2a)"); 94 } 95 96 int 97 main(void) 98 { 99 skip_if_unavailable("/proc/self/fd/"); 100 101 int fd = create_nl_socket(NETLINK_SOCK_DIAG); 102 const unsigned int hdrlen = sizeof(struct packet_diag_msg); 103 void *const nlh0 = tail_alloc(NLMSG_SPACE(hdrlen)); 104 105 static char pattern[4096]; 106 fill_memory_ex(pattern, sizeof(pattern), 'a', 'z' - 'a' + 1); 107 108 static const struct packet_diag_info pinfo = { 109 .pdi_index = 0xabcddafa, 110 .pdi_version = 0xbabcdafb, 111 .pdi_reserve = 0xcfaacdaf, 112 .pdi_copy_thresh = 0xdabacdaf, 113 .pdi_tstamp = 0xeafbaadf, 114 .pdi_flags = PDI_RUNNING 115 }; 116 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen, 117 init_packet_diag_msg, print_packet_diag_msg, 118 PACKET_DIAG_INFO, pattern, pinfo, 119 PRINT_FIELD_U("{", pinfo, pdi_index); 120 PRINT_FIELD_U(", ", pinfo, pdi_version); 121 PRINT_FIELD_U(", ", pinfo, pdi_reserve); 122 PRINT_FIELD_U(", ", pinfo, pdi_copy_thresh); 123 PRINT_FIELD_U(", ", pinfo, pdi_tstamp); 124 printf(", pdi_flags=PDI_RUNNING}")); 125 126 const struct packet_diag_mclist dml[] = { 127 { 128 .pdmc_index = ifindex_lo(), 129 .pdmc_count = 0xabcdaefc, 130 .pdmc_type = 0xcdaf, 131 .pdmc_alen = 4, 132 .pdmc_addr = "1234" 133 }, 134 { 135 .pdmc_index = ifindex_lo(), 136 .pdmc_count = 0xdaefeafc, 137 .pdmc_type = 0xadef, 138 .pdmc_alen = 4, 139 .pdmc_addr = "5678" 140 } 141 }; 142 TEST_NLATTR_ARRAY(fd, nlh0, hdrlen, 143 init_packet_diag_msg, print_packet_diag_msg, 144 PACKET_DIAG_MCLIST, pattern, dml, 145 print_packet_diag_mclist); 146 147 static const struct packet_diag_ring pdr = { 148 .pdr_block_size = 0xabcdafed, 149 .pdr_block_nr = 0xbcadefae, 150 .pdr_frame_size = 0xcabdfeac, 151 .pdr_frame_nr = 0xdeaeadef, 152 .pdr_retire_tmo = 0xedbafeac, 153 .pdr_sizeof_priv = 0xfeadeacd, 154 .pdr_features = 0xadebadea 155 }; 156 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen, 157 init_packet_diag_msg, print_packet_diag_msg, 158 PACKET_DIAG_RX_RING, pattern, pdr, 159 PRINT_FIELD_U("{", pdr, pdr_block_size); 160 PRINT_FIELD_U(", ", pdr, pdr_block_nr); 161 PRINT_FIELD_U(", ", pdr, pdr_frame_size); 162 PRINT_FIELD_U(", ", pdr, pdr_frame_nr); 163 PRINT_FIELD_U(", ", pdr, pdr_retire_tmo); 164 PRINT_FIELD_U(", ", pdr, pdr_sizeof_priv); 165 PRINT_FIELD_U(", ", pdr, pdr_features); 166 printf("}")); 167 168 TEST_NLATTR_ARRAY(fd, nlh0, hdrlen, 169 init_packet_diag_msg, print_packet_diag_msg, 170 PACKET_DIAG_FILTER, pattern, filter, 171 print_sock_filter); 172 173 printf("+++ exited with 0 +++\n"); 174 return 0; 175 } 176