chiark / gitweb /
bus-proxy: make sure sure eavesdrop= XML attributes are properly handled
[elogind.git] / src / libsystemd-network / test-lldp.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright (C) 2014 Tom Gundersen
7   Copyright (C) 2014 Susant Sahani
8
9   systemd is free software; you can redistribute it and/or modify it
10   under the terms of the GNU Lesser General Public License as published by
11   the Free Software Foundation; either version 2.1 of the License, or
12   (at your option) any later version.
13
14   systemd is distributed in the hope that it will be useful, but
15   WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   Lesser General Public License for more details.
18
19   You should have received a copy of the GNU Lesser General Public License
20   along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 ***/
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/socket.h>
27 #include <linux/if.h>
28 #include <linux/if_ether.h>
29 #include <net/ethernet.h>
30 #include <sys/types.h>
31 #include <arpa/inet.h>
32
33 #include "macro.h"
34 #include "lldp.h"
35 #include "lldp-tlv.h"
36
37 #define TEST_LLDP_PORT "em1"
38 #define TEST_LLDP_TYPE_SYSTEM_NAME "systemd-lldp"
39 #define TEST_LLDP_TYPE_SYSTEM_DESC "systemd-lldp-desc"
40
41 static struct ether_addr mac_addr = {
42         .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}
43 };
44
45 static int lldp_build_tlv_packet(tlv_packet **ret) {
46         _cleanup_tlv_packet_free_ tlv_packet *m = NULL;
47         const uint8_t lldp_dst[] = LLDP_MULTICAST_ADDR;
48         struct ether_header ether;
49
50         /* Append ethernet header */
51         memset(&ether, 0, sizeof(ether));
52         memcpy(&ether.ether_dhost, lldp_dst, ETHER_ADDR_LEN);
53         memcpy(&ether.ether_shost, &mac_addr, ETHER_ADDR_LEN);
54         ether.ether_type = htons(ETHERTYPE_LLDP);
55
56         assert_se(tlv_packet_new(&m) >= 0);
57
58         assert_se(tlv_packet_append_bytes(m, &ether, sizeof(struct ether_header)) >= 0);
59
60         assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_CHASSIS_ID) >= 0);
61
62         assert_se(tlv_packet_append_u8(m, LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS) >= 0);
63         assert_se(tlv_packet_append_bytes(m, &mac_addr, ETHER_ADDR_LEN) >= 0);
64
65         assert_se(lldp_tlv_packet_close_container(m) >= 0);
66
67         /* port name */
68         assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_PORT_ID) >= 0);
69
70         assert_se(tlv_packet_append_u8(m, LLDP_PORT_SUBTYPE_INTERFACE_NAME) >= 0);
71         assert_se(tlv_packet_append_bytes(m, TEST_LLDP_PORT, strlen(TEST_LLDP_PORT) + 1) >= 0);
72
73         assert_se(lldp_tlv_packet_close_container(m) >= 0);
74
75         /* ttl */
76         assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_TTL) >= 0);
77
78         assert_se(tlv_packet_append_u16(m, 170) >= 0);
79
80         assert_se(lldp_tlv_packet_close_container(m) >= 0);
81
82         /* system name */
83         assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_SYSTEM_NAME) >= 0);
84
85         assert_se(tlv_packet_append_bytes(m, TEST_LLDP_TYPE_SYSTEM_NAME,
86                                           strlen(TEST_LLDP_TYPE_SYSTEM_NAME)) >= 0);
87         assert_se(lldp_tlv_packet_close_container(m) >= 0);
88
89         /* system descrition */
90         assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_SYSTEM_DESCRIPTION) >= 0);
91
92         assert_se(tlv_packet_append_bytes(m, TEST_LLDP_TYPE_SYSTEM_DESC,
93                                           strlen(TEST_LLDP_TYPE_SYSTEM_DESC)) >= 0);
94
95         assert_se(lldp_tlv_packet_close_container(m) >= 0);
96
97         /* Mark end of packet */
98         assert_se(lldp_tlv_packet_open_container(m, LLDP_TYPE_END) >= 0);
99         assert_se(lldp_tlv_packet_close_container(m) >= 0);
100
101         *ret = m;
102
103         m = NULL;
104
105         return 0;
106 }
107
108 static int lldp_parse_chassis_tlv(tlv_packet *m, uint8_t *type) {
109         uint8_t *p, subtype;
110         uint16_t length;
111
112         assert_se(lldp_tlv_packet_enter_container(m, LLDP_TYPE_CHASSIS_ID) >= 0);
113         assert_se(tlv_packet_read_u8(m, &subtype) >= 0);
114
115         switch (subtype) {
116         case LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS:
117
118                 *type = LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS;
119                 assert_se(tlv_packet_read_bytes(m, &p, &length) >= 0);
120
121                 assert_se(memcmp(p, &mac_addr.ether_addr_octet, ETHER_ADDR_LEN) == 0);
122
123                 break;
124         default:
125                 assert_not_reached("Unhandled option");
126         }
127
128         assert_se(lldp_tlv_packet_exit_container(m) >= 0);
129
130         return 0;
131 }
132
133 static int lldp_parse_port_id_tlv(tlv_packet *m) {
134         char *str = NULL, *p;
135         uint16_t length;
136         uint8_t subtype;
137
138         assert_se(lldp_tlv_packet_enter_container(m, LLDP_TYPE_PORT_ID) >= 0);
139
140         assert_se(tlv_packet_read_u8(m, &subtype) >= 0);
141
142         switch (subtype) {
143         case LLDP_PORT_SUBTYPE_INTERFACE_NAME:
144                 assert_se(tlv_packet_read_string(m, &str, &length) >= 0);
145
146                 p = malloc0(length + 1);
147                 assert_se(p);
148                 strncpy(p, str, length-1);
149
150                 assert_se(streq(p, TEST_LLDP_PORT) == 1);
151                 break;
152         default:
153                 assert_not_reached("Unhandled option");
154         }
155
156         assert_se(lldp_tlv_packet_exit_container(m) >= 0);
157
158         return 0;
159 }
160
161 static int lldp_parse_system_name_tlv(tlv_packet *m) {
162         char *str = NULL, *p;
163         uint16_t length;
164
165         assert_se(lldp_tlv_packet_enter_container(m, LLDP_TYPE_SYSTEM_NAME) >= 0);
166         assert_se(tlv_packet_read_string(m, &str, &length) >= 0);
167
168         p = malloc0(length + 1);
169         strncpy(p, str, length);
170
171         assert_se(streq(p, TEST_LLDP_TYPE_SYSTEM_NAME) == 1);
172
173         assert_se(lldp_tlv_packet_exit_container(m) >= 0);
174
175         return 1;
176 }
177
178 static int lldp_parse_system_desc_tlv(tlv_packet *m) {
179         char *str = NULL, *p;
180         uint16_t length;
181
182         assert_se(lldp_tlv_packet_enter_container(m, LLDP_TYPE_SYSTEM_DESCRIPTION) >= 0);
183         assert_se(tlv_packet_read_string(m, &str, &length) >= 0);
184
185         p = malloc0(length + 1);
186         assert_se(p);
187         strncpy(p, str, length);
188
189         assert_se(streq(p, TEST_LLDP_TYPE_SYSTEM_DESC) == 1);
190
191         assert_se(lldp_tlv_packet_exit_container(m) >= 0);
192
193         return 0;
194 }
195
196 static int lldp_parse_ttl_tlv(tlv_packet *m) {
197         uint16_t ttl;
198
199         assert_se(lldp_tlv_packet_enter_container(m, LLDP_TYPE_TTL) >= 0);
200         assert_se(tlv_packet_read_u16(m, &ttl) >= 0);
201
202         assert_se(ttl == 170);
203
204         assert_se(lldp_tlv_packet_exit_container(m) >= 0);
205
206         return 0;
207 }
208
209 static int lldp_parse_tlv_packet(tlv_packet *m, int len) {
210         uint8_t subtype;
211
212         assert_se(tlv_packet_parse_pdu(m, len) >= 0);
213         assert_se(lldp_parse_chassis_tlv(m, &subtype) >= 0);
214         assert_se(lldp_parse_port_id_tlv(m) >= 0);
215         assert_se(lldp_parse_system_name_tlv(m) >= 0);
216         assert_se(lldp_parse_ttl_tlv(m) >= 0);
217         assert_se(lldp_parse_system_desc_tlv(m) >= 0);
218
219         return 0;
220 }
221
222 int main(int argc, char *argv[]) {
223         _cleanup_tlv_packet_free_ tlv_packet *tlv = NULL;
224
225         /* form a packet */
226         lldp_build_tlv_packet(&tlv);
227
228         /* parse the packet */
229         tlv_packet_parse_pdu(tlv, tlv->length);
230
231         /* verify */
232         lldp_parse_tlv_packet(tlv, tlv->length);
233
234         return 0;
235 }