int Secondary_Ipaddr_Handler::init_netlink_request ( char* const ip_slash_netmask, const char *const if_name, Netlink_Request& net_req, bool action) { ACE_OS::memset (&net_req, 0, sizeof(net_req)); // fill the request header net_req.nhdr_.nlmsg_len = NLMSG_LENGTH (sizeof(struct ifaddrmsg)); net_req.nhdr_.nlmsg_flags = NLM_F_REQUEST; net_req.nhdr_.nlmsg_type = action ? RTM_NEWADDR : RTM_DELADDR; net_req.ifa_.ifa_family = AF_INET; int interface_index = -1; if (get_if_index (if_name, interface_index) == -1 || interface_index < 0) { ACE_OS::fprintf (stderr, "get_if_index () - failed\n"); return -1; } net_req.ifa_.ifa_index = interface_index; Inet_Prefix local_prefix; if (fill_inet_prefix (local_prefix, ip_slash_netmask) == -1) { ACE_OS::fprintf (stderr, "fill_inet_prefix () - failed\n"); return -1; } fill_rtnetlink_request (net_req.nhdr_, IFA_LOCAL, &local_prefix.data, local_prefix.bytelen); net_req.ifa_.ifa_prefixlen = local_prefix.bitlen; // number of bits in netmask net_req.ifa_.ifa_scope = 0; return 0; }
int main(int argc, char *argv[]) { struct sockaddr_ll srcethaddr; /* man 7 packet */ struct sockaddr_ll bindethaddr; /* man 7 packet */ struct packet_mreq mr; /* man 7 packet */ struct ifreq ifr; /* man 7 netdevice */ int nbytes; socklen_t addrlen; /* how big should the buffer be? * * This can be determined by MTU. MTU can be obtained by an ioctl call: * * ioctl(socket, SIOCGIFMTU, &ifr) * * where socket is a socket descriptor, ifr is of type struct ifreq. * More information can be found at manual page netdevice(7). Note that * one needs to give ifr_name to invoke the ioctl call. If a program * retrieves frames from more than one device, the maximum MTU among * the devices should be used. * * In Linux, available network devices can be obtained in multiple * methods, commonly, * (1) by walking through the /proc/net/dev file. * (2) by calling ioctl(...) with request SIOCGIFCONF * (3) via rtnetlink socket * * MTU does not include header/trailer. For capturing Ethernet frames, * the buffer size should be set no less than * 6 + 6 + 2 + MTU = ETHER_HDR_LEN + MTU. * * Question: how does IEEE 802.1Q affect the required buffer size? * */ int bufsize; /* how big should the buffer be? */ int ifindex; /* interface index */ setupsignal(SIGINT, cleanup); /* capture CTRL-C */ if (argc < 2) { usage(argv[0]); exit(1); } /* open a raw packet socket to capture all types of ethernet frames */ sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (sockfd < 0) { perror("socket(AF_PACKET, SOCK_RAW, ETH_P_ALL) failed"); exit(1); } /* obtain interface index from interface name */ if ((ifindex = get_if_index(sockfd, argv[1])) == -1) { fprintf(stderr, "failed to obtain interface index for interface %s\n", argv[1]); exit(1); } /* put the interface into promiscuous mode. man 7 packet */ memset(&mr, 0, sizeof(mr)); mr.mr_ifindex = ifindex; mr.mr_type = PACKET_MR_PROMISC; if (setsockopt(sockfd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, (char *)&mr, sizeof(mr)) != 0) { perror("setsockopt(sockfd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, ...)"); exit(1); } /* bind the socket to the interface. see bind(2) and packet(7) */ memset(&bindethaddr, 0, sizeof(bindethaddr)); bindethaddr.sll_family = AF_PACKET; bindethaddr.sll_protocol = htons(ETH_P_ALL); bindethaddr.sll_ifindex = ifindex; if (bind(sockfd, (struct sockaddr*)&bindethaddr, sizeof(bindethaddr)) != 0) { perror("bind(sockfd, &bindethaddr, sizeof(bindethaddr))"); exit(1); } /* obtain MTU. see netdevice(7) */ ifr.ifr_addr.sa_family = AF_PACKET; safe_strncpy(ifr.ifr_name, argv[1], IFNAMSIZ); if (ioctl(sockfd, SIOCGIFMTU, &ifr) != 0) { perror("ioctl(sockfd, SIOCGIFMTU, &ifr)"); exit (1); } /* allocate buffer */ bufsize = ifr.ifr_mtu + ETHER_HDR_LEN; if ((buf = malloc(bufsize)) == NULL) { fprintf(stderr, "insufficient memory\n"); exit(1); } /* begin capturing */ memset(&srcethaddr, 0, sizeof(srcethaddr)); while (1) { addrlen = sizeof(srcethaddr); nbytes = recvfrom(sockfd, buf, bufsize, 0, (struct sockaddr*)&srcethaddr, &addrlen); if (nbytes < 0) { perror("recv(sockfd ...) failed"); exit (1); } /* dump captured frame */ printf("Captured at interface: %s frame from ", argv[1]); dump_physical_address(srcethaddr.sll_halen, srcethaddr.sll_addr); printf("\n"); dumpbuf(buf, nbytes); /** * flush the buffer so that we don't have to rely on stdbuf, as in * sudo stdbuf -o 0 ./ethercap eth0 | tee frame_captured.txt */ fflush(stdout); } /* remove the interface's promiscuous mode */ setsockopt(sockfd, SOL_PACKET, PACKET_DROP_MEMBERSHIP, (char *)&mr, sizeof(mr)); free(buf); close(sockfd); return 0; }