OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / lib / Libnet / src / libnet_link_bpf.c
1 /*
2  *  $Id: libnet_link_bpf.c,v 1.1.1.1 2000/05/25 00:28:49 route Exp $
3  *
4  *  libnet
5  *  libnet_bpf.c - low-level bpf routines
6  *
7  *  Copyright (c) 1998 - 2001 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(char *errbuf)
55 {
56     int i, fd;
57     char 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         sprintf(errbuf, "%s: %s", device, ll_strerror(errno));
87     }
88     return (fd);
89 }
90
91
92 struct libnet_link_int *
93 libnet_open_link_interface(char *device, char *ebuf)
94 {
95     struct ifreq ifr;
96     struct bpf_version bv;
97     u_int v;
98     struct libnet_link_int *l;
99
100 #if defined(BIOCGHDRCMPLT) && defined(BIOCSHDRCMPLT)
101     u_int spoof_eth_src = 1;
102 #endif
103
104     l = (struct libnet_link_int *)malloc(sizeof(*l));
105     if (!l)
106     {
107         sprintf(ebuf, "malloc: %s", ll_strerror(errno));
108 #if (__DEBUG)
109         libnet_error(LN_ERR_CRITICAL, "bpf libnet_open_link_interface: malloc %s",
110                 ll_strerror(errno));
111 #endif
112         return (NULL);
113     }
114
115     memset(l, 0, sizeof(*l));
116
117     l->fd = libnet_bpf_open(ebuf);
118     if (l->fd == -1)
119     {
120         goto bad;
121     }
122
123     /*
124      *  Get bpf version.
125      */
126     if (ioctl(l->fd, BIOCVERSION, (caddr_t)&bv) < 0)
127     {
128         sprintf(ebuf, "BIOCVERSION: %s", ll_strerror(errno));
129         goto bad;
130     }
131
132     if (bv.bv_major != BPF_MAJOR_VERSION || bv.bv_minor < BPF_MINOR_VERSION)
133     {
134         sprintf(ebuf, "kernel bpf filter out of date");
135         goto bad;
136     }
137
138     /*
139      *  Attach network interface to bpf device.
140      */
141     strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
142     if (ioctl(l->fd, BIOCSETIF, (caddr_t)&ifr) == -1)
143     {
144         sprintf(ebuf, "%s: %s", device, ll_strerror(errno));
145         goto bad;
146     }
147
148     /*
149      *  Get the data link layer type.
150      */
151     if (ioctl(l->fd, BIOCGDLT, (caddr_t)&v) == -1)
152     {
153         sprintf(ebuf, "BIOCGDLT: %s", ll_strerror(errno));
154         goto bad;
155     }
156
157     /*
158      *  NetBSD and FreeBSD BPF have an ioctl for enabling/disabling
159      *  automatic filling of the link level source address.
160      */
161 #if defined(BIOCGHDRCMPLT) && defined(BIOCSHDRCMPLT)
162     if (ioctl(l->fd, BIOCSHDRCMPLT, &spoof_eth_src) == -1)
163     {
164         sprintf(ebuf, "BIOCSHDRCMPLT: %s", ll_strerror(errno));
165         goto bad;
166     }
167 #endif
168
169     /*
170      *  Assign link type and offset.
171      */
172     switch (v)
173     {
174         case DLT_SLIP:
175             l->linkoffset = 0x10;
176             break;
177         case DLT_RAW:
178             l->linkoffset = 0x0;
179             break;
180         case DLT_PPP:
181             l->linkoffset = 0x04;
182             break;
183         case DLT_EN10MB:
184         default:
185             l->linkoffset = 0xe;     /* default to ethernet */
186             break;
187     }
188 #if _BSDI_VERSION - 0 >= 199510
189     switch (v)
190     {
191         case DLT_SLIP:
192             v = DLT_SLIP_BSDOS;
193             l->linkoffset = 0x10;
194             break;
195         case DLT_PPP:
196             v = DLT_PPP_BSDOS;
197             l->linkoffset = 0x04;
198             break;
199     }
200 #endif
201     l->linktype = v;
202
203     return (l);
204
205 bad:
206     close(l->fd);      /* this can fail ok */
207     free(l);
208     return (NULL);
209 }
210
211
212 int
213 libnet_close_link_interface(struct libnet_link_int *l)
214 {
215     if (close(l->fd) == 0)
216     {
217         return (1);
218     }
219     else
220     {
221         return (-1);
222     }
223 }
224
225
226 int
227 libnet_write_link_layer(struct libnet_link_int *l, const char *device,
228             u_char *buf, int len)
229 {
230     int c;
231
232     c = write(l->fd, buf, len);
233     if (c != len)
234     {
235 #if (__DEBUG)
236         libnet_error(LN_ERR_WARNING,
237                 "write_link_layer: %d bytes written (%s)\n", c,
238                 strerror(errno));
239 #endif
240     }
241     return (c);
242 }
243
244
245 struct ether_addr *
246 libnet_get_hwaddr(struct libnet_link_int *l, const char *device, char *ebuf)
247 {
248     int mib[6];
249     size_t len;
250     char *buf, *next, *end;
251     struct if_msghdr *ifm;
252     struct sockaddr_dl *sdl;
253     struct ether_addr *ea = NULL;
254
255     mib[0] = CTL_NET;
256     mib[1] = AF_ROUTE;
257     mib[2] = 0;
258     mib[3] = AF_LINK;
259     mib[4] = NET_RT_IFLIST;
260     mib[5] = 0;
261
262     if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
263     {
264         return (NULL);
265     }
266
267     if (!(buf = (char *)malloc(len)))
268     {
269         return NULL;
270     }
271    if (sysctl(mib, 6, buf, &len, NULL, 0) < 0)
272    {
273         free(buf);
274         return (NULL);
275     }
276     end = buf + len;
277
278     for (next = buf ; next < end ; next += ifm->ifm_msglen)
279     {
280         ifm = (struct if_msghdr *)next;
281         if (ifm->ifm_type == RTM_IFINFO)
282         {
283             sdl = (struct sockaddr_dl *)(ifm + 1);
284             if (strncmp(&sdl->sdl_data[0], device, sdl->sdl_nlen) == 0)
285             {
286                 if (!(ea = malloc(sizeof(struct ether_addr))))
287                 {
288                     return (NULL);
289                 }
290                 memcpy(ea->ether_addr_octet, LLADDR(sdl), ETHER_ADDR_LEN);
291                 break;
292             }
293         }
294     }
295     free(buf);
296     return (ea);
297 }
298
299
300 /* EOF */