Annotation of embedaddon/libnet/src/libnet_link_linux.c, revision 1.1.1.1
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/bpf.h"
56: #include "../include/libnet.h"
57:
58: #include "../include/gnuc.h"
59: #ifdef HAVE_OS_PROTO_H
60: #include "../include/os-proto.h"
61: #endif
62:
63:
64: int
65: libnet_open_link(libnet_t *l)
66: {
67: struct ifreq ifr;
68: int n = 1;
69:
70: if (l == NULL)
71: {
72: return (-1);
73: }
74:
75: #if (HAVE_PACKET_SOCKET)
76: l->fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
77: #else
78: l->fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL));
79: #endif
80: if (l->fd == -1)
81: {
82: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
83: "socket: %s", strerror(errno));
84: goto bad;
85: }
86:
87: memset(&ifr, 0, sizeof (ifr));
88: strncpy(ifr.ifr_name, l->device, sizeof (ifr.ifr_name) -1);
89: ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
90:
91: if (ioctl(l->fd, SIOCGIFHWADDR, &ifr) < 0 )
92: {
93: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
94: "SIOCGIFHWADDR: %s", strerror(errno));
95: goto bad;
96: }
97:
98: switch (ifr.ifr_hwaddr.sa_family)
99: {
100: case ARPHRD_ETHER:
101: case ARPHRD_METRICOM:
102: #ifdef ARPHRD_LOOPBACK
103: case ARPHRD_LOOPBACK:
104: #endif
105: l->link_type = DLT_EN10MB;
106: l->link_offset = 0xe;
107: break;
108: case ARPHRD_SLIP:
109: case ARPHRD_CSLIP:
110: case ARPHRD_SLIP6:
111: case ARPHRD_CSLIP6:
112: case ARPHRD_PPP:
113: l->link_type = DLT_RAW;
114: break;
115: case ARPHRD_FDDI:
116: l->link_type = DLT_FDDI;
117: l->link_offset = 0x15;
118: break;
119: /* Token Ring */
120: case ARPHRD_IEEE802:
121: case ARPHRD_IEEE802_TR:
122: case ARPHRD_PRONET:
123: l->link_type = DLT_PRONET;
124: l->link_offset = 0x16;
125: break;
126:
127: default:
128: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
129: "unknown physical layer type 0x%x\n",
130: ifr.ifr_hwaddr.sa_family);
131: goto bad;
132: }
133: #ifdef SO_BROADCAST
134: /*
135: * man 7 socket
136: *
137: * Set or get the broadcast flag. When enabled, datagram sockets
138: * receive packets sent to a broadcast address and they are allowed
139: * to send packets to a broadcast address. This option has no
140: * effect on stream-oriented sockets.
141: */
142: if (setsockopt(l->fd, SOL_SOCKET, SO_BROADCAST, &n, sizeof(n)) == -1)
143: {
144: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
145: "%s: set SO_BROADCAST failed: %s\n",
146: __func__, strerror(errno));
147: goto bad;
148: }
149: #endif /* SO_BROADCAST */
150:
151: return (1);
152:
153: bad:
154: if (l->fd >= 0)
155: {
156: close(l->fd);
157: }
158: return (-1);
159: }
160:
161:
162: int
163: libnet_close_link(libnet_t *l)
164: {
165: if (close(l->fd) == 0)
166: {
167: return (1);
168: }
169: else
170: {
171: return (-1);
172: }
173: }
174:
175:
176: #if (HAVE_PACKET_SOCKET)
177: static int
178: get_iface_index(int fd, const int8_t *device)
179: {
180: struct ifreq ifr;
181:
182: /* memset(&ifr, 0, sizeof(ifr)); */
183: strncpy (ifr.ifr_name, device, sizeof(ifr.ifr_name) - 1);
184: ifr.ifr_name[sizeof(ifr.ifr_name)-1] = '\0';
185:
186: if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1)
187: {
188: return (-1);
189: }
190:
191: return ifr.ifr_ifindex;
192: }
193: #endif
194:
195:
196: int
197: libnet_write_link(libnet_t *l, u_int8_t *packet, u_int32_t size)
198: {
199: int c;
200: #if (HAVE_PACKET_SOCKET)
201: struct sockaddr_ll sa;
202: #else
203: struct sockaddr sa;
204: #endif
205:
206: if (l == NULL)
207: {
208: return (-1);
209: }
210:
211: memset(&sa, 0, sizeof (sa));
212: #if (HAVE_PACKET_SOCKET)
213: sa.sll_family = AF_PACKET;
214: sa.sll_ifindex = get_iface_index(l->fd, l->device);
215: if (sa.sll_ifindex == -1)
216: {
217: return (-1);
218: }
219: sa.sll_protocol = htons(ETH_P_ALL);
220: #else
221: strncpy(sa.sa_data, l->device, sizeof (sa.sa_data) - 1);
222: sa.sa_data[sizeof (sa.sa_data) - 1] = 0;
223: #endif
224:
225: c = sendto(l->fd, packet, size, 0,
226: (struct sockaddr *)&sa, sizeof (sa));
227: if (c != size)
228: {
229: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
230: "libnet_write_link(): only %d bytes written (%s)\n", c,
231: strerror(errno));
232: }
233: return (c);
234: }
235:
236:
237: struct libnet_ether_addr *
238: libnet_get_hwaddr(libnet_t *l)
239: {
240: int fd;
241: struct ifreq ifr;
242: struct libnet_ether_addr *eap;
243: /*
244: * XXX - non-re-entrant!
245: */
246: static struct libnet_ether_addr ea;
247:
248: if (l == NULL)
249: {
250: return (NULL);
251: }
252:
253: if (l->device == NULL)
254: {
255: if (libnet_select_device(l) == -1)
256: {
257: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
258: "libnet_get_hwaddr: can't figure out a device to use\n");
259: return (NULL);
260: }
261: }
262:
263: /*
264: * Create dummy socket to perform an ioctl upon.
265: */
266: fd = socket(AF_INET, SOCK_DGRAM, 0);
267: if (fd < 0)
268: {
269: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
270: "socket: %s", strerror(errno));
271: goto bad;
272: }
273:
274: memset(&ifr, 0, sizeof(ifr));
275: eap = &ea;
276: strncpy(ifr.ifr_name, l->device, sizeof(ifr.ifr_name) - 1);
277: ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
278:
279: if (ioctl(fd, SIOCGIFHWADDR, (int8_t *)&ifr) < 0)
280: {
281: close(fd);
282: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
283: "ioctl: %s", strerror(errno));
284: goto bad;
285: }
286: memcpy(eap, &ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
287: close(fd);
288: return (eap);
289:
290: bad:
291: return (NULL);
292: }
293:
294:
295: /* EOF */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>