?? scan_dhcp.c
字號:
/* * dhcp.c * * Code to check for a DHCP server. */#include <arpa/inet.h>#include <errno.h>#include <net/if.h>#include <netinet/in.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <sys/time.h>#include <sys/types.h>#include <unistd.h>#include "skan_config.h"#define SA struct sockaddrstruct dhcp_packet { unsigned char op; unsigned char htype; unsigned char hlen; unsigned char hops; unsigned int xid; unsigned short secs; unsigned short flags; unsigned int ciaddr; unsigned int yiaddr; unsigned int siaddr; unsigned int giaddr; unsigned char chaddr[16]; unsigned char sname[64]; unsigned char file[128]; unsigned int cookie; unsigned char options[336];};extern gtkskan_config_t skan_conf;/* * Returns the minimum length of the packet. */int dhcp_get_length(struct dhcp_packet * pkt){ int i = 0; if (pkt == NULL) { return 240 + 1; } while (pkt->options[i] != 0xff) { i++; } return 240 + i + 1;}/* * Gets the MAC address for 'dev'. */int dhcp_get_mac(int fd, const char * dev, unsigned char * mac){ struct ifreq ifr; int retval; if (dev == NULL) { return -1; } memset(&ifr, 0, sizeof(ifr)); strcpy(ifr.ifr_name, dev); retval = ioctl(fd, SIOCGIFHWADDR, &ifr); if (retval < 0) { return retval; } if (mac) { memcpy(mac, ifr.ifr_hwaddr.sa_data, 6); } return 0;}/* * Returns a pointer to the given option. */unsigned char * dhcp_get_opt(struct dhcp_packet * pkt, int opt){ unsigned char * options; if (pkt == NULL) { return NULL; } options = pkt->options; for (;;) { if (*options == opt) { return options; } if (*options == 0xff) { return NULL; } options += *(options + 1); } return NULL;}/* * Broadcasts a DHCPDISCOVER packet. */int dhcp_discover(int fd, unsigned char * mac){ struct dhcp_packet pkt; struct sockaddr_in sa; int retval; if (fd < 0) { return fd; } memset(&pkt, 0, sizeof(pkt)); pkt.op = 1; /* BOOTREQUEST */ pkt.htype = 1; /* Ethernet */ pkt.hlen = 6; /* ETH_ALEN */ pkt.xid = htonl(0x12345678); pkt.cookie = htonl(0x63825363); if (mac) { memcpy(pkt.chaddr, mac, 6); } else { retval = dhcp_get_mac(fd, "eth0", pkt.chaddr); if (retval < 0) { return retval; } } /* * This is a discover packet. */ pkt.options[0] = 53; /* DHCP Message Type */ pkt.options[1] = 1; pkt.options[2] = 1; /* DHCPDISCOVER */ pkt.options[3] = 0xff; memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; sa.sin_addr = (struct in_addr) { INADDR_BROADCAST }; sa.sin_port = htons(67); retval = sendto(fd, &pkt, dhcp_get_length(&pkt), 0, (SA *) &sa, sizeof(sa)); if (retval < 0) { return retval; } return 0;}/* * Receives a DHCP packet. */int dhcp_recv(int fd, struct dhcp_packet * pkt){ int retval; if (pkt == NULL) { return -1; } retval = recv(fd, pkt, sizeof(*pkt), 0); if (retval < 0) { return retval; } return retval;}/* * Creates a DHCP socket. */int dhcp_socket(void){ struct sockaddr_in sa; int fd, on = 1, retval; fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { return fd; } retval = setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)); if (retval < 0) { return retval; } memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; sa.sin_addr = (struct in_addr) { INADDR_ANY }; sa.sin_port = htons(68); retval = bind(fd, (SA *) &sa, sizeof(sa)); if (retval < 0) { return retval; } return fd;}void * dhcp_search(void *data){ unsigned char mac[6]; struct timeval tv; int fd, retval, timeout = 1; fd_set rfds; /* * Create the socket. Do this early so we can use the socket * for generic sockopts. */ fd = (int)data; if (fd < 0) { fprintf(stderr, "socket error: %m\n"); exit(1); } /* * Grab the MAC address to use in the 'chaddr' field. */// retval = dhcp_get_mac(fd, wvlan_interface, mac); retval = dhcp_get_mac(fd, skan_conf.interface, mac); if (retval < 0) { fprintf(stderr, "dhcp_get_mac error: %m\n"); exit(1); } FD_ZERO(&rfds); memset(&tv, 0, sizeof(tv)); /* * Send a discover packet every N seconds. * Also display any packets we see. */ for (;;) { FD_SET(fd, &rfds); retval = select(fd + 1, &rfds, NULL, NULL, &tv); if (retval < 0) { if (errno != EINTR) { fprintf(stderr, "select error: %m\n"); } } /* * Timeout, send a DHCPDISCOVER packet and reset the timer. */ if (retval == 0) { retval = dhcp_discover(fd, mac); if (retval < 0) { fprintf(stderr, "dhcp_discover error: %m\n"); } tv.tv_sec = timeout; tv.tv_usec = 0; continue; } /* * Receive the packet. */ if (FD_ISSET(fd, &rfds)) { struct dhcp_packet pkt; struct in_addr a; unsigned char * opt; retval = dhcp_recv(fd, &pkt); if (retval < 0) { fprintf(stderr, "dhcp_recv error: %m\n"); continue; } a = (struct in_addr) { pkt.yiaddr }; fprintf(stdout, "received offer for %s\n", inet_ntoa(a));#if 0 opt = dhcp_get_opt(&pkt, 53); if (opt) { fprintf(stdout, "msgtype: %d\n", *(opt + 2)); }#endif#if 1 /* untested */ opt = dhcp_get_opt(&pkt, 15); if (opt) { fprintf(stdout, "domainname: %s\n", (char *) opt + 2); }#endif return NULL; } } return NULL;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -