source: MondoRescue/branches/3.3/mindi-busybox/networking/udhcp/d6_packet.c@ 3803

Last change on this file since 3803 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

  • Property svn:eol-style set to native
File size: 4.4 KB
Line 
1/* vi: set sw=4 ts=4: */
2/*
3 * Copyright (C) 2011 Denys Vlasenko.
4 *
5 * Licensed under GPLv2, see file LICENSE in this source tree.
6 */
7#include "common.h"
8#include "d6_common.h"
9#include "dhcpd.h"
10#include <netinet/in.h>
11#include <netinet/if_ether.h>
12#include <netpacket/packet.h>
13
14#if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 2
15void FAST_FUNC d6_dump_packet(struct d6_packet *packet)
16{
17 if (dhcp_verbose < 2)
18 return;
19
20 bb_error_msg(
21 "xid %x"
22 , packet->d6_xid32
23 );
24 //*bin2hex(buf, (void *) packet->chaddr, sizeof(packet->chaddr)) = '\0';
25 //bb_error_msg(" chaddr %s", buf);
26}
27#endif
28
29int FAST_FUNC d6_recv_kernel_packet(struct in6_addr *peer_ipv6
30 UNUSED_PARAM
31 , struct d6_packet *packet, int fd)
32{
33 int bytes;
34
35 memset(packet, 0, sizeof(*packet));
36 bytes = safe_read(fd, packet, sizeof(*packet));
37 if (bytes < 0) {
38 log1("packet read error, ignoring");
39 return bytes; /* returns -1 */
40 }
41
42 if (bytes < offsetof(struct d6_packet, d6_options)) {
43 bb_error_msg("packet with bad magic, ignoring");
44 return -2;
45 }
46 log1("received %s", "a packet");
47 d6_dump_packet(packet);
48
49 return bytes;
50}
51
52/* Construct a ipv6+udp header for a packet, send packet */
53int FAST_FUNC d6_send_raw_packet(
54 struct d6_packet *d6_pkt, unsigned d6_pkt_size,
55 struct in6_addr *src_ipv6, int source_port,
56 struct in6_addr *dst_ipv6, int dest_port, const uint8_t *dest_arp,
57 int ifindex)
58{
59 struct sockaddr_ll dest_sll;
60 struct ip6_udp_d6_packet packet;
61 int fd;
62 int result = -1;
63 const char *msg;
64
65 fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6));
66 if (fd < 0) {
67 msg = "socket(%s)";
68 goto ret_msg;
69 }
70
71 memset(&dest_sll, 0, sizeof(dest_sll));
72 memset(&packet, 0, offsetof(struct ip6_udp_d6_packet, data));
73 packet.data = *d6_pkt; /* struct copy */
74
75 dest_sll.sll_family = AF_PACKET;
76 dest_sll.sll_protocol = htons(ETH_P_IPV6);
77 dest_sll.sll_ifindex = ifindex;
78 dest_sll.sll_halen = 6;
79 memcpy(dest_sll.sll_addr, dest_arp, 6);
80
81 if (bind(fd, (struct sockaddr *)&dest_sll, sizeof(dest_sll)) < 0) {
82 msg = "bind(%s)";
83 goto ret_close;
84 }
85
86 packet.ip6.ip6_vfc = (6 << 4); /* 4 bits version, top 4 bits of tclass */
87 if (src_ipv6)
88 packet.ip6.ip6_src = *src_ipv6; /* struct copy */
89 packet.ip6.ip6_dst = *dst_ipv6; /* struct copy */
90 packet.udp.source = htons(source_port);
91 packet.udp.dest = htons(dest_port);
92 /* size, excluding IP header: */
93 packet.udp.len = htons(sizeof(struct udphdr) + d6_pkt_size);
94 packet.ip6.ip6_plen = packet.udp.len;
95 /*
96 * Someone was smoking weed (at least) while inventing UDP checksumming:
97 * UDP checksum skips first four bytes of IPv6 header.
98 * 'next header' field should be summed as if it is one more byte
99 * to the right, therefore we write its value (IPPROTO_UDP)
100 * into ip6_hlim, and its 'real' location remains zero-filled for now.
101 */
102 packet.ip6.ip6_hlim = IPPROTO_UDP;
103 packet.udp.check = inet_cksum(
104 (uint16_t *)&packet + 2,
105 offsetof(struct ip6_udp_d6_packet, data) - 4 + d6_pkt_size
106 );
107 /* fix 'hop limit' and 'next header' after UDP checksumming */
108 packet.ip6.ip6_hlim = 1; /* observed Windows machines to use hlim=1 */
109 packet.ip6.ip6_nxt = IPPROTO_UDP;
110
111 d6_dump_packet(d6_pkt);
112 result = sendto(fd, &packet, offsetof(struct ip6_udp_d6_packet, data) + d6_pkt_size,
113 /*flags:*/ 0,
114 (struct sockaddr *) &dest_sll, sizeof(dest_sll)
115 );
116 msg = "sendto";
117 ret_close:
118 close(fd);
119 if (result < 0) {
120 ret_msg:
121 bb_perror_msg(msg, "PACKET");
122 }
123 return result;
124}
125
126/* Let the kernel do all the work for packet generation */
127int FAST_FUNC d6_send_kernel_packet(
128 struct d6_packet *d6_pkt, unsigned d6_pkt_size,
129 struct in6_addr *src_ipv6, int source_port,
130 struct in6_addr *dst_ipv6, int dest_port)
131{
132 struct sockaddr_in6 sa;
133 int fd;
134 int result = -1;
135 const char *msg;
136
137 fd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
138 if (fd < 0) {
139 msg = "socket(%s)";
140 goto ret_msg;
141 }
142 setsockopt_reuseaddr(fd);
143
144 memset(&sa, 0, sizeof(sa));
145 sa.sin6_family = AF_INET6;
146 sa.sin6_port = htons(source_port);
147 sa.sin6_addr = *src_ipv6; /* struct copy */
148 if (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
149 msg = "bind(%s)";
150 goto ret_close;
151 }
152
153 memset(&sa, 0, sizeof(sa));
154 sa.sin6_family = AF_INET6;
155 sa.sin6_port = htons(dest_port);
156 sa.sin6_addr = *dst_ipv6; /* struct copy */
157 if (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
158 msg = "connect";
159 goto ret_close;
160 }
161
162 d6_dump_packet(d6_pkt);
163 result = safe_write(fd, d6_pkt, d6_pkt_size);
164 msg = "write";
165 ret_close:
166 close(fd);
167 if (result < 0) {
168 ret_msg:
169 bb_perror_msg(msg, "UDP");
170 }
171 return result;
172}
Note: See TracBrowser for help on using the repository browser.