Annotation of embedaddon/libnet/src/libnet_link_linux.c, revision 1.1.1.2
1.1 misho 1: /*
2: * $Id: libnet_link_linux.c,v 1.5 2004/01/03 20:31:02 mike Exp $
3: *
4: * libnet 1.1
5: * libnet_link_linux.c - linux packet socket and pack socket 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: (1) source code distributions
12: * retain the above copyright notice and this paragraph in its entirety, (2)
13: * distributions including binary code include the above copyright notice and
14: * this paragraph in its entirety in the documentation or other materials
15: * provided with the distribution, and (3) all advertising materials mentioning
16: * features or use of this software display the following acknowledgement:
17: * ``This product includes software developed by the University of California,
18: * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
19: * the University nor the names of its contributors may be used to endorse
20: * or promote products derived from this software without specific prior
21: * written permission.
22: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
23: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
24: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
25: */
26:
27: #if (HAVE_CONFIG_H)
28: #include "../include/config.h"
29: #endif
30: #include <sys/time.h>
31:
32: #include <net/if.h>
33: #if (__GLIBC__)
34: #include <netinet/if_ether.h>
35: #include <net/if_arp.h>
36: #else
37: #include <linux/if_arp.h>
38: #include <linux/if_ether.h>
39: #endif
40:
41: #if (HAVE_PACKET_SOCKET)
42: #ifndef SOL_PACKET
43: #define SOL_PACKET 263
44: #endif /* SOL_PACKET */
45: #if __GLIBC__ >= 2 && __GLIBC_MINOR >= 1
46: #include <netpacket/packet.h>
47: #include <net/ethernet.h> /* the L2 protocols */
48: #else
49: #include <asm/types.h>
50: #include <linux/if_packet.h>
51: #include <linux/if_ether.h> /* The L2 protocols */
52: #endif
53: #endif /* HAVE_PACKET_SOCKET */
54:
55: #include "../include/libnet.h"
56:
1.1.1.2 ! misho 57: /* These should not vary across linux systems, and are only defined in
! 58: * <pcap-bpf.h>, included from <pcap.h>, but since we have no other dependency
! 59: * on libpcap right now, define locally. I'm not sure if this is a good idea,
! 60: * but we'll try.
! 61: */
! 62: #define DLT_PRONET 4 /* Proteon ProNET Token Ring */
! 63: #define DLT_FDDI 10 /* FDDI */
! 64: #define DLT_RAW 12 /* raw IP */
! 65:
1.1 misho 66: #include "../include/gnuc.h"
67: #ifdef HAVE_OS_PROTO_H
68: #include "../include/os-proto.h"
69: #endif
70:
71:
72: int
73: libnet_open_link(libnet_t *l)
74: {
75: struct ifreq ifr;
76: int n = 1;
77:
78: if (l == NULL)
79: {
80: return (-1);
81: }
82:
83: #if (HAVE_PACKET_SOCKET)
84: l->fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
85: #else
86: l->fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL));
87: #endif
88: if (l->fd == -1)
89: {
1.1.1.2 ! misho 90: if (errno == EPERM) {
! 91: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
! 92: "%s(): UID/EUID 0 or capability CAP_NET_RAW required",
! 93: __func__);
! 94:
! 95: } else {
! 96: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
! 97: "socket: %s", strerror(errno));
! 98: }
1.1 misho 99: goto bad;
100: }
101:
102: memset(&ifr, 0, sizeof (ifr));
103: strncpy(ifr.ifr_name, l->device, sizeof (ifr.ifr_name) -1);
104: ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
105:
106: if (ioctl(l->fd, SIOCGIFHWADDR, &ifr) < 0 )
107: {
108: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
109: "SIOCGIFHWADDR: %s", strerror(errno));
110: goto bad;
111: }
112:
113: switch (ifr.ifr_hwaddr.sa_family)
114: {
115: case ARPHRD_ETHER:
116: case ARPHRD_METRICOM:
117: #ifdef ARPHRD_LOOPBACK
118: case ARPHRD_LOOPBACK:
119: #endif
120: l->link_type = DLT_EN10MB;
121: l->link_offset = 0xe;
122: break;
123: case ARPHRD_SLIP:
124: case ARPHRD_CSLIP:
125: case ARPHRD_SLIP6:
126: case ARPHRD_CSLIP6:
127: case ARPHRD_PPP:
128: l->link_type = DLT_RAW;
129: break;
130: case ARPHRD_FDDI:
131: l->link_type = DLT_FDDI;
132: l->link_offset = 0x15;
133: break;
134: /* Token Ring */
135: case ARPHRD_IEEE802:
136: case ARPHRD_IEEE802_TR:
137: case ARPHRD_PRONET:
138: l->link_type = DLT_PRONET;
139: l->link_offset = 0x16;
140: break;
141:
142: default:
143: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
144: "unknown physical layer type 0x%x\n",
145: ifr.ifr_hwaddr.sa_family);
146: goto bad;
147: }
148: #ifdef SO_BROADCAST
149: /*
150: * man 7 socket
151: *
152: * Set or get the broadcast flag. When enabled, datagram sockets
153: * receive packets sent to a broadcast address and they are allowed
154: * to send packets to a broadcast address. This option has no
155: * effect on stream-oriented sockets.
156: */
157: if (setsockopt(l->fd, SOL_SOCKET, SO_BROADCAST, &n, sizeof(n)) == -1)
158: {
159: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
160: "%s: set SO_BROADCAST failed: %s\n",
161: __func__, strerror(errno));
162: goto bad;
163: }
164: #endif /* SO_BROADCAST */
165:
166: return (1);
167:
168: bad:
169: if (l->fd >= 0)
170: {
171: close(l->fd);
172: }
173: return (-1);
174: }
175:
176:
177: int
178: libnet_close_link(libnet_t *l)
179: {
180: if (close(l->fd) == 0)
181: {
182: return (1);
183: }
184: else
185: {
186: return (-1);
187: }
188: }
189:
190:
191: #if (HAVE_PACKET_SOCKET)
192: static int
1.1.1.2 ! misho 193: get_iface_index(int fd, const char *device)
1.1 misho 194: {
195: struct ifreq ifr;
196:
197: /* memset(&ifr, 0, sizeof(ifr)); */
198: strncpy (ifr.ifr_name, device, sizeof(ifr.ifr_name) - 1);
199: ifr.ifr_name[sizeof(ifr.ifr_name)-1] = '\0';
200:
201: if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1)
202: {
203: return (-1);
204: }
205:
206: return ifr.ifr_ifindex;
207: }
208: #endif
209:
210:
211: int
1.1.1.2 ! misho 212: libnet_write_link(libnet_t *l, const uint8_t *packet, uint32_t size)
1.1 misho 213: {
214: int c;
215: #if (HAVE_PACKET_SOCKET)
216: struct sockaddr_ll sa;
217: #else
218: struct sockaddr sa;
219: #endif
220:
221: if (l == NULL)
222: {
223: return (-1);
224: }
225:
226: memset(&sa, 0, sizeof (sa));
227: #if (HAVE_PACKET_SOCKET)
228: sa.sll_family = AF_PACKET;
229: sa.sll_ifindex = get_iface_index(l->fd, l->device);
230: if (sa.sll_ifindex == -1)
231: {
232: return (-1);
233: }
234: sa.sll_protocol = htons(ETH_P_ALL);
235: #else
236: strncpy(sa.sa_data, l->device, sizeof (sa.sa_data) - 1);
237: sa.sa_data[sizeof (sa.sa_data) - 1] = 0;
238: #endif
239:
240: c = sendto(l->fd, packet, size, 0,
241: (struct sockaddr *)&sa, sizeof (sa));
242: if (c != size)
243: {
244: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
245: "libnet_write_link(): only %d bytes written (%s)\n", c,
246: strerror(errno));
247: }
248: return (c);
249: }
250:
251:
252: struct libnet_ether_addr *
253: libnet_get_hwaddr(libnet_t *l)
254: {
255: int fd;
256: struct ifreq ifr;
257: struct libnet_ether_addr *eap;
258: /*
259: * XXX - non-re-entrant!
260: */
261: static struct libnet_ether_addr ea;
262:
263: if (l == NULL)
264: {
265: return (NULL);
266: }
267:
268: if (l->device == NULL)
269: {
270: if (libnet_select_device(l) == -1)
271: {
272: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
273: "libnet_get_hwaddr: can't figure out a device to use\n");
274: return (NULL);
275: }
276: }
277:
278: /*
279: * Create dummy socket to perform an ioctl upon.
280: */
281: fd = socket(AF_INET, SOCK_DGRAM, 0);
282: if (fd < 0)
283: {
284: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
285: "socket: %s", strerror(errno));
286: goto bad;
287: }
288:
289: memset(&ifr, 0, sizeof(ifr));
290: eap = &ea;
291: strncpy(ifr.ifr_name, l->device, sizeof(ifr.ifr_name) - 1);
292: ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
293:
294: if (ioctl(fd, SIOCGIFHWADDR, (int8_t *)&ifr) < 0)
295: {
296: close(fd);
297: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
298: "ioctl: %s", strerror(errno));
299: goto bad;
300: }
301: memcpy(eap, &ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
302: close(fd);
303: return (eap);
304:
305: bad:
306: return (NULL);
307: }
308:
1.1.1.2 ! misho 309: /* ---- Emacs Variables ----
! 310: * Local Variables:
! 311: * c-basic-offset: 4
! 312: * indent-tabs-mode: nil
! 313: * End:
! 314: */
1.1 misho 315:
316: /* EOF */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>