#include #include #include #include #ifndef USE_NETLIB #include #include #ifdef __linux__ #include #endif #include #else #include #endif #include "pktlib.h" #include "pktbuf.h" struct dhcp { unsigned char message_type; unsigned char hardware_type; unsigned char hardware_addrlen; unsigned char hops; unsigned int transaction_id; unsigned short seconds_elapsed; unsigned short flags; unsigned int client_ip_address; unsigned int your_ip_address; unsigned int next_server_ip_address; unsigned int relay_agent_ip_address; char client_mac_address[6]; unsigned char padding[10]; unsigned char server_host_name[64]; unsigned char boot_file_name[128]; unsigned int magic_cookie; #define DHCP_MAGIC_COOKIE_DHCP 0x63825363 unsigned char option[0]; }; struct dhcp_option { unsigned char type; #define DHCP_OPTION_TYPE_SUBNET_MASK 0x01 #define DHCP_OPTION_TYPE_HOST_NAME 0x0c #define DHCP_OPTION_TYPE_DOMAIN_NAME 0x0f #define DHCP_OPTION_TYPE_REQ_IP_ADDR 0x32 #define DHCP_OPTION_TYPE_IP_LEASE_TIME 0x33 #define DHCP_OPTION_TYPE_MESSAGE_TYPE 0x35 #define DHCP_OPTION_TYPE_SERVER_ID 0x36 #define DHCP_OPTION_TYPE_PARAM_REQLIST 0x37 #define DHCP_OPTION_TYPE_CLIENT_ID 0x3d #define DHCP_OPTION_TYPE_END 0xff unsigned char length; unsigned char data[0]; }; struct dhcp_params { struct ether_addr src_macaddr; struct ether_addr client_macaddr; unsigned int server_ipaddr; unsigned int transaction_id; unsigned int your_ip_address; unsigned int subnet_mask; }; #define DHCP_TRANSACTION_ID 0x12345678 static char *macaddr_s(char macaddr[]) { return ether_ntoa((struct ether_addr *)macaddr); } static char *ipaddr_s(unsigned int ipaddr) { struct in_addr in; in.s_addr = htonl(ipaddr); return inet_ntoa(in); } static int send_dhcp_offer(pktif_t pktif, struct header_param *paramp, struct dhcp_params *dhcpparams) { pktbuf_t pktbuf; struct header_param param; struct dhcp *dhcphdr; struct dhcp_option *dhcpopt; unsigned int val4; memcpy(param.ethernet.src_macaddr, &dhcpparams->src_macaddr, ETHER_ADDR_LEN); memcpy(param.ethernet.dst_macaddr, ¶mp->ethernet.src_macaddr, ETHER_ADDR_LEN); param.ethernet.type = ETHERTYPE_IP; param.ip.id = 0x1234; param.ip.ttl = 64; param.ip.protocol = IPPROTO_UDP; param.ip.src_ipaddr = dhcpparams->server_ipaddr; param.ip.dst_ipaddr = dhcpparams->your_ip_address; param.udp.src_port = 67; param.udp.dst_port = 68; pktbuf = pktbuf_create(-1); dhcphdr = (struct dhcp *)pktbuf_add_header(pktbuf, sizeof(*dhcphdr) + 64); memset(dhcphdr, 0, sizeof(*dhcphdr)); dhcphdr->message_type = 2; /* Boot Reply */ dhcphdr->hardware_type = 1; /* Ethernet */ dhcphdr->hardware_addrlen = ETHER_ADDR_LEN; dhcphdr->transaction_id = htonl(dhcpparams->transaction_id); dhcphdr->your_ip_address = htonl(dhcpparams->your_ip_address); memcpy(dhcphdr->client_mac_address, &dhcpparams->client_macaddr, ETHER_ADDR_LEN); dhcphdr->magic_cookie = htonl(DHCP_MAGIC_COOKIE_DHCP); dhcpopt = (struct dhcp_option *)dhcphdr->option; dhcpopt->type = DHCP_OPTION_TYPE_MESSAGE_TYPE; dhcpopt->length = 1; dhcpopt->data[0] = 2; /* Offer */ dhcpopt = (struct dhcp_option *)((char *)dhcpopt + 2 + dhcpopt->length); dhcpopt->type = DHCP_OPTION_TYPE_SERVER_ID; dhcpopt->length = 4; val4 = htonl(dhcpparams->server_ipaddr); memcpy(dhcpopt->data, &val4, sizeof(val4)); dhcpopt = (struct dhcp_option *)((char *)dhcpopt + 2 + dhcpopt->length); dhcpopt->type = DHCP_OPTION_TYPE_IP_LEASE_TIME; dhcpopt->length = 4; val4 = htonl(600); memcpy(dhcpopt->data, &val4, sizeof(val4)); dhcpopt = (struct dhcp_option *)((char *)dhcpopt + 2 + dhcpopt->length); dhcpopt->type = DHCP_OPTION_TYPE_SUBNET_MASK; dhcpopt->length = 4; val4 = htonl(dhcpparams->subnet_mask); memcpy(dhcpopt->data, &val4, sizeof(val4)); dhcpopt = (struct dhcp_option *)((char *)dhcpopt + 2 + dhcpopt->length); dhcpopt->type = DHCP_OPTION_TYPE_DOMAIN_NAME; dhcpopt->length = 11; memcpy(dhcpopt->data, "example.org", 11); dhcpopt = (struct dhcp_option *)((char *)dhcpopt + 2 + dhcpopt->length); dhcpopt->type = DHCP_OPTION_TYPE_END; dhcpopt = (struct dhcp_option *)((char *)dhcpopt + 1); pktbuf_set_size(pktbuf, (char *)dhcpopt - (char *)dhcphdr); pktbuf = pktbuf_make_udp(pktbuf, ¶m); pktbuf = pktbuf_make_ip(pktbuf, ¶m); pktbuf = pktbuf_checksum_correct_ip(pktbuf); pktbuf = pktbuf_make_ethernet(pktbuf, ¶m); pktbuf = pktbuf_send(pktif, pktbuf); if (pktbuf) { pktbuf_destroy(pktbuf); return 0; } return 1; } static int send_dhcp_ack(pktif_t pktif, struct header_param *paramp, struct dhcp_params *dhcpparams) { pktbuf_t pktbuf; struct header_param param; struct dhcp *dhcphdr; struct dhcp_option *dhcpopt; unsigned int val4; memcpy(param.ethernet.src_macaddr, &dhcpparams->src_macaddr, ETHER_ADDR_LEN); memcpy(param.ethernet.dst_macaddr, ¶mp->ethernet.src_macaddr, ETHER_ADDR_LEN); param.ethernet.type = ETHERTYPE_IP; param.ip.id = 0x1234; param.ip.ttl = 64; param.ip.protocol = IPPROTO_UDP; param.ip.src_ipaddr = dhcpparams->server_ipaddr; param.ip.dst_ipaddr = dhcpparams->your_ip_address; param.udp.src_port = 67; param.udp.dst_port = 68; pktbuf = pktbuf_create(-1); dhcphdr = (struct dhcp *)pktbuf_add_header(pktbuf, sizeof(*dhcphdr) + 64); memset(dhcphdr, 0, sizeof(*dhcphdr)); dhcphdr->message_type = 2; /* Boot Reply */ dhcphdr->hardware_type = 1; /* Ethernet */ dhcphdr->hardware_addrlen = ETHER_ADDR_LEN; dhcphdr->transaction_id = htonl(dhcpparams->transaction_id); dhcphdr->your_ip_address = htonl(dhcpparams->your_ip_address); memcpy(dhcphdr->client_mac_address, &dhcpparams->client_macaddr, ETHER_ADDR_LEN); dhcphdr->magic_cookie = htonl(DHCP_MAGIC_COOKIE_DHCP); dhcpopt = (struct dhcp_option *)dhcphdr->option; dhcpopt->type = DHCP_OPTION_TYPE_MESSAGE_TYPE; dhcpopt->length = 1; dhcpopt->data[0] = 5; /* ACK */ dhcpopt = (struct dhcp_option *)((char *)dhcpopt + 2 + dhcpopt->length); dhcpopt->type = DHCP_OPTION_TYPE_SERVER_ID; dhcpopt->length = 4; val4 = htonl(dhcpparams->server_ipaddr); memcpy(dhcpopt->data, &val4, sizeof(val4)); dhcpopt = (struct dhcp_option *)((char *)dhcpopt + 2 + dhcpopt->length); dhcpopt->type = DHCP_OPTION_TYPE_IP_LEASE_TIME; dhcpopt->length = 4; val4 = htonl(600); memcpy(dhcpopt->data, &val4, sizeof(val4)); dhcpopt = (struct dhcp_option *)((char *)dhcpopt + 2 + dhcpopt->length); dhcpopt->type = DHCP_OPTION_TYPE_SUBNET_MASK; dhcpopt->length = 4; val4 = htonl(dhcpparams->subnet_mask); memcpy(dhcpopt->data, &val4, sizeof(val4)); dhcpopt = (struct dhcp_option *)((char *)dhcpopt + 2 + dhcpopt->length); dhcpopt->type = DHCP_OPTION_TYPE_DOMAIN_NAME; dhcpopt->length = 11; memcpy(dhcpopt->data, "example.org", 11); dhcpopt = (struct dhcp_option *)((char *)dhcpopt + 2 + dhcpopt->length); dhcpopt->type = DHCP_OPTION_TYPE_END; dhcpopt = (struct dhcp_option *)((char *)dhcpopt + 1); pktbuf_set_size(pktbuf, (char *)dhcpopt - (char *)dhcphdr); pktbuf = pktbuf_make_udp(pktbuf, ¶m); pktbuf = pktbuf_make_ip(pktbuf, ¶m); pktbuf = pktbuf_checksum_correct_ip(pktbuf); pktbuf = pktbuf_make_ethernet(pktbuf, ¶m); pktbuf = pktbuf_send(pktif, pktbuf); if (pktbuf) { pktbuf_destroy(pktbuf); return 0; } return 1; } static int analyze_dhcp_discover_or_request(struct dhcp *dhcphdr, struct dhcp_params *dhcpparams) { struct dhcp_option *dhcpopt; unsigned int ipaddr; if (dhcphdr->message_type != 1) /* Boot Request */ return 0; if (dhcphdr->hardware_type != 1) /* Ethernet */ return 0; if (dhcphdr->hardware_addrlen != ETHER_ADDR_LEN) return 0; if (ntohl(dhcphdr->magic_cookie) != DHCP_MAGIC_COOKIE_DHCP) return 0; dhcpparams->transaction_id = ntohl(dhcphdr->transaction_id); memcpy(&dhcpparams->client_macaddr, dhcphdr->client_mac_address, ETHER_ADDR_LEN); printf("Client MAC Address : %s\n", macaddr_s(dhcphdr->client_mac_address)); dhcpopt = (struct dhcp_option *)dhcphdr->option; while (1) { if (dhcpopt->type == DHCP_OPTION_TYPE_END) break; if (dhcpopt->type == DHCP_OPTION_TYPE_SERVER_ID) { ipaddr = htonl(dhcpparams->server_ipaddr); if (memcmp(&ipaddr, dhcpopt->data, sizeof(ipaddr))) return 0; memcpy(&ipaddr, dhcpopt->data, sizeof(ipaddr)); ipaddr = ntohl(ipaddr); printf("Server ID : %s\n", ipaddr_s(ipaddr)); } if (dhcpopt->type == DHCP_OPTION_TYPE_REQ_IP_ADDR) { ipaddr = htonl(dhcpparams->your_ip_address); if (memcmp(&ipaddr, dhcpopt->data, sizeof(ipaddr))) return 0; memcpy(&ipaddr, dhcpopt->data, sizeof(ipaddr)); ipaddr = ntohl(ipaddr); printf("Requested IP Address: %s\n", ipaddr_s(ipaddr)); } dhcpopt = (struct dhcp_option *)((char *)dhcpopt + 2 + dhcpopt->length); } return 1; } static int analyze_dhcp(struct dhcp *dhcphdr, struct dhcp_params *dhcpparams) { struct dhcp_option *dhcpopt; int type; dhcpopt = (struct dhcp_option *)dhcphdr->option; while (1) { if (dhcpopt->type == DHCP_OPTION_TYPE_END) break; if (dhcpopt->type == DHCP_OPTION_TYPE_MESSAGE_TYPE) { type = dhcpopt->data[0]; switch (type) { case 1: /* Discover */ case 3: /* Request */ switch (type) { case 1: printf("DHCP DISCOVER:\n"); break; case 3: printf("DHCP REQUEST:\n"); break; default: break; } if (analyze_dhcp_discover_or_request(dhcphdr, dhcpparams)> 0) return type; break; case 2: /* Offer */ case 5: /* ACK */ default: /* Unknown */ break; } } dhcpopt = (struct dhcp_option *)((char *)dhcpopt + 2 + dhcpopt->length); } return 0; } static int recv_dhcp(pktif_t pktif, struct header_param *paramp, struct dhcp_params *dhcpparams) { pktbuf_t pktbuf; int r = 0, next, payload = 0; struct header_param param; pktbuf = pktbuf_recv(pktif, 0); if (pktbuf) pktbuf_destroy(pktbuf); next = pktif_get_linktype(pktif); switch (next) { case DLT_EN10MB: r = pktbuf_analyze_ethernet(pktbuf, ¶m); break; default: break; } if (r> 0) { switch (next) { case DLT_EN10MB: printf("Ethernet:\n"); printf("\tsrc macaddr: %s\n", macaddr_s(param.ethernet.src_macaddr)); printf("\tdst macaddr: %s\n", macaddr_s(param.ethernet.dst_macaddr)); printf("\ttype : %04x\n", param.ethernet.type); payload += param.ethernet.header_size; next = param.ethernet.type; break; default: next = -1; break; } } if (r> 1) { switch (next) { case ETHERTYPE_IP: printf("IP:\n"); printf("\tid : %04x\n", param.ip.id); printf("\tttl : %04x\n", param.ip.ttl); printf("\tprotocol : %d\n", param.ip.protocol); printf("\tsrc ipaddr: %s\n", ipaddr_s(param.ip.src_ipaddr)); printf("\tdst ipaddr: %s\n", ipaddr_s(param.ip.dst_ipaddr)); payload += param.ip.header_size; next = param.ip.protocol; break; default: next = -1; break; } } if (r> 2) { switch (next) { case IPPROTO_UDP: printf("UDP:\n"); printf("\tsrc port: %d\n", param.udp.src_port); printf("\tdst port: %d\n", param.udp.dst_port); payload += param.udp.header_size; if ((param.udp.src_port == 68) && (param.udp.dst_port == 67)) { if (paramp) memcpy(paramp, ¶m, sizeof(*paramp)); return analyze_dhcp((struct dhcp *)(pktbuf_get_header(pktbuf) + payload), dhcpparams); } break; default: break; } } return 0; } int main(int argc, char *argv[]) { pktif_t pktif; struct header_param param; struct dhcp_params dhcpparams; argc--; argv++; pktif = pktif_open(argv[0], PKTIF_OPEN_FLAG_RECV_NOTSENT, 0); memcpy(&dhcpparams.src_macaddr, ether_aton(argv[1]), ETHER_ADDR_LEN); dhcpparams.server_ipaddr = (unsigned int)ntohl(inet_addr(argv[2])); dhcpparams.your_ip_address = (unsigned int)ntohl(inet_addr(argv[3])); dhcpparams.subnet_mask = (unsigned int)ntohl(inet_addr(argv[4])); while (recv_dhcp(pktif, ¶m, &dhcpparams) != 1) /* Discover */ ; send_dhcp_offer(pktif, ¶m, &dhcpparams); while (recv_dhcp(pktif, ¶m, &dhcpparams) != 3) /* Request */ ; send_dhcp_ack(pktif, ¶m, &dhcpparams); return 0; }

AltStyle によって変換されたページ (->オリジナル) /