xref: /dragonfly/contrib/tcpdump/netdissect.c (revision ed775ee7)
1411677aeSAaron LI /*
2411677aeSAaron LI  * Copyright (c) 1988-1997
3411677aeSAaron LI  *	The Regents of the University of California.  All rights reserved.
4411677aeSAaron LI  *
5411677aeSAaron LI  * Copyright (c) 1998-2012  Michael Richardson <mcr@tcpdump.org>
6411677aeSAaron LI  *      The TCPDUMP project
7411677aeSAaron LI  *
8411677aeSAaron LI  * Redistribution and use in source and binary forms, with or without
9411677aeSAaron LI  * modification, are permitted provided that: (1) source code distributions
10411677aeSAaron LI  * retain the above copyright notice and this paragraph in its entirety, (2)
11411677aeSAaron LI  * distributions including binary code include the above copyright notice and
12411677aeSAaron LI  * this paragraph in its entirety in the documentation or other materials
13411677aeSAaron LI  * provided with the distribution, and (3) all advertising materials mentioning
14411677aeSAaron LI  * features or use of this software display the following acknowledgement:
15411677aeSAaron LI  * ``This product includes software developed by the University of California,
16411677aeSAaron LI  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
17411677aeSAaron LI  * the University nor the names of its contributors may be used to endorse
18411677aeSAaron LI  * or promote products derived from this software without specific prior
19411677aeSAaron LI  * written permission.
20411677aeSAaron LI  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
21411677aeSAaron LI  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
22411677aeSAaron LI  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
23411677aeSAaron LI  */
24411677aeSAaron LI 
25411677aeSAaron LI #ifdef HAVE_CONFIG_H
26*ed775ee7SAntonio Huete Jimenez #include <config.h>
27411677aeSAaron LI #endif
28411677aeSAaron LI 
29*ed775ee7SAntonio Huete Jimenez #include "netdissect-stdinc.h"
30411677aeSAaron LI #include "netdissect.h"
31411677aeSAaron LI #include <string.h>
32411677aeSAaron LI #include <stdio.h>
33*ed775ee7SAntonio Huete Jimenez #include <stdlib.h>
34411677aeSAaron LI 
35411677aeSAaron LI #ifdef USE_LIBSMI
36411677aeSAaron LI #include <smi.h>
37411677aeSAaron LI #endif
38411677aeSAaron LI 
39411677aeSAaron LI /*
40411677aeSAaron LI  * Initialize anything that must be initialized before dissecting
41411677aeSAaron LI  * packets.
42411677aeSAaron LI  *
43411677aeSAaron LI  * This should be called at the beginning of the program; it does
44411677aeSAaron LI  * not need to be called, and should not be called, for every
45411677aeSAaron LI  * netdissect_options structure.
46411677aeSAaron LI  */
47411677aeSAaron LI int
nd_init(char * errbuf,size_t errbuf_size)48411677aeSAaron LI nd_init(char *errbuf, size_t errbuf_size)
49411677aeSAaron LI {
50411677aeSAaron LI #ifdef _WIN32
51411677aeSAaron LI 	WORD wVersionRequested;
52411677aeSAaron LI 	WSADATA wsaData;
53411677aeSAaron LI 	int err;
54411677aeSAaron LI 
55411677aeSAaron LI 	/*
56411677aeSAaron LI 	 * Request Winsock 2.2; we expect Winsock 2.
57411677aeSAaron LI 	 */
58411677aeSAaron LI 	wVersionRequested = MAKEWORD(2, 2);
59411677aeSAaron LI 	err = WSAStartup(wVersionRequested, &wsaData);
60411677aeSAaron LI 	if (err != 0) {
61411677aeSAaron LI 		strlcpy(errbuf, "Attempting to initialize Winsock failed",
62411677aeSAaron LI 		    errbuf_size);
63411677aeSAaron LI 		return (-1);
64411677aeSAaron LI 	}
65411677aeSAaron LI #endif /* _WIN32 */
66411677aeSAaron LI 
67411677aeSAaron LI #ifdef USE_LIBSMI
68411677aeSAaron LI 	/*
69411677aeSAaron LI 	 * XXX - should we just fail if this fails?  Some of the
70411677aeSAaron LI 	 * libsmi calls may fail.
71411677aeSAaron LI 	 */
72411677aeSAaron LI 	smiInit("tcpdump");
73411677aeSAaron LI #endif
74411677aeSAaron LI 
75411677aeSAaron LI 	/*
76411677aeSAaron LI 	 * Clears the error buffer, and uses it so we don't get
77411677aeSAaron LI 	 * "unused argument" warnings at compile time.
78411677aeSAaron LI 	 */
79411677aeSAaron LI 	strlcpy(errbuf, "", errbuf_size);
80411677aeSAaron LI 	return (0);
81411677aeSAaron LI }
82411677aeSAaron LI 
83411677aeSAaron LI /*
84411677aeSAaron LI  * Clean up anything that ndo_init() did.
85411677aeSAaron LI  */
86411677aeSAaron LI void
nd_cleanup(void)87411677aeSAaron LI nd_cleanup(void)
88411677aeSAaron LI {
89411677aeSAaron LI #ifdef USE_LIBSMI
90411677aeSAaron LI 	/*
91411677aeSAaron LI 	 * This appears, in libsmi 0.4.8, to do nothing if smiInit()
92411677aeSAaron LI 	 * wasn't done or failed, so we call it unconditionally.
93411677aeSAaron LI 	 */
94411677aeSAaron LI 	smiExit();
95411677aeSAaron LI #endif
96411677aeSAaron LI 
97411677aeSAaron LI #ifdef _WIN32
98411677aeSAaron LI 	/*
99411677aeSAaron LI 	 * Undo the WSAStartup() call above.
100411677aeSAaron LI 	 */
101411677aeSAaron LI 	WSACleanup();
102411677aeSAaron LI #endif
103411677aeSAaron LI }
104411677aeSAaron LI 
105411677aeSAaron LI int
nd_have_smi_support(void)106411677aeSAaron LI nd_have_smi_support(void)
107411677aeSAaron LI {
108411677aeSAaron LI #ifdef USE_LIBSMI
109411677aeSAaron LI 	return (1);
110411677aeSAaron LI #else
111411677aeSAaron LI 	return (0);
112411677aeSAaron LI #endif
113411677aeSAaron LI }
114411677aeSAaron LI 
115411677aeSAaron LI /*
116411677aeSAaron LI  * Indicates whether an SMI module has been loaded, so that we can use
117411677aeSAaron LI  * libsmi to translate OIDs.
118411677aeSAaron LI  */
119411677aeSAaron LI int nd_smi_module_loaded;
120411677aeSAaron LI 
121411677aeSAaron LI int
nd_load_smi_module(const char * module,char * errbuf,size_t errbuf_size)122411677aeSAaron LI nd_load_smi_module(const char *module, char *errbuf, size_t errbuf_size)
123411677aeSAaron LI {
124411677aeSAaron LI #ifdef USE_LIBSMI
125411677aeSAaron LI 	if (smiLoadModule(module) == 0) {
126411677aeSAaron LI 		snprintf(errbuf, errbuf_size, "could not load MIB module %s",
127411677aeSAaron LI 		    module);
128411677aeSAaron LI 		return (-1);
129411677aeSAaron LI 	}
130411677aeSAaron LI 	nd_smi_module_loaded = 1;
131411677aeSAaron LI 	return (0);
132411677aeSAaron LI #else
133411677aeSAaron LI 	snprintf(errbuf, errbuf_size, "MIB module %s not loaded: no libsmi support",
134411677aeSAaron LI 	    module);
135411677aeSAaron LI 	return (-1);
136411677aeSAaron LI #endif
137411677aeSAaron LI }
138411677aeSAaron LI 
139411677aeSAaron LI const char *
nd_smi_version_string(void)140411677aeSAaron LI nd_smi_version_string(void)
141411677aeSAaron LI {
142411677aeSAaron LI #ifdef USE_LIBSMI
143411677aeSAaron LI 	return (smi_version_string);
144411677aeSAaron LI #else
145411677aeSAaron LI 	return (NULL);
146411677aeSAaron LI #endif
147411677aeSAaron LI }
148*ed775ee7SAntonio Huete Jimenez 
149*ed775ee7SAntonio Huete Jimenez 
150*ed775ee7SAntonio Huete Jimenez int
nd_push_buffer(netdissect_options * ndo,u_char * new_buffer,const u_char * new_packetp,const u_char * new_snapend)151*ed775ee7SAntonio Huete Jimenez nd_push_buffer(netdissect_options *ndo, u_char *new_buffer,
152*ed775ee7SAntonio Huete Jimenez     const u_char *new_packetp, const u_char *new_snapend)
153*ed775ee7SAntonio Huete Jimenez {
154*ed775ee7SAntonio Huete Jimenez 	struct netdissect_saved_packet_info *ndspi;
155*ed775ee7SAntonio Huete Jimenez 
156*ed775ee7SAntonio Huete Jimenez 	ndspi = (struct netdissect_saved_packet_info *)malloc(sizeof(struct netdissect_saved_packet_info));
157*ed775ee7SAntonio Huete Jimenez 	if (ndspi == NULL)
158*ed775ee7SAntonio Huete Jimenez 		return (0);	/* fail */
159*ed775ee7SAntonio Huete Jimenez 	ndspi->ndspi_buffer = new_buffer;
160*ed775ee7SAntonio Huete Jimenez 	ndspi->ndspi_packetp = ndo->ndo_packetp;
161*ed775ee7SAntonio Huete Jimenez 	ndspi->ndspi_snapend = ndo->ndo_snapend;
162*ed775ee7SAntonio Huete Jimenez 	ndspi->ndspi_prev = ndo->ndo_packet_info_stack;
163*ed775ee7SAntonio Huete Jimenez 
164*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_packetp = new_packetp;
165*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_snapend = new_snapend;
166*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_packet_info_stack = ndspi;
167*ed775ee7SAntonio Huete Jimenez 
168*ed775ee7SAntonio Huete Jimenez 	return (1);	/* success */
169*ed775ee7SAntonio Huete Jimenez }
170*ed775ee7SAntonio Huete Jimenez 
171*ed775ee7SAntonio Huete Jimenez /*
172*ed775ee7SAntonio Huete Jimenez  * Set a new snapshot end to the minimum of the existing snapshot end
173*ed775ee7SAntonio Huete Jimenez  * and the new snapshot end.
174*ed775ee7SAntonio Huete Jimenez  */
175*ed775ee7SAntonio Huete Jimenez int
nd_push_snapend(netdissect_options * ndo,const u_char * new_snapend)176*ed775ee7SAntonio Huete Jimenez nd_push_snapend(netdissect_options *ndo, const u_char *new_snapend)
177*ed775ee7SAntonio Huete Jimenez {
178*ed775ee7SAntonio Huete Jimenez 	struct netdissect_saved_packet_info *ndspi;
179*ed775ee7SAntonio Huete Jimenez 
180*ed775ee7SAntonio Huete Jimenez 	ndspi = (struct netdissect_saved_packet_info *)malloc(sizeof(struct netdissect_saved_packet_info));
181*ed775ee7SAntonio Huete Jimenez 	if (ndspi == NULL)
182*ed775ee7SAntonio Huete Jimenez 		return (0);	/* fail */
183*ed775ee7SAntonio Huete Jimenez 	ndspi->ndspi_buffer = NULL;	/* no new buffer */
184*ed775ee7SAntonio Huete Jimenez 	ndspi->ndspi_packetp = ndo->ndo_packetp;
185*ed775ee7SAntonio Huete Jimenez 	ndspi->ndspi_snapend = ndo->ndo_snapend;
186*ed775ee7SAntonio Huete Jimenez 	ndspi->ndspi_prev = ndo->ndo_packet_info_stack;
187*ed775ee7SAntonio Huete Jimenez 
188*ed775ee7SAntonio Huete Jimenez 	/* No new packet pointer, either */
189*ed775ee7SAntonio Huete Jimenez 	if (new_snapend < ndo->ndo_snapend)
190*ed775ee7SAntonio Huete Jimenez 		ndo->ndo_snapend = new_snapend;
191*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_packet_info_stack = ndspi;
192*ed775ee7SAntonio Huete Jimenez 
193*ed775ee7SAntonio Huete Jimenez 	return (1);	/* success */
194*ed775ee7SAntonio Huete Jimenez }
195*ed775ee7SAntonio Huete Jimenez 
196*ed775ee7SAntonio Huete Jimenez /*
197*ed775ee7SAntonio Huete Jimenez  * Change an already-pushed snapshot end.  This may increase the
198*ed775ee7SAntonio Huete Jimenez  * snapshot end, as it may be used, for example, for a Jumbo Payload
199*ed775ee7SAntonio Huete Jimenez  * option in IPv6.  It must not increase it past the snapshot length
200*ed775ee7SAntonio Huete Jimenez  * atop which the current one was pushed, however.
201*ed775ee7SAntonio Huete Jimenez  */
202*ed775ee7SAntonio Huete Jimenez void
nd_change_snapend(netdissect_options * ndo,const u_char * new_snapend)203*ed775ee7SAntonio Huete Jimenez nd_change_snapend(netdissect_options *ndo, const u_char *new_snapend)
204*ed775ee7SAntonio Huete Jimenez {
205*ed775ee7SAntonio Huete Jimenez 	struct netdissect_saved_packet_info *ndspi;
206*ed775ee7SAntonio Huete Jimenez 
207*ed775ee7SAntonio Huete Jimenez 	ndspi = ndo->ndo_packet_info_stack;
208*ed775ee7SAntonio Huete Jimenez 	if (ndspi->ndspi_prev != NULL) {
209*ed775ee7SAntonio Huete Jimenez 		if (new_snapend <= ndspi->ndspi_prev->ndspi_snapend)
210*ed775ee7SAntonio Huete Jimenez 			ndo->ndo_snapend = new_snapend;
211*ed775ee7SAntonio Huete Jimenez 	} else {
212*ed775ee7SAntonio Huete Jimenez 		if (new_snapend < ndo->ndo_snapend)
213*ed775ee7SAntonio Huete Jimenez 			ndo->ndo_snapend = new_snapend;
214*ed775ee7SAntonio Huete Jimenez 	}
215*ed775ee7SAntonio Huete Jimenez }
216*ed775ee7SAntonio Huete Jimenez 
217*ed775ee7SAntonio Huete Jimenez void
nd_pop_packet_info(netdissect_options * ndo)218*ed775ee7SAntonio Huete Jimenez nd_pop_packet_info(netdissect_options *ndo)
219*ed775ee7SAntonio Huete Jimenez {
220*ed775ee7SAntonio Huete Jimenez 	struct netdissect_saved_packet_info *ndspi;
221*ed775ee7SAntonio Huete Jimenez 
222*ed775ee7SAntonio Huete Jimenez 	ndspi = ndo->ndo_packet_info_stack;
223*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_packetp = ndspi->ndspi_packetp;
224*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_snapend = ndspi->ndspi_snapend;
225*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_packet_info_stack = ndspi->ndspi_prev;
226*ed775ee7SAntonio Huete Jimenez 
227*ed775ee7SAntonio Huete Jimenez 	free(ndspi->ndspi_buffer);
228*ed775ee7SAntonio Huete Jimenez 	free(ndspi);
229*ed775ee7SAntonio Huete Jimenez }
230*ed775ee7SAntonio Huete Jimenez 
231*ed775ee7SAntonio Huete Jimenez void
nd_pop_all_packet_info(netdissect_options * ndo)232*ed775ee7SAntonio Huete Jimenez nd_pop_all_packet_info(netdissect_options *ndo)
233*ed775ee7SAntonio Huete Jimenez {
234*ed775ee7SAntonio Huete Jimenez 	while (ndo->ndo_packet_info_stack != NULL)
235*ed775ee7SAntonio Huete Jimenez 		nd_pop_packet_info(ndo);
236*ed775ee7SAntonio Huete Jimenez }
237