Annotation of embedaddon/libnet/src/libnet_link_bpf.c, revision 1.1.1.4
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:
1.1.1.4 ! misho 30: #include "common.h"
! 31:
1.1 misho 32: #include <sys/param.h> /* optionally get BSD define */
1.1.1.4 ! misho 33: #if !defined(__OpenBSD__) && !defined(__FreeBSD__)
1.1 misho 34: #include <sys/timeb.h>
1.1.1.4 ! misho 35: #endif
1.1 misho 36: #include <sys/file.h>
37: #include <sys/ioctl.h>
38:
39: #include <sys/types.h>
40: #include <sys/time.h>
41: #include <net/bpf.h>
42:
43: #include <sys/sysctl.h>
44: #include <net/route.h>
45: #include <net/if_dl.h>
1.1.1.2 misho 46: #include <net/if_types.h>
1.1 misho 47: #include "../include/gnuc.h"
1.1.1.2 misho 48:
1.1.1.4 ! misho 49: #include "../include/bpf.h"
1.1 misho 50:
51: #ifdef HAVE_OS_PROTO_H
52: #include "../include/os-proto.h"
53: #endif
54:
55: int
1.1.1.2 misho 56: libnet_bpf_open(char *err_buf)
1.1 misho 57: {
58: int i, fd;
1.1.1.2 misho 59: char device[] = "/dev/bpf000";
1.1 misho 60:
61: /*
62: * Go through all the minors and find one that isn't in use.
63: */
1.1.1.4 ! misho 64: for (i = 0; i < 1000; i++)
1.1 misho 65: {
1.1.1.4 ! misho 66: snprintf(device, sizeof(device), "/dev/bpf%d", i);
1.1 misho 67:
68: fd = open(device, O_RDWR);
69: if (fd == -1 && errno == EBUSY)
70: {
71: /*
72: * Device is busy.
73: */
74: continue;
75: }
76: else
77: {
78: /*
79: * Either we've got a valid file descriptor, or errno is not
80: * EBUSY meaning we've probably run out of devices.
81: */
82: break;
83: }
84: }
85:
86: if (fd == -1)
87: {
1.1.1.4 ! misho 88: snprintf(err_buf, LIBNET_ERRBUF_SIZE, "%s(): open(): (%s): %s",
1.1 misho 89: __func__, device, strerror(errno));
90: }
91: return (fd);
92: }
93:
94:
95: int
96: libnet_open_link(libnet_t *l)
97: {
98: struct ifreq ifr;
99: struct bpf_version bv;
1.1.1.2 misho 100: uint v;
1.1 misho 101:
102: #if defined(BIOCGHDRCMPLT) && defined(BIOCSHDRCMPLT) && !(__APPLE__)
1.1.1.2 misho 103: uint spoof_eth_src = 1;
1.1 misho 104: #endif
105:
106: if (l == NULL)
107: {
108: return (-1);
109: }
110:
111: if (l->device == NULL)
112: {
1.1.1.4 ! misho 113: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): NULL device",
1.1 misho 114: __func__);
115: goto bad;
116: }
117:
1.1.1.2 misho 118: l->fd = libnet_bpf_open((char*)l->err_buf);
1.1 misho 119: if (l->fd == -1)
120: {
121: goto bad;
122: }
123:
124: /*
125: * Get bpf version.
126: */
127: if (ioctl(l->fd, BIOCVERSION, (caddr_t)&bv) < 0)
128: {
1.1.1.4 ! misho 129: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): BIOCVERSION: %s",
1.1 misho 130: __func__, strerror(errno));
131: goto bad;
132: }
133:
134: if (bv.bv_major != BPF_MAJOR_VERSION || bv.bv_minor < BPF_MINOR_VERSION)
135: {
136: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
1.1.1.4 ! misho 137: "%s(): kernel bpf filter out of date", __func__);
1.1 misho 138: goto bad;
139: }
140:
141: /*
142: * Attach network interface to bpf device.
143: */
144: strncpy(ifr.ifr_name, l->device, sizeof(ifr.ifr_name) - 1);
145: ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
146:
147: if (ioctl(l->fd, BIOCSETIF, (caddr_t)&ifr) == -1)
148: {
1.1.1.4 ! misho 149: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): BIOCSETIF: (%s): %s",
1.1 misho 150: __func__, l->device, strerror(errno));
151: goto bad;
152: }
153:
154: /*
155: * Get the data link-layer type.
156: */
157: if (ioctl(l->fd, BIOCGDLT, (caddr_t)&v) == -1)
158: {
1.1.1.4 ! misho 159: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): BIOCGDLT: %s",
1.1 misho 160: __func__, strerror(errno));
161: goto bad;
162: }
163:
164: /*
165: * NetBSD and FreeBSD BPF have an ioctl for enabling/disabling
166: * automatic filling of the link level source address.
167: */
168: #if defined(BIOCGHDRCMPLT) && defined(BIOCSHDRCMPLT) && !(__APPLE__)
169: if (ioctl(l->fd, BIOCSHDRCMPLT, &spoof_eth_src) == -1)
170: {
1.1.1.4 ! misho 171: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): BIOCSHDRCMPLT: %s",
1.1 misho 172: __func__, strerror(errno));
173: goto bad;
174: }
175: #endif
176:
177: /*
178: * Assign link type and offset.
179: */
180: switch (v)
181: {
182: case DLT_SLIP:
183: l->link_offset = 0x10;
184: break;
185: case DLT_RAW:
186: l->link_offset = 0x0;
187: break;
188: case DLT_PPP:
189: l->link_offset = 0x04;
190: break;
191: case DLT_EN10MB:
192: default:
193: l->link_offset = 0xe; /* default to ethernet */
194: break;
195: }
196: #if _BSDI_VERSION - 0 >= 199510
197: switch (v)
198: {
199: case DLT_SLIP:
200: v = DLT_SLIP_BSDOS;
201: l->link_offset = 0x10;
202: break;
203: case DLT_PPP:
204: v = DLT_PPP_BSDOS;
205: l->link_offset = 0x04;
206: break;
207: }
208: #endif
209: l->link_type = v;
210:
211: return (1);
212:
213: bad:
214: if (l->fd > 0)
215: {
216: close(l->fd); /* this can fail ok */
217: }
218: return (-1);
219: }
220:
221:
222: int
223: libnet_close_link(libnet_t *l)
224: {
225: if (close(l->fd) == 0)
226: {
227: return (1);
228: }
229: else
230: {
231: return (-1);
232: }
233: }
234:
235:
236: int
1.1.1.2 misho 237: libnet_write_link(libnet_t *l, const uint8_t *packet, uint32_t size)
1.1 misho 238: {
239: int c;
240:
241: if (l == NULL)
242: {
243: return (-1);
244: }
245:
246: c = write(l->fd, packet, size);
247: if (c != size)
248: {
249: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
1.1.1.4 ! misho 250: "%s(): %d bytes written (%s)", __func__, c, strerror(errno));
1.1 misho 251: }
252: return (c);
253: }
254:
255:
256: struct libnet_ether_addr *
257: libnet_get_hwaddr(libnet_t *l)
258: {
259: int mib[6];
260: size_t len;
261: int8_t *buf, *next, *end;
262: struct if_msghdr *ifm;
263: struct sockaddr_dl *sdl;
264:
265: mib[0] = CTL_NET;
266: mib[1] = AF_ROUTE;
267: mib[2] = 0;
268: mib[3] = AF_LINK;
269: mib[4] = NET_RT_IFLIST;
270: mib[5] = 0;
271:
272: if (l == NULL)
273: {
274: return (NULL);
275: }
276:
277: if (l->device == NULL)
278: {
279: if (libnet_select_device(l) == -1)
280: {
281: /* err msg set in libnet_select_device */
282: return (NULL);
283: }
284: }
285:
286: if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1)
287: {
1.1.1.4 ! misho 288: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): sysctl(): %s",
1.1 misho 289: __func__, strerror(errno));
290: return (NULL);
291: }
292:
293: buf = (int8_t *)malloc(len);
294: if (buf == NULL)
295: {
1.1.1.4 ! misho 296: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): malloc(): %s",
1.1 misho 297: __func__, strerror(errno));
298: return (NULL);
299: }
300: if (sysctl(mib, 6, buf, &len, NULL, 0) < 0)
301: {
1.1.1.4 ! misho 302: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): sysctl(): %s",
1.1 misho 303: __func__, strerror(errno));
304: free(buf);
305: return (NULL);
306: }
307: end = buf + len;
308:
309: for (next = buf ; next < end ; next += ifm->ifm_msglen)
310: {
311: ifm = (struct if_msghdr *)next;
1.1.1.4 ! misho 312:
1.1.1.2 misho 313: if (ifm->ifm_version != RTM_VERSION)
314: continue;
1.1.1.4 ! misho 315:
1.1 misho 316: if (ifm->ifm_type == RTM_IFINFO)
317: {
318: sdl = (struct sockaddr_dl *)(ifm + 1);
1.1.1.3 misho 319: if (sdl->sdl_type != IFT_ETHER
1.1.1.4 ! misho 320: #ifdef IFT_FASTETHER
1.1.1.3 misho 321: && sdl->sdl_type != IFT_FASTETHER
1.1.1.4 ! misho 322: #endif
! 323: #ifdef IFT_FASTETHERFX
1.1.1.3 misho 324: && sdl->sdl_type != IFT_FASTETHERFX
1.1.1.4 ! misho 325: #endif
! 326: #ifdef IFT_GIGABITETHERNET
1.1.1.3 misho 327: && sdl->sdl_type != IFT_GIGABITETHERNET
1.1.1.4 ! misho 328: #endif
! 329:
1.1.1.3 misho 330: && sdl->sdl_type != IFT_L2VLAN)
1.1.1.2 misho 331: continue;
1.1.1.4 ! misho 332: if (sdl->sdl_nlen == strlen(l->device)
! 333: && strncmp(&sdl->sdl_data[0], l->device, sdl->sdl_nlen) == 0)
1.1 misho 334: {
1.1.1.4 ! misho 335: memcpy(l->link_addr.ether_addr_octet, LLADDR(sdl), ETHER_ADDR_LEN);
1.1 misho 336: break;
337: }
338: }
339: }
340: free(buf);
1.1.1.4 ! misho 341: if (next == end)
! 342: {
1.1.1.3 misho 343: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
344: "%s(): interface %s of known type not found.",
345: __func__, l->device);
346: return NULL;
347: }
1.1 misho 348:
1.1.1.4 ! misho 349: return (&l->link_addr);
! 350: }
1.1 misho 351:
1.1.1.4 ! misho 352: /**
! 353: * Local Variables:
! 354: * indent-tabs-mode: nil
! 355: * c-file-style: "stroustrup"
! 356: * End:
! 357: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>