int libnet_open_link(libnet_t *l) { struct ifreq ifr; struct bpf_version bv; uint v; #if defined(BIOCGHDRCMPLT) && defined(BIOCSHDRCMPLT) && !(__APPLE__) uint spoof_eth_src = 1; #endif if (l == NULL) { return (-1); } if (l->device == NULL) { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): NULL device", __func__); goto bad; } l->fd = libnet_bpf_open((char*)l->err_buf); if (l->fd == -1) { goto bad; } /* * Get bpf version. */ if (ioctl(l->fd, BIOCVERSION, (caddr_t)&bv) < 0) { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): BIOCVERSION: %s", __func__, strerror(errno)); goto bad; } if (bv.bv_major != BPF_MAJOR_VERSION || bv.bv_minor < BPF_MINOR_VERSION) { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): kernel bpf filter out of date", __func__); goto bad; } /* * Attach network interface to bpf device. */ strncpy(ifr.ifr_name, l->device, sizeof(ifr.ifr_name) - 1); ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0'; if (ioctl(l->fd, BIOCSETIF, (caddr_t)&ifr) == -1) { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): BIOCSETIF: (%s): %s", __func__, l->device, strerror(errno)); goto bad; } /* * Get the data link-layer type. */ if (ioctl(l->fd, BIOCGDLT, (caddr_t)&v) == -1) { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): BIOCGDLT: %s", __func__, strerror(errno)); goto bad; } /* * NetBSD and FreeBSD BPF have an ioctl for enabling/disabling * automatic filling of the link level source address. */ #if defined(BIOCGHDRCMPLT) && defined(BIOCSHDRCMPLT) && !(__APPLE__) if (ioctl(l->fd, BIOCSHDRCMPLT, &spoof_eth_src) == -1) { snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): BIOCSHDRCMPLT: %s", __func__, strerror(errno)); goto bad; } #endif /* * Assign link type and offset. */ switch (v) { case DLT_SLIP: l->link_offset = 0x10; break; case DLT_RAW: l->link_offset = 0x0; break; case DLT_PPP: l->link_offset = 0x04; break; case DLT_EN10MB: default: l->link_offset = 0xe; /* default to ethernet */ break; } #if _BSDI_VERSION - 0 >= 199510 switch (v) { case DLT_SLIP: v = DLT_SLIP_BSDOS; l->link_offset = 0x10; break; case DLT_PPP: v = DLT_PPP_BSDOS; l->link_offset = 0x04; break; } #endif l->link_type = v; return (1); bad: if (l->fd > 0) { close(l->fd); /* this can fail ok */ } return (-1); }
struct libnet_link_int * libnet_open_link_interface(char *device, char *ebuf) { struct ifreq ifr; struct bpf_version bv; u_int v; struct libnet_link_int *l; l = (struct libnet_link_int *)malloc(sizeof(*l)); if (!l) { sprintf(ebuf, "malloc: %s", ll_strerror(errno)); #if (__DEBUG) libnet_error(LN_ERR_CRITICAL, "bpf libnet_open_link_interface: malloc %s", ll_strerror(errno)); #endif return (NULL); } memset(l, 0, sizeof(*l)); l->fd = libnet_bpf_open(ebuf); if (l->fd == -1) { goto bad; } /* * Get bpf version. */ if (ioctl(l->fd, BIOCVERSION, (caddr_t)&bv) < 0) { sprintf(ebuf, "BIOCVERSION: %s", ll_strerror(errno)); goto bad; } if (bv.bv_major != BPF_MAJOR_VERSION || bv.bv_minor < BPF_MINOR_VERSION) { sprintf(ebuf, "kernel bpf filter out of date"); goto bad; } /* * Attach network interface to bpf device. */ strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); if (ioctl(l->fd, BIOCSETIF, (caddr_t)&ifr) == -1) { sprintf(ebuf, "%s: %s", device, ll_strerror(errno)); goto bad; } /* * Get the data link layer type. */ if (ioctl(l->fd, BIOCGDLT, (caddr_t)&v) == -1) { sprintf(ebuf, "BIOCGDLT: %s", ll_strerror(errno)); goto bad; } /* * Assign link type and offset. */ switch (v) { case DLT_SLIP: l->linkoffset = 0x10; break; case DLT_RAW: l->linkoffset = 0x0; break; case DLT_PPP: l->linkoffset = 0x04; break; case DLT_EN10MB: default: l->linkoffset = 0xe; /* default to ethernet */ break; } #if _BSDI_VERSION - 0 >= 199510 switch (v) { case DLT_SLIP: v = DLT_SLIP_BSDOS; l->linkoffset = 0x10; break; case DLT_PPP: v = DLT_PPP_BSDOS; l->linkoffset = 0x04; break; } #endif l->linktype = v; return (l); bad: close(l->fd); /* this can fail ok */ free(l); return (NULL); }