Annotation of embedaddon/libnet/src/libnet_link_bpf.c, revision 1.1.1.1
1.1 misho 1: /*
2: * $Id: libnet_link_bpf.c,v 1.6 2004/01/28 19:45:00 mike Exp $
3: *
4: * libnet
5: * libnet_link_bpf.c - low-level bpf routines
6: *
7: * Copyright (c) 1998 - 2004 Mike D. Schiffman <mike@infonexus.com>
8: * All rights reserved.
9: *
10: * Copyright (c) 1993, 1994, 1995, 1996, 1998
11: * The Regents of the University of California. All rights reserved.
12: *
13: * Redistribution and use in source and binary forms, with or without
14: * modification, are permitted provided that: (1) source code distributions
15: * retain the above copyright notice and this paragraph in its entirety, (2)
16: * distributions including binary code include the above copyright notice and
17: * this paragraph in its entirety in the documentation or other materials
18: * provided with the distribution, and (3) all advertising materials mentioning
19: * features or use of this software display the following acknowledgement:
20: * ``This product includes software developed by the University of California,
21: * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
22: * the University nor the names of its contributors may be used to endorse
23: * or promote products derived from this software without specific prior
24: * written permission.
25: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
26: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
27: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
28: */
29:
30: #include <sys/param.h> /* optionally get BSD define */
31: #include <sys/timeb.h>
32: #include <sys/file.h>
33: #include <sys/ioctl.h>
34:
35: #include <sys/types.h>
36: #include <sys/time.h>
37: #include <net/bpf.h>
38:
39: #if (HAVE_CONFIG_H)
40: #include "../include/config.h"
41: #endif
42: #include "../include/libnet.h"
43: #include <sys/sysctl.h>
44: #include <net/route.h>
45: #include <net/if_dl.h>
46: #include "../include/gnuc.h"
47: #include "../include/bpf.h"
48:
49: #ifdef HAVE_OS_PROTO_H
50: #include "../include/os-proto.h"
51: #endif
52:
53: int
54: libnet_bpf_open(int8_t *err_buf)
55: {
56: int i, fd;
57: int8_t device[sizeof "/dev/bpf000"];
58:
59: /*
60: * Go through all the minors and find one that isn't in use.
61: */
62: for (i = 0;;i++)
63: {
64: sprintf(device, "/dev/bpf%d", i);
65:
66: fd = open(device, O_RDWR);
67: if (fd == -1 && errno == EBUSY)
68: {
69: /*
70: * Device is busy.
71: */
72: continue;
73: }
74: else
75: {
76: /*
77: * Either we've got a valid file descriptor, or errno is not
78: * EBUSY meaning we've probably run out of devices.
79: */
80: break;
81: }
82: }
83:
84: if (fd == -1)
85: {
86: snprintf(err_buf, LIBNET_ERRBUF_SIZE, "%s(): open(): (%s): %s\n",
87: __func__, device, strerror(errno));
88: }
89: return (fd);
90: }
91:
92:
93: int
94: libnet_open_link(libnet_t *l)
95: {
96: struct ifreq ifr;
97: struct bpf_version bv;
98: u_int v;
99:
100: #if defined(BIOCGHDRCMPLT) && defined(BIOCSHDRCMPLT) && !(__APPLE__)
101: u_int spoof_eth_src = 1;
102: #endif
103:
104: if (l == NULL)
105: {
106: return (-1);
107: }
108:
109: if (l->device == NULL)
110: {
111: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): NULL device\n",
112: __func__);
113: goto bad;
114: }
115:
116: l->fd = libnet_bpf_open(l->err_buf);
117: if (l->fd == -1)
118: {
119: goto bad;
120: }
121:
122: /*
123: * Get bpf version.
124: */
125: if (ioctl(l->fd, BIOCVERSION, (caddr_t)&bv) < 0)
126: {
127: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): BIOCVERSION: %s\n",
128: __func__, strerror(errno));
129: goto bad;
130: }
131:
132: if (bv.bv_major != BPF_MAJOR_VERSION || bv.bv_minor < BPF_MINOR_VERSION)
133: {
134: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
135: "%s(): kernel bpf filter out of date\n", __func__);
136: goto bad;
137: }
138:
139: /*
140: * Attach network interface to bpf device.
141: */
142: strncpy(ifr.ifr_name, l->device, sizeof(ifr.ifr_name) - 1);
143: ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
144:
145: if (ioctl(l->fd, BIOCSETIF, (caddr_t)&ifr) == -1)
146: {
147: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): BIOCSETIF: (%s): %s\n",
148: __func__, l->device, strerror(errno));
149: goto bad;
150: }
151:
152: /*
153: * Get the data link-layer type.
154: */
155: if (ioctl(l->fd, BIOCGDLT, (caddr_t)&v) == -1)
156: {
157: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): BIOCGDLT: %s\n",
158: __func__, strerror(errno));
159: goto bad;
160: }
161:
162: /*
163: * NetBSD and FreeBSD BPF have an ioctl for enabling/disabling
164: * automatic filling of the link level source address.
165: */
166: #if defined(BIOCGHDRCMPLT) && defined(BIOCSHDRCMPLT) && !(__APPLE__)
167: if (ioctl(l->fd, BIOCSHDRCMPLT, &spoof_eth_src) == -1)
168: {
169: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): BIOCSHDRCMPLT: %s\n",
170: __func__, strerror(errno));
171: goto bad;
172: }
173: #endif
174:
175: /*
176: * Assign link type and offset.
177: */
178: switch (v)
179: {
180: case DLT_SLIP:
181: l->link_offset = 0x10;
182: break;
183: case DLT_RAW:
184: l->link_offset = 0x0;
185: break;
186: case DLT_PPP:
187: l->link_offset = 0x04;
188: break;
189: case DLT_EN10MB:
190: default:
191: l->link_offset = 0xe; /* default to ethernet */
192: break;
193: }
194: #if _BSDI_VERSION - 0 >= 199510
195: switch (v)
196: {
197: case DLT_SLIP:
198: v = DLT_SLIP_BSDOS;
199: l->link_offset = 0x10;
200: break;
201: case DLT_PPP:
202: v = DLT_PPP_BSDOS;
203: l->link_offset = 0x04;
204: break;
205: }
206: #endif
207: l->link_type = v;
208:
209: return (1);
210:
211: bad:
212: if (l->fd > 0)
213: {
214: close(l->fd); /* this can fail ok */
215: }
216: return (-1);
217: }
218:
219:
220: int
221: libnet_close_link(libnet_t *l)
222: {
223: if (close(l->fd) == 0)
224: {
225: return (1);
226: }
227: else
228: {
229: return (-1);
230: }
231: }
232:
233:
234: int
235: libnet_write_link(libnet_t *l, u_int8_t *packet, u_int32_t size)
236: {
237: int c;
238:
239: if (l == NULL)
240: {
241: return (-1);
242: }
243:
244: c = write(l->fd, packet, size);
245: if (c != size)
246: {
247: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
248: "%s(): %d bytes written (%s)\n", __func__, c, strerror(errno));
249: }
250: return (c);
251: }
252:
253:
254: struct libnet_ether_addr *
255: libnet_get_hwaddr(libnet_t *l)
256: {
257: int mib[6];
258: size_t len;
259: int8_t *buf, *next, *end;
260: struct if_msghdr *ifm;
261: struct sockaddr_dl *sdl;
262: struct libnet_ether_addr *ea = NULL;
263:
264: mib[0] = CTL_NET;
265: mib[1] = AF_ROUTE;
266: mib[2] = 0;
267: mib[3] = AF_LINK;
268: mib[4] = NET_RT_IFLIST;
269: mib[5] = 0;
270:
271: if (l == NULL)
272: {
273: return (NULL);
274: }
275:
276: if (l->device == NULL)
277: {
278: if (libnet_select_device(l) == -1)
279: {
280: /* err msg set in libnet_select_device */
281: return (NULL);
282: }
283: }
284:
285: if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1)
286: {
287: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): sysctl(): %s\n",
288: __func__, strerror(errno));
289: return (NULL);
290: }
291:
292: buf = (int8_t *)malloc(len);
293: if (buf == NULL)
294: {
295: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): malloc(): %s\n",
296: __func__, strerror(errno));
297: return (NULL);
298: }
299: if (sysctl(mib, 6, buf, &len, NULL, 0) < 0)
300: {
301: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): sysctl(): %s\n",
302: __func__, strerror(errno));
303: free(buf);
304: return (NULL);
305: }
306: end = buf + len;
307:
308: for (next = buf ; next < end ; next += ifm->ifm_msglen)
309: {
310: ifm = (struct if_msghdr *)next;
311: if (ifm->ifm_type == RTM_IFINFO)
312: {
313: sdl = (struct sockaddr_dl *)(ifm + 1);
314: if (strncmp(&sdl->sdl_data[0], l->device, sdl->sdl_nlen) == 0)
315: {
316: if (!(ea = malloc(sizeof(struct libnet_ether_addr))))
317: {
318: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
319: "%s(): malloc(): %s", __func__, strerror(errno));
320: free(buf);
321: return (NULL);
322: }
323: memcpy(ea->ether_addr_octet, LLADDR(sdl), ETHER_ADDR_LEN);
324: break;
325: }
326: }
327: }
328: free(buf);
329: return (ea);
330: }
331:
332:
333: /* EOF */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>