Annotation of embedaddon/libnet/src/libnet_link_linux.c, revision 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>