1: /*
2: * $Id: libnet_raw.c,v 1.1.1.3 2023/09/27 11:11:38 misho Exp $
3: *
4: * libnet
5: * libnet_raw.c - raw sockets 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: #include "common.h"
34:
35: #ifndef HAVE_SOCKLEN_T
36: typedef int socklen_t;
37: #endif
38:
39: /* TODO this doesn't make any sense, the code in the #else branch is littered
40: with conditionals on __WIN32__ that are never reachable, what happened?
41: */
42: #if defined (__WIN32__)
43: int
44: libnet_open_raw4(libnet_t *l)
45: {
46: return (libnet_open_link(l));
47: }
48:
49: int
50: libnet_open_raw6(libnet_t *l)
51: {
52: return (libnet_open_link(l));
53: }
54:
55: int
56: libnet_close_raw4(libnet_t *l)
57: {
58: return (libnet_close_link_interface(l));
59: }
60:
61: int
62: libnet_close_raw6(libnet_t *l)
63: {
64: return (libnet_close_link_interface(l));
65: }
66: #else
67:
68: static int libnet_finish_setup_socket(libnet_t *l)
69: {
70: #if !(__WIN32__)
71: int n = 1;
72: #if (__svr4__)
73: void *nptr = &n;
74: #else
75: int *nptr = &n;
76: #endif /* __svr4__ */
77: #else
78: BOOL n;
79: #endif
80: unsigned len;
81:
82: #ifdef SO_SNDBUF
83:
84: /*
85: * man 7 socket
86: *
87: * Sets and gets the maximum socket send buffer in bytes.
88: *
89: * Taken from libdnet by Dug Song
90: */
91: len = sizeof(n);
92: if (getsockopt(l->fd, SOL_SOCKET, SO_SNDBUF, &n, &len) < 0)
93: {
94: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
95: "%s(): get SO_SNDBUF failed: %s",
96: __func__, strerror(errno));
97: goto bad;
98: }
99:
100: for (n += 128; n < 1048576; n += 128)
101: {
102: if (setsockopt(l->fd, SOL_SOCKET, SO_SNDBUF, &n, len) < 0)
103: {
104: if (errno == ENOBUFS)
105: {
106: break;
107: }
108: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
109: "%s(): set SO_SNDBUF failed: %s",
110: __func__, strerror(errno));
111: goto bad;
112: }
113: }
114: #endif
115:
116: #ifdef SO_BROADCAST
117: /*
118: * man 7 socket
119: *
120: * Set or get the broadcast flag. When enabled, datagram sockets
121: * receive packets sent to a broadcast address and they are allowed
122: * to send packets to a broadcast address. This option has no
123: * effect on stream-oriented sockets.
124: */
125: if (setsockopt(l->fd, SOL_SOCKET, SO_BROADCAST, nptr, sizeof(n)) == -1)
126: {
127: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
128: "%s(): set SO_BROADCAST failed: %s",
129: __func__, strerror(errno));
130: goto bad;
131: }
132: #endif /* SO_BROADCAST */
133:
134: #if (__linux__)
135: if(l->device != NULL)
136: if(setsockopt(l->fd, SOL_SOCKET, SO_BINDTODEVICE, l->device, strlen(l->device)) == -1) {
137: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
138: "%s(): set SO_BINDTODEVICE failed: %s", __func__, strerror(errno));
139: goto bad;
140: }
141: #endif /* __linux__ */
142:
143: return 0;
144:
145: bad:
146: return (-1);
147: }
148:
149:
150:
151:
152: int
153: libnet_open_raw4(libnet_t *l)
154: {
155: #if !(__WIN32__)
156: int n = 1;
157: #if (__svr4__)
158: void *nptr = &n;
159: #else
160: int *nptr = &n;
161: #endif /* __svr4__ */
162: #else
163: BOOL n;
164: #endif
165:
166: if (l == NULL)
167: {
168: return (-1);
169: }
170:
171: l->fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
172: if (l->fd == -1)
173: {
174: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
175: "%s(): SOCK_RAW allocation failed: %s",
176: __func__, strerror(errno));
177: goto bad;
178: }
179:
180: #ifdef IP_HDRINCL
181: /*
182: * man raw
183: *
184: * The IPv4 layer generates an IP header when sending a packet unless
185: * the IP_HDRINCL socket option is enabled on the socket. When it
186: * is enabled, the packet must contain an IP header. For
187: * receiving the IP header is always included in the packet.
188: */
189: #if !(__WIN32__)
190: if (setsockopt(l->fd, IPPROTO_IP, IP_HDRINCL, nptr, sizeof(n)) == -1)
191: #else
192: n = TRUE;
193: if (setsockopt(l->fd, IPPROTO_IP, IP_HDRINCL, &n, sizeof(n)) == -1)
194: #endif
195:
196: {
197: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
198: "%s(): set IP_HDRINCL failed: %s",
199: __func__, strerror(errno));
200: goto bad;
201: }
202: #endif /* IP_HDRINCL */
203:
204:
205: if (libnet_finish_setup_socket(l) == -1)
206: goto bad;
207:
208: return (l->fd);
209:
210: bad:
211: return (-1);
212: }
213:
214:
215: int
216: libnet_close_raw4(libnet_t *l)
217: {
218: if (l == NULL)
219: {
220: return (-1);
221: }
222:
223: return (close(l->fd));
224: }
225:
226: #if ((defined HAVE_SOLARIS && !defined HAVE_SOLARIS_IPV6) || defined (__WIN32__))
227: int libnet_open_raw6(libnet_t *l)
228: {
229: return (-1);
230: }
231:
232: #else
233: int
234: libnet_open_raw6(libnet_t *l)
235: {
236: if (l == NULL)
237: {
238: return (-1);
239: }
240:
241: l->fd = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
242: if (l->fd == -1)
243: {
244: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
245: "%s(): SOCK_RAW allocation failed: %s", __func__,
246: strerror(errno));
247: goto bad;
248: }
249:
250:
251: if (libnet_finish_setup_socket(l) == -1)
252: goto bad;
253:
254: return (l->fd);
255:
256: bad:
257: return (-1);
258: }
259: #endif
260:
261: int
262: libnet_close_raw6(libnet_t *l)
263: {
264: if (l == NULL)
265: {
266: return (-1);
267: }
268: return (close(l->fd));
269: }
270: #endif
271:
272: /**
273: * Local Variables:
274: * indent-tabs-mode: nil
275: * c-file-style: "stroustrup"
276: * End:
277: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>