Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / env / common / vera / niu_ippktgen / C / libnet / src / libnet_pkt.c
CommitLineData
86530b38
AT
1/*
2 * $Id: libnet_pkt.c,v 1.19 2005/11/29 22:48:29 carlosc Exp $
3 *
4 * libnet
5 * libnet_pkt.c - routines.
6 *
7 * Copyright (c) 1998 - 2004 Mike D. Schiffman <mike@infonexus.com>
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 */
32
33#if (HAVE_CONFIG_H)
34#include "../include/config.h"
35#endif
36#if (!(_WIN32) || (__CYGWIN__))
37#include "../include/libnet.h"
38#else
39#include "../include/win32/libnet.h"
40#endif
41
42libnet_t *
43libnet_init_pkt(int injection_type, char *device, char *err_buf)
44{
45 libnet_t *l = NULL;
46
47#if 0
48#if !defined(__WIN32__)
49 if (getuid() && geteuid())
50 {
51 snprintf(err_buf, LIBNET_ERRBUF_SIZE,
52 "%s(): UID or EUID of 0 required\n", __func__);
53 goto bad;
54 }
55#else
56 WSADATA wsaData;
57
58 if ((WSAStartup(0x0202, &wsaData)) != 0)
59 {
60 snprintf(err_buf, LIBNET_ERRBUF_SIZE,
61 "%s(): unable to initialize winsock 2\n", __func__);
62 goto bad;
63 }
64#endif
65#endif
66
67 l = (libnet_t *)malloc(sizeof (libnet_t));
68 if (l == NULL)
69 {
70 snprintf(err_buf, LIBNET_ERRBUF_SIZE, "%s(): malloc(): %s\n", __func__,
71 strerror(errno));
72 goto bad;
73 }
74
75 memset(l, 0, sizeof (*l));
76
77 l->injection_type = injection_type;
78 l->ptag_state = LIBNET_PTAG_INITIALIZER;
79 l->device = (device ? strdup(device) : NULL);
80
81 strncpy(l->label, LIBNET_LABEL_DEFAULT, LIBNET_LABEL_SIZE);
82 l->label[sizeof(l->label)] = '\0';
83
84#if 0
85 switch (l->injection_type)
86 {
87 case LIBNET_LINK:
88 case LIBNET_LINK_ADV:
89 if (libnet_select_device(l) == -1)
90 {
91 snprintf(err_buf, LIBNET_ERRBUF_SIZE, l->err_buf);
92 goto bad;
93 }
94 if (libnet_open_link(l) == -1)
95 {
96 snprintf(err_buf, LIBNET_ERRBUF_SIZE, l->err_buf);
97 goto bad;
98 }
99 break;
100 case LIBNET_RAW4:
101 case LIBNET_RAW4_ADV:
102 if (libnet_open_raw4(l) == -1)
103 {
104 snprintf(err_buf, LIBNET_ERRBUF_SIZE, l->err_buf);
105 goto bad;
106 }
107 break;
108 case LIBNET_RAW6:
109 case LIBNET_RAW6_ADV:
110 if (libnet_open_raw6(l) == -1)
111 {
112 snprintf(err_buf, LIBNET_ERRBUF_SIZE, l->err_buf);
113 goto bad;
114 }
115 break;
116 default:
117 snprintf(err_buf, LIBNET_ERRBUF_SIZE,
118 "%s(): unsupported injection type\n", __func__);
119 goto bad;
120 break;
121 }
122#endif
123
124 return (l);
125
126bad:
127 if (l)
128 {
129 libnet_destroy(l);
130 }
131 return (NULL);
132}
133
134
135
136int
137libnet_pblock_coalesce_pkt(libnet_t *l, u_int8_t **packet, u_int32_t *size, u_int32_t align);
138
139void
140libnet_print_pkt(u_int8_t *pktbuf, u_int32_t pktlen)
141{
142 int i;
143
144 fprintf(stderr, "pktbuf = 0x%p, pktlen = %d\n", pktbuf, pktlen);
145 for (i=0; i<pktlen; i++) {
146 if(!(i%16)) fprintf (stderr,"\n %06d\t\t",i);
147 fprintf(stderr,"%02x ", pktbuf[i]);
148 }
149 fprintf (stderr,"\n");
150}
151
152
153int
154libnet_write_pkt(libnet_t *l, u_int8_t **packet, u_int32_t *len, u_int32_t align)
155{
156 int c;
157#if 0
158 u_int32_t len;
159 u_int8_t *packet = NULL;
160#endif
161
162 if (l == NULL)
163 {
164 return (-1);
165 }
166
167 c = libnet_pblock_coalesce_pkt(l, packet, len, align);
168 if (c == - 1)
169 {
170 /* err msg set in libnet_pblock_coalesce() */
171 return (-1);
172 }
173
174#if 0
175 /* assume error */
176 c = -1;
177 switch (l->injection_type)
178 {
179 case LIBNET_RAW4:
180 case LIBNET_RAW4_ADV:
181 if (len > LIBNET_MAX_PACKET)
182 {
183 snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
184 "%s(): packet is too large (%d bytes)\n",
185 __func__, len);
186 goto done;
187 }
188 c = libnet_write_raw_ipv4(l, packet, len);
189 break;
190 case LIBNET_RAW6:
191 case LIBNET_RAW6_ADV:
192 c = libnet_write_raw_ipv6(l, packet, len);
193 break;
194 case LIBNET_LINK:
195 case LIBNET_LINK_ADV:
196 c = libnet_write_link(l, packet, len);
197 break;
198 default:
199 snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
200 "%s(): unsuported injection type\n", __func__);
201 goto done;
202 }
203#endif
204
205 /* do statistics */
206 if (c == *len)
207 {
208 l->stats.packets_sent++;
209 l->stats.bytes_written += c;
210 }
211 else
212 {
213 l->stats.packet_errors++;
214 /*
215 * XXX - we probably should have a way to retrieve the number of
216 * bytes actually written (since we might have written something).
217 */
218 if (c > 0)
219 {
220 l->stats.bytes_written += c;
221 }
222 }
223done:
224#if 0
225 /*
226 * Restore original pointer address so free won't complain about a
227 * modified chunk pointer.
228 */
229 if (l->aligner > 0)
230 {
231 *packet = *packet - l->aligner;
232 }
233
234 free(packet);
235#endif
236 return (c);
237}
238
239
240int
241libnet_pblock_coalesce_pkt(libnet_t *l, u_int8_t **packet, u_int32_t *size, u_int32_t align)
242{
243 libnet_pblock_t *p, *q;
244 u_int32_t c, n;
245
246 /*
247 * Determine the offset required to keep memory aligned (strict
248 * architectures like solaris enforce this, but's a good practice
249 * either way). This is only required on the link layer with the
250 * 14 byte ethernet offset (others are similarly unkind).
251 */
252#if 1
253 if (l->injection_type == LIBNET_LINK ||
254 l->injection_type == LIBNET_LINK_ADV)
255 {
256 /* 8 byte alignment should work */
257 if (align)
258 l->aligner = align - (l->link_offset % align);
259 else
260 l->aligner = 0;
261 }
262 else
263 {
264 l->aligner = 0;
265 }
266#else
267 l->aligner = align;
268#endif
269
270/********** fprintf(stderr, "libnet_pblock_coalesce_pkt: aligner = %d\n", l->aligner);***/
271
272 *packet = malloc(l->aligner + l->total_size);
273 if (*packet == NULL)
274 {
275 snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): malloc(): %s\n",
276 __func__, strerror(errno));
277 return (-1);
278 }
279
280 memset(*packet, 0, l->aligner + l->total_size);
281
282 if (l->injection_type == LIBNET_RAW4 &&
283 l->pblock_end->type == LIBNET_PBLOCK_IPV4_H)
284 {
285 libnet_pblock_setflags(l->pblock_end, LIBNET_PBLOCK_DO_CHECKSUM);
286#if 0
287 libnet_pblock_setflags(l->pblock_end, 0x0);
288#endif
289 }
290
291 /* additional sanity checks to perform if we're not in advanced mode */
292 if (!(l->injection_type & LIBNET_ADV_MASK))
293 {
294 switch (l->injection_type)
295 {
296 case LIBNET_LINK:
297 if ((l->pblock_end->type != LIBNET_PBLOCK_TOKEN_RING_H) &&
298 (l->pblock_end->type != LIBNET_PBLOCK_FDDI_H) &&
299 (l->pblock_end->type != LIBNET_PBLOCK_ETH_H) &&
300 (l->pblock_end->type != LIBNET_PBLOCK_802_1Q_H) &&
301 (l->pblock_end->type != LIBNET_PBLOCK_ISL_H) &&
302 (l->pblock_end->type != LIBNET_PBLOCK_802_3_H))
303 {
304 snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
305 "%s(): packet assembly cannot find a layer 2 header\n",
306 __func__);
307 return (-1);
308 }
309 break;
310 case LIBNET_RAW4:
311 if ((l->pblock_end->type != LIBNET_PBLOCK_IPV4_H))
312 {
313 snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
314 "%s(): packet assembly cannot find an IPv4 header\n",
315 __func__);
316 return (-1);
317 }
318 break;
319 case LIBNET_RAW6:
320 if ((l->pblock_end->type != LIBNET_PBLOCK_IPV6_H))
321 {
322 snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
323 "%s(): packet assembly cannot find an IPv6 header\n",
324 __func__);
325 return (-1);
326 }
327 break;
328 default:
329 /* we should not end up here ever */
330 snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
331 "%s(): suddenly the dungeon collapses -- you die\n",
332 __func__);
333 return (-1);
334 break;
335 }
336 }
337
338 q = NULL;
339 for (n = l->aligner + l->total_size, p = l->protocol_blocks; p || q; )
340 {
341
342 if (q)
343 {
344 p = p->next;
345 }
346#if 0
347 if (p != NULL) {
348/***********/fprintf(stderr, "libnet_pblock_coalesce_pkt: p(%d) proto=%d, p->next(%d)\n", p, libnet_pblock_p2p(p->type), p->next);
349 } else {
350 fprintf(stderr, "libnet_pblock_coalesce_pkt: p is null");
351 }
352#endif
353 if (p)
354 {
355 n -= p->b_len;
356 /* copy over the packet chunk */
357 memcpy(*packet + n, p->buf, p->b_len);
358/*************fprintf(stderr, "libnet_pblock_coalesce_pkt: Copying over %d bytes from the end\n", p->b_len);*/
359 }
360 if (q)
361 {
362 if (p == NULL || ((p->flags) & LIBNET_PBLOCK_DO_CHECKSUM))
363#if 0
364 if (p == NULL || ((p->flags) & 0x0))
365#endif
366 {
367 if ((q->flags) & LIBNET_PBLOCK_DO_CHECKSUM)
368#if 0
369 if ((q->flags) & 0x0)
370#endif
371 {
372 int offset = (l->total_size + l->aligner) - q->ip_offset;
373/******fprintf(stderr, "libnet_pblock_coalesce_pkt: Calling libnet_do_checksum with the packet offset set at %d, ip_offset being %d, and buf %d, proto %d, len %d\n", offset, q->ip_offset, (unsigned int)(*packet + offset), libnet_pblock_p2p(q->type), q->h_len);*/
374
375 c = libnet_do_checksum(l, *packet + offset,
376 libnet_pblock_p2p(q->type), q->h_len);
377 if (c == -1)
378 {
379 /* err msg set in libnet_do_checksum() */
380 return (-1);
381 }
382 }
383 q = p;
384 }
385 }
386 else
387 {
388 q = p;
389 }
390 }
391 *size = l->aligner + l->total_size;
392
393 /*
394 * Set the packet pointer to the true beginning of the packet and set
395 * the size for transmission.
396 */
397 if ((l->injection_type == LIBNET_LINK ||
398 l->injection_type == LIBNET_LINK_ADV) && l->aligner)
399 {
400 *packet += l->aligner;
401 *size -= l->aligner;
402 }
403#if 0
404 return (1);
405#endif
406 return (*size);
407}
408
409/* EOF */