2 * $Id: libnet_link_sockpacket.c,v 1.1.1.1 2000/05/25 00:28:49 route Exp $
5 * libnet_sockpacket.c - linux sockpacket routines
7 * Copyright (c) 1998 - 2001 Mike D. Schiffman <mike@infonexus.com>
10 * Copyright (c) 1996, 1997
11 * The Regents of the University of California. All rights reserved.
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
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.
31 #include "../include/config.h"
37 #include <netinet/if_ether.h>
38 #include <net/if_arp.h>
40 #include <linux/if_arp.h>
41 #include <linux/if_ether.h>
45 #include <linux/if_packet.h>
47 #define SOL_PACKET 263
48 #endif /* SOL_PACKET */
49 #endif /* HAVE_PF_PACKET */
51 #include "../include/bpf.h"
52 #include "../include/libnet.h"
54 #include "../include/gnuc.h"
55 #ifdef HAVE_OS_PROTO_H
56 #include "../include/os-proto.h"
61 get_iface_index(int fd, const char *device)
65 memset(&ifr, 0, sizeof(ifr));
66 strncpy (ifr.ifr_name, device, sizeof(ifr.ifr_name) - 1);
67 ifr.ifr_name[sizeof(ifr.ifr_name)-1] = '\0';
69 if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1)
74 return ifr.ifr_ifindex;
79 struct libnet_link_int *
80 libnet_open_link_interface(char *device, char *ebuf)
82 register struct libnet_link_int *l;
85 struct packet_mreq mr;
88 l = (struct libnet_link_int *)malloc(sizeof (*l));
91 sprintf(ebuf, "malloc: %s", ll_strerror(errno));
94 memset(l, 0, sizeof (*l));
97 l->fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
99 l->fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL));
103 sprintf(ebuf, "socket: %s", ll_strerror(errno));
108 memset(&mr, 0, sizeof(mr));
109 mr.mr_ifindex = get_iface_index (l->fd, device);
110 if (mr.mr_ifindex == -1)
112 sprintf(ebuf, "SIOCGIFINDEX %s: %s", device, ll_strerror(errno));
115 mr.mr_type = PACKET_MR_ALLMULTI;
117 if (setsockopt(l->fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, (char *)&mr,
120 sprintf(ebuf, "setsockopt %s: %s", device, ll_strerror(errno));
125 memset(&ifr, 0, sizeof (ifr));
126 strncpy(ifr.ifr_name, device, sizeof (ifr.ifr_name));
127 if (ioctl(l->fd, SIOCGIFHWADDR, &ifr) < 0 )
129 sprintf(ebuf, "SIOCGIFHWADDR: %s", ll_strerror(errno));
133 switch (ifr.ifr_hwaddr.sa_family)
136 case ARPHRD_METRICOM:
137 #ifdef ARPHRD_LOOPBACK
138 case ARPHRD_LOOPBACK:
140 l->linktype = DLT_EN10MB;
148 l->linktype = DLT_RAW;
151 sprintf(ebuf, "unknown physical layer type 0x%x",
152 ifr.ifr_hwaddr.sa_family);
168 libnet_close_link_interface(struct libnet_link_int *l)
170 if (close(l->fd) == 0)
182 libnet_write_link_layer(struct libnet_link_int *l, const char *device,
183 u_char *buf, int len)
187 struct sockaddr_ll sa;
192 memset(&sa, 0, sizeof (sa));
194 sa.sll_family = AF_PACKET;
195 sa.sll_ifindex = get_iface_index(l->fd, device);
196 if (sa.sll_ifindex == -1)
200 sa.sll_protocol = htons(ETH_P_ALL);
202 strncpy(sa.sa_data, device, sizeof (sa.sa_data));
205 c = sendto(l->fd, buf, len, 0, (struct sockaddr *)&sa, sizeof (sa));
209 libnet_error(LIBNET_ERR_WARNING,
210 "write_link_layer: %d bytes written (%s)\n", c,
219 libnet_get_hwaddr(struct libnet_link_int *l, const char *device, char *ebuf)
223 struct ether_addr *eap;
225 * XXX - non-re-entrant!
227 static struct ether_addr ea;
230 * Create dummy socket to perform an ioctl upon.
232 fd = socket(AF_INET, SOCK_DGRAM, 0);
235 sprintf(ebuf, "get_hwaddr: %s", strerror(errno));
239 memset(&ifr, 0, sizeof(ifr));
241 strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
243 if (ioctl(fd, SIOCGIFHWADDR, (char *)&ifr) < 0)
246 sprintf(ebuf, "get_hwaddr: %s", strerror(errno));
249 memcpy(eap, &ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);