3. udp头:struct udphdr
static void AppendIpv6Header(U8 *packet, DhcpMessageIpv6T *msg) { struct ip6_hdr *ip6hdr = DML_CAST_PTR(struct ip6_hdr *, packet); /* Parameter checks */ DML_ASSERTR(packet != NULL); DML_ASSERTR(msg != NULL); /* Fill in the IPv6 header. */ ip6hdr->ip6_flow = htonl ((6 << 28) | (0 << 20) | 0); // IPv6 version (4 bits), Traffic class (8 bits), Flow label (20 bits) ip6hdr->ip6_plen = htons(UDPHDR_LEN + msg->len); ip6hdr->ip6_nxt = IPPROTO_UDP; ip6hdr->ip6_hops = MAXTTL; memcpy(ip6hdr->ip6_src.s6_addr, msg->srcIp6, sizeof(msg->srcIp6)); memcpy(ip6hdr->ip6_dst.s6_addr, msg->dstIp6, sizeof(msg->dstIp6)); } static void AppendUdpHeader(U8 *packet, DhcpMessageIpv6T *msg) { struct udphdr *udphdr = DML_CAST_PTR(struct udphdr *, packet); U32 udpLength = 0; /* Parameter checks */ DML_ASSERTR(packet != NULL); DML_ASSERTR(msg != NULL); /* Calculate the UDP datagram length */ udpLength = UDPHDR_LEN + msg->len; /* Fill in the UDP header. */ udphdr->dest = htons(msg->dstPort); udphdr->source = htons(msg->srcPort); udphdr->len = htons(udpLength); udphdr->check = 0; } static DmlErrorT OpenSendL2SocketIpv6(DhcpCRawSocketIpv6T *dhcpSock) { S32 sock; U32 on = 1; /* Parameter checks */ DML_ASSERTRC(dhcpSock != NULL, DML_PARAM); DML_ASSERTRC(dhcpSock->sendL2Sock == INVALID_SOCKET, DML_ERROR); /* * Create a socket for sending/receiving broadcast DHCP messages */ sock = socket (PF_INET6, SOCK_RAW, htons(ETH_P_ALL)); if (sock < 0) { DML_LOG(DML_EVT_COMP_DHCP_CLIENT, DML_LOG_LVL_CRIT, "Could not create RAW Socket, errno=%s", strerror(errno)); return DML_ERROR; } /* Enable sending broadcast frames on this socket. */ if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0) { DML_LOG(DML_EVT_COMP_DHCP_CLIENT, DML_LOG_LVL_CRIT, "Could set BROADCAST option on socket, errno=%s", strerror(errno)); close(sock); return DML_ERROR; } dhcpSock->sendL2Sock = sock; DML_LOG(DML_EVT_COMP_DHCP_CLIENT, DML_LOG_LVL_TRACE,"Open DHCP send socket - %d\n", sock); return DML_OK; } DmlErrorT DhcpCRawSockSendL2Ipv6(DhcpCRawSocketIpv6T *dhcpSock, DhcpMessageIpv6T *msg) { S32 rc; U8 datagram[DHCP_MAX_MSG_SIZE]; U8 *datagramPtr = datagram; U8 *udpPtr = NULL; U32 datagramLen = 0; struct ethhdr *eth = NULL; struct sockaddr_pkt sockAddr; /* Parameter checks */ DML_ASSERTRC(dhcpSock != NULL, DML_PARAM); DML_ASSERTRC(msg != NULL, DML_PARAM); /* Fill in the Ethernet header. */ eth = DML_CAST_PTR(struct ethhdr *, datagramPtr); memcpy(eth->h_dest, msg->dstMac, sizeof(eth->h_dest)); memcpy(eth->h_source, msg->srcMac, sizeof(eth->h_source)); eth->h_proto = htons(ETH_P_IPV6); datagramPtr += ETHHDR_LEN; datagramLen += ETHHDR_LEN; /* Fill in the IP header. */ AppendIpv6Header(datagramPtr, msg); datagramPtr += IPV6HDR_LEN; datagramLen += IPV6HDR_LEN; /* Fill in the UDP header. * * Note, save a pointer to the UDP header because the checksum * will have to be computed over the entire frame after the data * is copied in. */ udpPtr = datagramPtr; AppendUdpHeader(datagramPtr, msg); datagramPtr += UDPHDR_LEN; datagramLen += UDPHDR_LEN; /* Check if there is enough room to copy the DHCP message into the * datagram buffer. */ if ((sizeof(datagram) - datagramLen) <= msg->len) { DML_LOG(DML_EVT_COMP_DHCP_CLIENT, DML_LOG_LVL_ERR, "Datagram buffer size %u too small for DHCP message length %u", sizeof(datagram), msg->len); return DML_ERROR; } /* Copy in the DHCP message into the datagram buffer */ memcpy(datagramPtr, &msg->pkt, msg->len); datagramPtr += msg->len; datagramLen += msg->len; /* Update the UDP checksum */ UpdateUdpChecksumIpv6(udpPtr, msg); /* Set up a socket address */ memset (&sockAddr, 0, sizeof sockAddr); sockAddr.spkt_family = AF_PACKET; strncpy ((char *)sockAddr.spkt_device, dhcpSock->name, sizeof sockAddr.spkt_device); sockAddr.spkt_protocol = htons(ETH_P_IPV6); DML_LOG(DML_EVT_COMP_DHCP_CLIENT, DML_LOG_LVL_TRACE,"send to broadcast socket %d to %s\n", dhcpSock->bcastSock, dhcpSock->name); /* Send the raw IP packet */ rc = sendto(dhcpSock->bcastSock, datagram, datagramLen, 0, (struct sockaddr *)&sockAddr, sizeof(sockAddr)); if (rc != (S32)(datagramLen)) { DML_LOG(DML_EVT_COMP_DHCP_CLIENT, DML_LOG_LVL_ERR, "sendto() failed: %s\n", strerror(errno)); return DML_ERROR; } return DML_OK; }