【Linux】

void sendmsg_packet_to_client(struct dhcp_packet *dhcp_pkt, int force_broadcast)
{
int fd = server_socket;
struct ifreq ifr;
struct msghdr msg;
struct sockaddr_in dest;
struct cmsghdr *cmptr;
struct iovec iov;
int iface_index = 0, ret = -1;
struct in_addr iface_addr;
struct arpreq arp_req;

union {
	struct cmsghdr align; /* this ensures alignment */
	char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
} control_u;

/* fill cmsg for outbound interface (both broadcast & unicast) */
struct in_pktinfo *pkt;
msg.msg_control = control_u.control;
msg.msg_controllen = sizeof(control_u);
msg.msg_name = &dest;
msg.msg_namelen = sizeof(dest);
iov.iov_base = (void *)dhcp_pkt;
iov.iov_len = sizeof(struct dhcp_packet);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
cmptr = CMSG_FIRSTHDR(&msg);
pkt = (struct in_pktinfo *)CMSG_DATA(cmptr);
pkt->ipi_ifindex = ifopr_getifindex(fd, server_config.interface);
pkt->ipi_spec_dst.s_addr = 0;
msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
cmptr->cmsg_level = IPPROTO_IP;
cmptr->cmsg_type = IP_PKTINFO;

if (force_broadcast
	|| (ntohs(dhcp_pkt->flags) & 0x8000) 
	|| dhcp_pkt->hlen == 0 
	|| dhcp_pkt->hlen > sizeof(ifr.ifr_addr.sa_data) 
	|| dhcp_pkt->htype == 0)
{
	/* broadcast to 255.255.255.255 (or mac address invalid) */
	dest.sin_family = AF_INET;
	dest.sin_addr.s_addr = INADDR_BROADCAST;
	dest.sin_port = htons(CLIENT_PORT);
	bb_info_msg("%s %d : broadcast to 255.255.255.255\r\n", __FUNCTION__, __LINE__);
}
else
{
	/* unicast to unconfigured client. Inject mac address direct into ARP cache.
	struct sockaddr limits size to 14 bytes. */
	dest.sin_family = AF_INET;
	dest.sin_addr = *(struct in_addr*)&dhcp_pkt->yiaddr;
	dest.sin_port = htons(CLIENT_PORT);
	memcpy(&arp_req.arp_pa, &dest, sizeof(struct sockaddr_in));
	arp_req.arp_pa.sa_family = AF_INET;
	strncpy(arp_req.arp_dev, server_config.interface, 16);
	arp_req.arp_ha.sa_family = dhcp_pkt->htype;
	memcpy(arp_req.arp_ha.sa_data, dhcp_pkt->chaddr, dhcp_pkt->hlen);
	/* interface name already copied in */
	arp_req.arp_flags = ATF_COM;
	if (ioctl(fd, SIOCSARP, &arp_req) == -1)
	{
		bb_info_msg("%s %d : ARP-cache injection failed : %s on %s\r\n", __FUNCTION__, __LINE__, strerror(errno), server_config.interface);
	}
}
if (0 > (ret = sendmsg(fd, &msg, 0)))
{
	bb_info_msg("%s %d : sendmsg failed : %s \r\n", __FUNCTION__, __LINE__, strerror(errno));
}

}

static int ifopr_getifindex(int sockfd, const char *ifname)
{
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
if (-1 == ioctl(sockfd, SIOCGIFINDEX, &ifr))
{
return -1;
}
return ifr.ifr_ifindex;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值