Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / env / common / vera / niu_ippktgen / C / libnet / src / libnet_write.c
CommitLineData
86530b38
AT
1/*
2 * $Id: libnet_write.c,v 1.21 2005/11/29 21:52:41 carlosc Exp $
3 *
4 * libnet
5 * libnet_write.c - writes a prebuilt packet to the network
6 *
7 * Copyright (c) 1998 - 2004 Mike D. Schiffman <mike@infonexus.com>
8 * All rights reserved.
9 * win32 specific code
10 * Copyright (c) 2002 - 2003 Roberto Larcher <roberto.larcher@libero.it>
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 */
34
35#if (HAVE_CONFIG_H)
36#include "../include/config.h"
37#endif
38#if (!(_WIN32) || (__CYGWIN__))
39#include "../include/libnet.h"
40#else
41#include "../include/win32/libnet.h"
42#include "../include/win32/config.h"
43#include "packet32.h"
44#include "Ntddndis.h"
45#endif
46
47int
48libnet_write(libnet_t *l)
49{
50 int c;
51 u_int32_t len;
52 u_int8_t *packet = NULL;
53
54 if (l == NULL)
55 {
56 return (-1);
57 }
58
59 c = libnet_pblock_coalesce(l, &packet, &len);
60 if (c == - 1)
61 {
62 /* err msg set in libnet_pblock_coalesce() */
63 return (-1);
64 }
65
66 /* assume error */
67 c = -1;
68 switch (l->injection_type)
69 {
70 case LIBNET_RAW4:
71 case LIBNET_RAW4_ADV:
72 if (len > LIBNET_MAX_PACKET)
73 {
74 snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
75 "%s(): packet is too large (%d bytes)\n",
76 __func__, len);
77 goto done;
78 }
79 c = libnet_write_raw_ipv4(l, packet, len);
80 break;
81 case LIBNET_RAW6:
82 case LIBNET_RAW6_ADV:
83 c = libnet_write_raw_ipv6(l, packet, len);
84 break;
85 case LIBNET_LINK:
86 case LIBNET_LINK_ADV:
87 c = libnet_write_link(l, packet, len);
88 break;
89 default:
90 snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
91 "%s(): unsuported injection type\n", __func__);
92 goto done;
93 }
94
95 /* do statistics */
96 if (c == len)
97 {
98 l->stats.packets_sent++;
99 l->stats.bytes_written += c;
100 }
101 else
102 {
103 l->stats.packet_errors++;
104 /*
105 * XXX - we probably should have a way to retrieve the number of
106 * bytes actually written (since we might have written something).
107 */
108 if (c > 0)
109 {
110 l->stats.bytes_written += c;
111 }
112 }
113done:
114 /*
115 * Restore original pointer address so free won't complain about a
116 * modified chunk pointer.
117 */
118 if (l->aligner > 0)
119 {
120 packet = packet - l->aligner;
121 }
122 free(packet);
123 return (c);
124}
125
126#if defined (__WIN32__)
127libnet_ptag_t
128libnet_win32_build_fake_ethernet(u_int8_t *dst, u_int8_t *src, u_int16_t type,
129u_int8_t *payload, u_int32_t payload_s, u_int8_t *packet, libnet_t *l,
130libnet_ptag_t ptag)
131{
132 struct libnet_ethernet_hdr eth_hdr;
133
134 if (!packet)
135 {
136 return (-1);
137 }
138
139 memset(&eth_hdr, 0, sizeof(eth_hdr));
140 eth_hdr.ether_type = htons(type);
141 memcpy(eth_hdr.ether_dhost, dst, ETHER_ADDR_LEN); /* destination address */
142 memcpy(eth_hdr.ether_shost, src, ETHER_ADDR_LEN); /* source address */
143
144 if (payload && payload_s)
145 {
146 /*
147 * Unchecked runtime error for buf + ETH_H payload to be greater than
148 * the allocated heap memory.
149 */
150 memcpy(packet + LIBNET_ETH_H, payload, payload_s);
151 }
152 memcpy(packet, &eth_hdr, sizeof(eth_hdr));
153 return (1);
154}
155
156libnet_ptag_t
157libnet_win32_build_fake_token(u_int8_t *dst, u_int8_t *src, u_int16_t type,
158u_int8_t *payload, u_int32_t payload_s, u_int8_t *packet, libnet_t *l,
159libnet_ptag_t ptag)
160{
161 struct libnet_token_ring_hdr token_ring_hdr;
162
163 if (!packet)
164 {
165 return (-1);
166 }
167
168 memset(&token_ring_hdr, 0, sizeof(token_ring_hdr));
169 token_ring_hdr.token_ring_access_control = 0x10;
170 token_ring_hdr.token_ring_frame_control = 0x40;
171 token_ring_hdr.token_ring_llc_dsap = 0xaa;
172 token_ring_hdr.token_ring_llc_ssap = 0xaa;
173 token_ring_hdr.token_ring_llc_control_field = 0x03;
174 token_ring_hdr.token_ring_type = htons(type);
175 memcpy(token_ring_hdr.token_ring_dhost, dst, ETHER_ADDR_LEN);
176 memcpy(token_ring_hdr.token_ring_shost, libnet_get_hwaddr(l),
177 ETHER_ADDR_LEN);
178
179 if (payload && payload_s)
180 {
181 /*
182 * Unchecked runtime error for buf + ETH_H payload to be greater than
183 * the allocated heap memory.
184 */
185 memcpy(packet + LIBNET_TOKEN_RING_H, payload, payload_s);
186 }
187 memcpy(packet, &token_ring_hdr, sizeof(token_ring_hdr));
188 return (1);
189}
190
191
192int
193libnet_win32_write_raw_ipv4(libnet_t *l, u_int8_t *payload, u_int32_t payload_s)
194{
195 static BYTE dst[ETHER_ADDR_LEN];
196 static BYTE src[ETHER_ADDR_LEN];
197
198 u_int8_t *packet = NULL;
199 u_int32_t packet_s;
200
201 LPPACKET lpPacket = NULL;
202 DWORD remoteip = 0;
203 DWORD BytesTransfered;
204 NetType type;
205 struct libnet_ipv4_hdr *ip_hdr = NULL;
206
207 memset(dst, 0, sizeof(dst));
208 memset(src, 0, sizeof(src));
209
210 packet_s = payload_s + l->link_offset;
211 packet = (u_int8_t *)malloc(packet_s);
212 if (packet == NULL)
213 {
214 snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
215 "%s(): failed to allocate packet\n", __func__);
216 return (-1);
217 }
218
219 /* we have to do the IP checksum */
220 if (libnet_do_checksum(l, payload, IPPROTO_IP, LIBNET_IPV4_H) == -1)
221 {
222 /* error msg set in libnet_do_checksum */
223 return (-1);
224 }
225
226 /* MACs, IPs and other stuff... */
227 ip_hdr = (struct libnet_ipv4_hdr *)payload;
228 memcpy(src, libnet_get_hwaddr(l), sizeof(src));
229 remoteip = ip_hdr->ip_dst.S_un.S_addr;
230
231 /* check if the remote station is the local station */
232 if (remoteip == libnet_get_ipaddr4(l))
233 {
234 memcpy(dst, src, sizeof(dst));
235 }
236 else
237 {
238 memcpy(dst, libnet_win32_get_remote_mac(l, remoteip), sizeof(dst));
239 }
240
241 PacketGetNetType(l->lpAdapter, &type);
242
243 switch(type.LinkType)
244 {
245 case NdisMedium802_3:
246 libnet_win32_build_fake_ethernet(dst, src, ETHERTYPE_IP, payload,
247 payload_s, packet, l , 0);
248 break;
249 case NdisMedium802_5:
250 libnet_win32_build_fake_token(dst, src, ETHERTYPE_IP, payload,
251 payload_s, packet, l, 0);
252 break;
253 case NdisMediumFddi:
254 break;
255 case NdisMediumWan:
256 case NdisMediumAtm:
257 case NdisMediumArcnet878_2:
258 default:
259 snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
260 "%s(): network type (%d) is not supported\n", __func__,
261 type.LinkType);
262 return (-1);
263 break;
264 }
265
266 BytesTransfered = -1;
267 if ((lpPacket = PacketAllocatePacket()) == NULL)
268 {
269 snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
270 "%s(): failed to allocate the LPPACKET structure\n", __func__);
271 return (-1);
272 }
273
274 PacketInitPacket(lpPacket, packet, packet_s);
275
276 /* PacketSendPacket returns a BOOLEAN */
277 if (PacketSendPacket(l->lpAdapter, lpPacket, TRUE))
278 {
279 BytesTransfered = packet_s;
280 }
281
282 PacketFreePacket(lpPacket);
283 free(packet);
284
285 return (BytesTransfered);
286}
287
288int
289libnet_write_raw_ipv4(libnet_t *l, u_int8_t *packet, u_int32_t size)
290{
291 return (libnet_win32_write_raw_ipv4(l, packet, size));
292}
293
294int
295libnet_write_raw_ipv6(libnet_t *l, u_int8_t *packet, u_int32_t size)
296{
297 /* no difference in win32 */
298 return (libnet_write_raw_ipv4(l, packet, size));
299}
300
301#else /* __WIN32__ */
302
303int
304libnet_write_raw_ipv4(libnet_t *l, u_int8_t *packet, u_int32_t size)
305{
306 int c;
307 struct sockaddr_in sin;
308 struct libnet_ipv4_hdr *ip_hdr;
309
310 if (l == NULL)
311 {
312 return (-1);
313 }
314
315 ip_hdr = (struct libnet_ipv4_hdr *)packet;
316
317#if (LIBNET_BSD_BYTE_SWAP)
318 /*
319 * For link access, we don't need to worry about the inconsistencies of
320 * certain BSD kernels. However, raw socket nuances abound. Certain
321 * BSD implmentations require the ip_len and ip_off fields to be in host
322 * byte order.
323 */
324 ip_hdr->ip_len = FIX(ip_hdr->ip_len);
325 ip_hdr->ip_off = FIX(ip_hdr->ip_off);
326#endif /* LIBNET_BSD_BYTE_SWAP */
327
328 memset(&sin, 0, sizeof(sin));
329 sin.sin_family = AF_INET;
330 sin.sin_addr.s_addr = ip_hdr->ip_dst.s_addr;
331#if (__WIN32__)
332 /* set port for TCP */
333 /*
334 * XXX - should first check to see if there's a pblock for a TCP
335 * header, if not we can use a dummy value for the port.
336 */
337 if (ip_hdr->ip_p == 6)
338 {
339 struct libnet_tcp_hdr *tcph_p =
340 (struct libnet_tcp_hdr *)(packet + (ip_hdr->ip_hl << 2));
341 sin.sin_port = tcph_p->th_dport;
342 }
343 /* set port for UDP */
344 /*
345 * XXX - should first check to see if there's a pblock for a UDP
346 * header, if not we can use a dummy value for the port.
347 */
348 else if (ip_hdr->ip_p == 17)
349 {
350 struct libnet_udp_hdr *udph_p =
351 (struct libnet_udp_hdr *)(packet + (ip_hdr->ip_hl << 2));
352 sin.sin_port = udph_p->uh_dport;
353 }
354#endif /* __WIN32__ */
355
356 c = sendto(l->fd, packet, size, 0, (struct sockaddr *)&sin,
357 sizeof(struct sockaddr));
358
359#if (LIBNET_BSD_BYTE_SWAP)
360 ip_hdr->ip_len = UNFIX(ip_hdr->ip_len);
361 ip_hdr->ip_off = UNFIX(ip_hdr->ip_off);
362#endif /* LIBNET_BSD_BYTE_SWAP */
363
364 if (c != size)
365 {
366#if !(__WIN32__)
367 snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
368 "%s(): %d bytes written (%s)\n", __func__, c,
369 strerror(errno));
370#else /* __WIN32__ */
371 snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
372 "%s(): %d bytes written (%d)\n", __func__, c,
373 WSAGetLastError());
374#endif /* !__WIN32__ */
375 }
376 return (c);
377}
378
379int
380libnet_write_raw_ipv6(libnet_t *l, u_int8_t *packet, u_int32_t size)
381{
382#if defined HAVE_SOLARIS && !defined HAVE_SOLARIS_IPV6
383 snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): no IPv6 support\n",
384 __func__, strerror(errno));
385 return (-1);
386}
387#else
388 int c;
389 struct sockaddr_in6 sin;
390 struct libnet_ipv6_hdr *ip_hdr;
391
392 if (l == NULL)
393 {
394 return (-1);
395 }
396
397 ip_hdr = (struct libnet_ipv6_hdr *)packet;
398
399 memset(&sin, 0, sizeof(sin));
400 sin.sin6_family = AF_INET6;
401 memcpy(sin.sin6_addr.s6_addr, ip_hdr->ip_dst.libnet_s6_addr,
402 sizeof(ip_hdr->ip_dst.libnet_s6_addr));
403
404 c = sendto(l->fd, packet, size, 0, (struct sockaddr *)&sin, sizeof(sin));
405 if (c != size)
406 {
407#if !(__WIN32__)
408 snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
409 "%s(): %d bytes written (%s)\n", __func__, c,
410 strerror(errno));
411#else /* __WIN32__ */
412 snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
413 "%s(): %d bytes written (%d)\n", __func__, c,
414 WSAGetLastError());
415#endif /* !__WIN32__ */
416 }
417 return (c);
418}
419#endif
420#endif
421/* EOF */