1e162ea60SGeorge V. Neville-Neil /*
2*179fa75eSJohn Baldwin * Copyright (c) 2010 Hudson River Trading LLC
3e162ea60SGeorge V. Neville-Neil * Written by George Neville-Neil gnn@freebsd.org
4e162ea60SGeorge V. Neville-Neil * All rights reserved.
5e162ea60SGeorge V. Neville-Neil *
6e162ea60SGeorge V. Neville-Neil * Redistribution and use in source and binary forms, with or without
7e162ea60SGeorge V. Neville-Neil * modification, are permitted provided that the following conditions
8e162ea60SGeorge V. Neville-Neil * are met:
9e162ea60SGeorge V. Neville-Neil * 1. Redistributions of source code must retain the above copyright
10e162ea60SGeorge V. Neville-Neil * notice, this list of conditions and the following disclaimer.
11e162ea60SGeorge V. Neville-Neil * 2. Redistributions in binary form must reproduce the above copyright
12e162ea60SGeorge V. Neville-Neil * notice, this list of conditions and the following disclaimer in the
13e162ea60SGeorge V. Neville-Neil * documentation and/or other materials provided with the distribution.
14e162ea60SGeorge V. Neville-Neil *
15e162ea60SGeorge V. Neville-Neil * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16e162ea60SGeorge V. Neville-Neil * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17e162ea60SGeorge V. Neville-Neil * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18e162ea60SGeorge V. Neville-Neil * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19e162ea60SGeorge V. Neville-Neil * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20e162ea60SGeorge V. Neville-Neil * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21e162ea60SGeorge V. Neville-Neil * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22e162ea60SGeorge V. Neville-Neil * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23e162ea60SGeorge V. Neville-Neil * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24e162ea60SGeorge V. Neville-Neil * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25e162ea60SGeorge V. Neville-Neil * SUCH DAMAGE.
26e162ea60SGeorge V. Neville-Neil *
27e162ea60SGeorge V. Neville-Neil * Description: The following is a test of the arp entry packet queues
28e162ea60SGeorge V. Neville-Neil * which replaced the single packet hold entry that existed in the BSDs
29e162ea60SGeorge V. Neville-Neil * since time immemorial. The test process is:
30e162ea60SGeorge V. Neville-Neil *
31e162ea60SGeorge V. Neville-Neil * 1) Find out the current system limit (maxhold)
32e162ea60SGeorge V. Neville-Neil * 2) Using an IP address for which we do not yet have an entry
33e162ea60SGeorge V. Neville-Neil * load up an ARP entry packet queue with exactly that many packets.
34e162ea60SGeorge V. Neville-Neil * 3) Check the arp dropped stat to make sure that we have not dropped
35e162ea60SGeorge V. Neville-Neil * any packets as yet.
36e162ea60SGeorge V. Neville-Neil * 4) Add one more packet to the queue.
37e162ea60SGeorge V. Neville-Neil * 5) Make sure that only one packet was dropped.
38e162ea60SGeorge V. Neville-Neil *
39e162ea60SGeorge V. Neville-Neil * CAVEAT: The ARP timer will flush the queue after 1 second so it is
40e162ea60SGeorge V. Neville-Neil * important not to run this code in a fast loop or the test will
41e162ea60SGeorge V. Neville-Neil * fail.
42e162ea60SGeorge V. Neville-Neil */
43e162ea60SGeorge V. Neville-Neil
44e162ea60SGeorge V. Neville-Neil #include <unistd.h>
45e162ea60SGeorge V. Neville-Neil #include <stdio.h>
46e162ea60SGeorge V. Neville-Neil #include <stdlib.h>
47e162ea60SGeorge V. Neville-Neil #include <string.h>
48e162ea60SGeorge V. Neville-Neil #include <sys/types.h>
49e162ea60SGeorge V. Neville-Neil #include <sys/sysctl.h>
50e162ea60SGeorge V. Neville-Neil #include <sys/socket.h>
51e162ea60SGeorge V. Neville-Neil #include <netinet/in.h>
52e162ea60SGeorge V. Neville-Neil #include <arpa/inet.h>
53e162ea60SGeorge V. Neville-Neil #include <net/if_arp.h>
54e162ea60SGeorge V. Neville-Neil
55e162ea60SGeorge V. Neville-Neil #define MSG_SIZE 1024
56e162ea60SGeorge V. Neville-Neil #define PORT 6969
57e162ea60SGeorge V. Neville-Neil
58e162ea60SGeorge V. Neville-Neil int
main(int argc,char ** argv)59e162ea60SGeorge V. Neville-Neil main(int argc, char **argv)
60e162ea60SGeorge V. Neville-Neil {
61e162ea60SGeorge V. Neville-Neil
62e162ea60SGeorge V. Neville-Neil int sock;
63e162ea60SGeorge V. Neville-Neil int maxhold;
64e162ea60SGeorge V. Neville-Neil size_t size = sizeof(maxhold);
65e162ea60SGeorge V. Neville-Neil struct sockaddr_in dest;
66e162ea60SGeorge V. Neville-Neil char message[MSG_SIZE];
67e162ea60SGeorge V. Neville-Neil struct arpstat arpstat;
68e162ea60SGeorge V. Neville-Neil size_t len = sizeof(arpstat);
69e162ea60SGeorge V. Neville-Neil unsigned long dropped = 0;
70e162ea60SGeorge V. Neville-Neil
71e162ea60SGeorge V. Neville-Neil memset(&message, 1, sizeof(message));
72e162ea60SGeorge V. Neville-Neil
73e162ea60SGeorge V. Neville-Neil if (sysctlbyname("net.link.ether.inet.maxhold", &maxhold, &size,
74e162ea60SGeorge V. Neville-Neil NULL, 0) < 0) {
75e162ea60SGeorge V. Neville-Neil perror("not ok 1 - sysctlbyname failed");
76e162ea60SGeorge V. Neville-Neil exit(1);
77e162ea60SGeorge V. Neville-Neil }
78e162ea60SGeorge V. Neville-Neil
79e162ea60SGeorge V. Neville-Neil #ifdef DEBUG
80e162ea60SGeorge V. Neville-Neil printf("maxhold is %d\n", maxhold);
81e162ea60SGeorge V. Neville-Neil #endif /* DEBUG */
82e162ea60SGeorge V. Neville-Neil
83e162ea60SGeorge V. Neville-Neil if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
84e162ea60SGeorge V. Neville-Neil perror("not ok 1 - could not open socket");
85e162ea60SGeorge V. Neville-Neil exit(1);
86e162ea60SGeorge V. Neville-Neil }
87e162ea60SGeorge V. Neville-Neil
88e162ea60SGeorge V. Neville-Neil bzero(&dest, sizeof(dest));
89e162ea60SGeorge V. Neville-Neil if (inet_pton(AF_INET, argv[1], &dest.sin_addr.s_addr) != 1) {
90e162ea60SGeorge V. Neville-Neil perror("not ok 1 - could not parse address");
91e162ea60SGeorge V. Neville-Neil exit(1);
92e162ea60SGeorge V. Neville-Neil }
93e162ea60SGeorge V. Neville-Neil dest.sin_len = sizeof(dest);
94e162ea60SGeorge V. Neville-Neil dest.sin_family = AF_INET;
95e162ea60SGeorge V. Neville-Neil dest.sin_port = htons(PORT);
96e162ea60SGeorge V. Neville-Neil
97e162ea60SGeorge V. Neville-Neil if (sysctlbyname("net.link.ether.arp.stats", &arpstat, &len,
98e162ea60SGeorge V. Neville-Neil NULL, 0) < 0) {
99e162ea60SGeorge V. Neville-Neil perror("not ok 1 - could not get initial arp stats");
100e162ea60SGeorge V. Neville-Neil exit(1);
101e162ea60SGeorge V. Neville-Neil }
102e162ea60SGeorge V. Neville-Neil
103e162ea60SGeorge V. Neville-Neil dropped = arpstat.dropped;
104e162ea60SGeorge V. Neville-Neil #ifdef DEBUG
105e162ea60SGeorge V. Neville-Neil printf("dropped before %ld\n", dropped);
106e162ea60SGeorge V. Neville-Neil #endif /* DEBUG */
107e162ea60SGeorge V. Neville-Neil
108e162ea60SGeorge V. Neville-Neil /*
109e162ea60SGeorge V. Neville-Neil * Load up the queue in the ARP entry to the maximum.
110e162ea60SGeorge V. Neville-Neil * We should not drop any packets at this point.
111e162ea60SGeorge V. Neville-Neil */
112e162ea60SGeorge V. Neville-Neil
113e162ea60SGeorge V. Neville-Neil while (maxhold > 0) {
114e162ea60SGeorge V. Neville-Neil if (sendto(sock, message, sizeof(message), 0,
115e162ea60SGeorge V. Neville-Neil (struct sockaddr *)&dest, sizeof(dest)) < 0) {
116e162ea60SGeorge V. Neville-Neil perror("not ok 1 - could not send packet");
117e162ea60SGeorge V. Neville-Neil exit(1);
118e162ea60SGeorge V. Neville-Neil }
119e162ea60SGeorge V. Neville-Neil maxhold--;
120e162ea60SGeorge V. Neville-Neil }
121e162ea60SGeorge V. Neville-Neil
122e162ea60SGeorge V. Neville-Neil if (sysctlbyname("net.link.ether.arp.stats", &arpstat, &len,
123e162ea60SGeorge V. Neville-Neil NULL, 0) < 0) {
124e162ea60SGeorge V. Neville-Neil perror("not ok 1 - could not get new arp stats");
125e162ea60SGeorge V. Neville-Neil exit(1);
126e162ea60SGeorge V. Neville-Neil }
127e162ea60SGeorge V. Neville-Neil
128e162ea60SGeorge V. Neville-Neil #ifdef DEBUG
129e162ea60SGeorge V. Neville-Neil printf("dropped after %ld\n", arpstat.dropped);
130e162ea60SGeorge V. Neville-Neil #endif /* DEBUG */
131e162ea60SGeorge V. Neville-Neil
132e162ea60SGeorge V. Neville-Neil if (arpstat.dropped != dropped) {
133e162ea60SGeorge V. Neville-Neil printf("not ok 1 - Failed, drops changed:"
134e162ea60SGeorge V. Neville-Neil "before %ld after %ld\n", dropped, arpstat.dropped);
135e162ea60SGeorge V. Neville-Neil exit(1);
136e162ea60SGeorge V. Neville-Neil }
137e162ea60SGeorge V. Neville-Neil
138e162ea60SGeorge V. Neville-Neil dropped = arpstat.dropped;
139e162ea60SGeorge V. Neville-Neil
140e162ea60SGeorge V. Neville-Neil /* Now add one extra and make sure it is dropped. */
141e162ea60SGeorge V. Neville-Neil if (sendto(sock, message, sizeof(message), 0,
142e162ea60SGeorge V. Neville-Neil (struct sockaddr *)&dest, sizeof(dest)) < 0) {
143e162ea60SGeorge V. Neville-Neil perror("not ok 1 - could not send packet");
144e162ea60SGeorge V. Neville-Neil exit(1);
145e162ea60SGeorge V. Neville-Neil }
146e162ea60SGeorge V. Neville-Neil
147e162ea60SGeorge V. Neville-Neil if (sysctlbyname("net.link.ether.arp.stats", &arpstat, &len,
148e162ea60SGeorge V. Neville-Neil NULL, 0) < 0) {
149e162ea60SGeorge V. Neville-Neil perror("not ok 1 - could not get new arp stats");
150e162ea60SGeorge V. Neville-Neil exit(1);
151e162ea60SGeorge V. Neville-Neil }
152e162ea60SGeorge V. Neville-Neil
153e162ea60SGeorge V. Neville-Neil if (arpstat.dropped != (dropped + 1)) {
154e162ea60SGeorge V. Neville-Neil printf("not ok 1 - Failed to drop one packet: before"
155e162ea60SGeorge V. Neville-Neil " %ld after %ld\n", dropped, arpstat.dropped);
156e162ea60SGeorge V. Neville-Neil exit(1);
157e162ea60SGeorge V. Neville-Neil }
158e162ea60SGeorge V. Neville-Neil
159e162ea60SGeorge V. Neville-Neil printf("ok\n");
160e162ea60SGeorge V. Neville-Neil return (0);
161e162ea60SGeorge V. Neville-Neil }
162