📄 net_ipv4_bootp.c
字号:
{ DHCP_SOURCE_ROUTING, DHCPOPT_INT8 }, { DHCP_POLICY_FILTER, DHCPOPT_IPADDR2 | DHCPOPT_LIST }, { DHCP_MAX_DGRAM_REASM, DHCPOPT_INT16 }, { DHCP_IP_TTL, DHCPOPT_INT8 }, { DHCP_PATH_MTU_TIMEOUT, DHCPOPT_INT32 }, { DHCP_PATH_MTU_PLATEAU, DHCPOPT_INT16 | DHCPOPT_LIST }, { DHCP_MTU, DHCPOPT_INT16 }, { DHCP_SUBNET_LOCAL, DHCPOPT_INT8 }, { DHCP_BROADCAST, DHCPOPT_IPADDR }, { DHCP_MASK_DISCOVERY, DHCPOPT_INT8 }, { DHCP_MASK_SUPPLIER, DHCPOPT_INT8 }, { DHCP_ROUTER_DISCOVERY, DHCPOPT_INT8 }, { DHCP_ROUTER_SOLICITATE, DHCPOPT_IPADDR }, { DHCP_STATIC_ROUTE, DHCPOPT_IPADDR2 | DHCPOPT_LIST }, { DHCP_TRAILER_ENCAP, DHCPOPT_INT8 }, { DHCP_ARP_CACHE_TIMEOUT, DHCPOPT_INT32 }, { DHCP_ETHERNET_ENCAP, DHCPOPT_INT8 }, { DHCP_TCP_TTL, DHCPOPT_INT8 }, { DHCP_TCP_KEEPALIVE_INT, DHCPOPT_INT32 }, { DHCP_TCP_KEEPALIVE_GAR, DHCPOPT_INT32 }, { DHCP_NIS_DOMAIN, DHCPOPT_STR }, { DHCP_NIS_SERVER, DHCPOPT_IPADDR | DHCPOPT_LIST }, { DHCP_NTP_SERVER, DHCPOPT_IPADDR | DHCPOPT_LIST }, { DHCP_VENDOR_SPECIFIC, DHCPOPT_STR }, { DHCP_NBNS_SERVER, DHCPOPT_IPADDR | DHCPOPT_LIST }, { DHCP_NBDD_SERVER, DHCPOPT_IPADDR | DHCPOPT_LIST }, { DHCP_NB_NODETYPE, DHCPOPT_INT8 }, { DHCP_XFONT_SERVER, DHCPOPT_IPADDR | DHCPOPT_LIST }, { DHCP_XDISPLAY_MANAGER, DHCPOPT_IPADDR }, { DHCP_REQUESTED_IP, DHCPOPT_IPADDR }, { DHCP_LEASE_TIME, DHCPOPT_INT32 }, { DHCPOPTION_OVERLOAD, DHCPOPT_INT8 }, { DHCP_MESSAGE_TYPE, DHCPOPT_INT8 }, { DHCP_SERVER_ID, DHCPOPT_INT32 }, { DHCP_PARAM_REQUEST, DHCPOPT_INT8 | DHCPOPT_LIST }, { DHCP_MESSAGE, DHCPOPT_STR }, { DHCP_MAX_SIZE, DHCPOPT_INT16 }, { DHCP_T1, DHCPOPT_INT32 }, { DHCP_T2, DHCPOPT_INT32 }, { DHCP_VENDOR_CLASS_ID, DHCPOPT_STR }, { DHCP_CLIENT_ID, DHCPOPT_VARIABLE }, { DHCP_NISPLUS_DOMAIN, DHCPOPT_STR }, { DHCP_NISPLUS_SERVER, DHCPOPT_IPADDR | DHCPOPT_LIST }, { DHCP_TFTP_SERVERNAME, DHCPOPT_STR }, { DHCP_BOOTFILE, DHCPOPT_STR }, { DHCP_MOBILE_IP_AGENT, DHCPOPT_IPADDR | DHCPOPT_LIST }, { DHCP_SMTP_SERVER, DHCPOPT_IPADDR | DHCPOPT_LIST }, { DHCP_POP3_SERVER, DHCPOPT_IPADDR | DHCPOPT_LIST }, { DHCP_NNTP_SERVER, DHCPOPT_IPADDR | DHCPOPT_LIST }, { DHCP_WWW_SERVER, DHCPOPT_IPADDR | DHCPOPT_LIST }, { DHCP_FINGER_SERVER, DHCPOPT_IPADDR | DHCPOPT_LIST }, { DHCP_IRC_SERVER, DHCPOPT_IPADDR | DHCPOPT_LIST }, { DHCP_ST_SERVER, DHCPOPT_IPADDR | DHCPOPT_LIST }, { DHCP_ST_DA_SERVER, DHCPOPT_IPADDR | DHCPOPT_LIST }, { 0, 0 },};/* OPTION : [code] [len] [data...] */#define DHCPOPT_CODE 0#define DHCPOPT_LEN 1#define DHCPOPT_DATA 2/* * function prototypes */int dhcp_send_discover(unsigned int xid);int dhcp_send_request(unsigned int xid, in_addr_t ipaddr, in_addr_t serverid);void dhcp_init_packet(bootphdr_t *pbp, int type);void dhcp_add_request_option(bootphdr_t *pbp);void dhcp_option_appendstr(unsigned char *str, unsigned char *opt);void dhcp_option_add(unsigned char *str, int code, unsigned int data, int list);/* * DHCP protocol *//* Broadcast a DHCP discover packet to the network, with an optionally requested IP */int dhcp_send_discover(unsigned int xid){ bootpip_t packet; dhcp_init_packet(&packet.bp, DHCPDISCOVER); packet.bp.bp_xid = xid; dhcp_add_request_option(&packet.bp); return udp_transmit(INADDR_BROADCAST, IPPORT_BOOTP_CLIENT, IPPORT_BOOTP_SERVER, sizeof packet.bp, &packet, 0);}int dhcp_send_request(unsigned int xid, in_addr_t ipaddr, in_addr_t serverid){ bootpip_t packet; dhcp_init_packet(&packet.bp, DHCPREQUEST); packet.bp.bp_xid = xid; dhcp_option_add(packet.bp.bp_vend, DHCP_REQUESTED_IP, ipaddr, 0); dhcp_option_add(packet.bp.bp_vend, DHCP_SERVER_ID, serverid, 0); dhcp_add_request_option(&packet.bp); return udp_transmit(INADDR_BROADCAST, IPPORT_BOOTP_CLIENT, IPPORT_BOOTP_SERVER, sizeof packet.bp, &packet, 0);}/* * DHCP packet *//* initialize a packet with the proper defaults */void dhcp_init_packet(bootphdr_t *pbp, int type){ static char s_vendorid[] = "Sigma Designs Bootloader"; unsigned char clientid[8]; memset(pbp, 0, sizeof(bootphdr_t)); switch (type) { case DHCPDISCOVER : case DHCPREQUEST : case DHCPRELEASE : case DHCPINFORM : pbp->bp_op = BOOTP_REQUEST; break; case DHCPOFFER : case DHCPACK : case DHCPNAK : pbp->bp_op = BOOTP_REPLY; break; } pbp->bp_htype = 1; // 10MB ethernet pbp->bp_hlen = ETH_ALEN; // 10MB ethernet pbp->bp_yiaddr = INADDR_NONE; pbp->bp_siaddr = INADDR_NONE; memcpy(pbp->bp_hwaddr, g_arptable[ARP_CLIENT].node, ETH_ALEN); // // DHCP magic code *((unsigned int *) pbp->bp_vend) = htonl(DHCP_MAGIC); pbp->bp_vend[4] = DHCP_END; // DHCP options dhcp_option_add(pbp->bp_vend, DHCP_MESSAGE_TYPE, type, 0); dhcp_option_add(pbp->bp_vend, DHCP_VENDOR_CLASS_ID, (unsigned int) s_vendorid, 0); clientid[0] = 1; memcpy(clientid + 1, g_arptable[ARP_CLIENT].node, ETH_ALEN); dhcp_option_add(pbp->bp_vend, DHCP_CLIENT_ID, (unsigned int) clientid, 7);}void dhcp_add_request_option(bootphdr_t *pbp){ static unsigned char s_request[] = { DHCP_SUBNET, DHCP_ROUTER, DHCP_DNS_SERVER, DHCP_HOST_NAME, DHCP_DOMAIN_NAME, DHCP_BROADCAST, DHCP_TFTP_SERVERNAME, DHCP_BOOTFILE }; dhcp_option_add(pbp->bp_vend, DHCP_PARAM_REQUEST, (unsigned int) s_request, sizeof s_request);}/* * DHCP options : */void dhcp_option_appendstr(unsigned char *str, unsigned char *opt){ int i, len; // look for the end of option for (i = 4; str[i] != DHCP_END;) { if (str[i] == DHCP_PADDING) ++i; else i += str[i + DHCPOPT_LEN] + 2; } len = opt[DHCPOPT_LEN] + 2; memcpy(str + i, opt, len); str[i + len] = DHCP_END;}// data : // 1, 2, 4 byte integer// type casted pointer to string// type casted pointer to array// list : // 0 : data is normal integer or pointer to string// 1 : data is array with one item// > 1 : data is array with more than one item// with the option type 'DHCPOPT_VARIABLE', list means size of arrayvoid dhcp_option_add(unsigned char *str, int code, unsigned int data, int list){ int i, len, copylen; unsigned char optstr[128]; uint8_t *ptr8, *ptrarr8; uint16_t *ptrarr16, data16; uint32_t *ptrarr32, data32; for (i = 0; s_option_list[i].code != 0; ++i) if (s_option_list[i].code == code) break; // invalid option code if (s_option_list[i].code == 0) return; // code optstr[DHCPOPT_CODE] = (unsigned char) code; // copy data len = s_option_len[s_option_list[i].flags & DHCPOPT_TYPEMASK]; copylen = 0; // don't use pointer to uint16_t or uint32_t // due to the alignment, pointer returns wrong value ptr8 = (uint8_t *) (optstr + DHCPOPT_DATA); switch (len) { case 1 : if (list) { ptrarr8 = (uint8_t *) data; copylen = list * 1; while (list-- > 0) *ptr8++ = *ptrarr8++; } else { copylen = 1; *ptr8 = (uint8_t) data; } break; case 2 : if (list) { ptrarr16 = (uint16_t *) data; copylen = list * 2; while (list-- > 0) { data16 = htons(*ptrarr16++); memcpy(ptr8, &data16, 2); ptr8 += 2; } } else { copylen = 2; data16 = htons((uint16_t) data); memcpy(ptr8, &data16, 2); ptr8 += 2; } break; case 4 : if (list) { ptrarr32 = (uint32_t *) data; copylen = list * 4; while (list-- > 0) { data32 = htonl(*ptrarr32++); memcpy(ptr8, &data32, 4); ptr8 += 4; } } else { copylen = 4; data32 = htonl((uint32_t) data); memcpy(ptr8, &data32, 4); ptr8 += 4; } break; case -1 : copylen = strlen((unsigned char *) data); memcpy(optstr + DHCPOPT_DATA, (void *) data, copylen); break; case -2 : copylen = list; memcpy(optstr + DHCPOPT_DATA, (void *) data, copylen); break; default : // invalid length. break; } // option length optstr[DHCPOPT_LEN] = copylen; dhcp_option_appendstr(str, optstr);}void dhcp_parse_option(unsigned char *str, dhcp_info_t *info){ unsigned char *cp = str; uint8_t *ptr8; uint16_t data16; uint32_t data32; memset(info, 0, sizeof(dhcp_info_t)); // look for the end of option for (cp += 4; *cp != DHCP_END;) { if (*cp == DHCP_PADDING) ++cp; else { // don't use pointer to uint16_t or uint32_t // due to the alignment, pointer returns wrong value ptr8 = cp + DHCPOPT_DATA; data16 = (ptr8[0] << 8) | (ptr8[1]); data32 = (data16 << 16) | (ptr8[2] << 8) | (ptr8[3]); switch (cp[DHCPOPT_CODE]) { case DHCP_MESSAGE_TYPE : info->message_type = *ptr8; break; case DHCP_SERVER_ID : info->server_id = data32; break; case DHCP_LEASE_TIME : info->lease_time = data32; break; case DHCP_SUBNET : info->subnet = data32; break; case DHCP_ROUTER : info->router = data32; break; case DHCP_DNS_SERVER : info->dns_server = data32; break; case DHCP_BROADCAST : info->broadcast = data32; break; case DHCP_DOMAIN_NAME : strncpy0(info->domain, ptr8, cp[DHCPOPT_LEN] + 1); break; case DHCP_TFTP_SERVERNAME : strncpy0(info->tftpserver, ptr8, cp[DHCPOPT_LEN] + 1); break; case DHCP_BOOTFILE : strncpy0(info->bootfile, ptr8, cp[DHCPOPT_LEN] + 1); break; } cp += cp[DHCPOPT_LEN] + 2; } }}// show BOOTP packet contentsvoid bootp_dump_packet(struct sk_buff *skb, int need_parsing){ int i; unsigned char *cp; if (need_parsing) bootp_parsepacket(skb); uart_printf("BOOTP : \n"); uart_printf(" opcode : %02x (%s)\n", skb->bootp->bp_op, skb->bootp->bp_op == BOOTP_REQUEST ? "Request" : "Reply"); uart_printf(" htype : %02x\n", skb->bootp->bp_htype); uart_printf(" hlen : %02x\n", skb->bootp->bp_hlen); uart_printf(" xid : %08x\n", skb->bootp->bp_xid); uart_printf(" secs : %04x\n", skb->bootp->bp_secs); uart_printf(" Client Address : %s (%08x)\n", ipaddr_to_str(skb->bootp->bp_ciaddr), skb->bootp->bp_ciaddr); uart_printf(" Your Address : %s (%08x)\n", ipaddr_to_str(skb->bootp->bp_yiaddr), skb->bootp->bp_yiaddr); uart_printf(" Server Address : %s (%08x)\n", ipaddr_to_str(skb->bootp->bp_siaddr), skb->bootp->bp_siaddr); uart_printf(" Gateway Address : %s (%08x)\n", ipaddr_to_str(skb->bootp->bp_giaddr), skb->bootp->bp_giaddr); uart_printf(" Hardware Address : %02X:%02X:%02X:%02X:%02X:%02X\n", skb->bootp->bp_hwaddr[0], skb->bootp->bp_hwaddr[1], skb->bootp->bp_hwaddr[2], skb->bootp->bp_hwaddr[3], skb->bootp->bp_hwaddr[4], skb->bootp->bp_hwaddr[5]); uart_printf(" Options :\n"); for (cp = skb->bootp->bp_vend + 4; *cp != DHCP_END;) { if (*cp == DHCP_PADDING) ++cp; else { uart_printf(" %02x, %02x : ", cp[0], cp[1]); for (i = 2; i < cp[1] + 2; ++i) uart_printf("%02x ", cp[i]); uart_printf("\n"); cp += cp[DHCPOPT_LEN] + 2; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -