5 #include <linux/icmp.h>
6 #include <netinet/icmp6.h>
8 #include <netinet/ip6.h>
14 static uint16_t _checksum(uint8_t *addr
, int count
);
16 void host_unreachable(in_addr_t destination
, uint16_t id
, in_addr_t source
, uint8_t *packet
, int packet_len
)
21 int len
= 0, on
= 1, icmp_socket
;
22 struct sockaddr_in whereto
= {0};
24 if ((icmp_socket
= socket(AF_INET
, SOCK_RAW
, IPPROTO_RAW
)) < 0)
27 setsockopt(icmp_socket
, IPPROTO_IP
, IP_HDRINCL
, (char *)&on
, sizeof(on
));
29 whereto
.sin_addr
.s_addr
= destination
;
30 whereto
.sin_family
= AF_INET
;
32 iph
= (struct iphdr
*)(buf
);
33 len
= sizeof(struct iphdr
);
34 icmp
= (struct icmphdr
*)(buf
+ len
);
35 len
+= sizeof(struct icmphdr
);
37 /* ip header + first 8 bytes of payload */
38 if (packet_len
> (sizeof(struct iphdr
) + 8))
39 packet_len
= sizeof(struct iphdr
) + 8;
41 memcpy(buf
+ len
, packet
, packet_len
);
53 iph
->daddr
= destination
;
56 iph
->tot_len
= ntohs(len
);
58 icmp
->type
= ICMP_DEST_UNREACH
;
59 icmp
->code
= ICMP_HOST_UNREACH
;
60 icmp
->checksum
= _checksum((uint8_t *) icmp
, sizeof(struct icmphdr
) + packet_len
);
62 iph
->check
= _checksum((uint8_t *) iph
, sizeof(struct iphdr
));
64 sendto(icmp_socket
, buf
, len
, 0, (struct sockaddr
*)&whereto
, sizeof(struct sockaddr
));
68 static uint16_t _checksum(uint8_t *addr
, int count
)
70 register long sum
= 0;
72 for (; count
> 1; count
-= 2)
74 sum
+= ntohs(*(uint16_t *) addr
);
78 if (count
> 0) sum
+= *(unsigned char *)addr
;
80 // take only 16 bits out of the 32 bit sum and add up the carries
82 sum
= (sum
& 0xFFFF) + (sum
>> 16);
84 // one's complement the result
87 return htons((uint16_t) sum
);
90 struct nd_opt_rdnss_info_l2tpns
92 uint8_t nd_opt_rdnssi_type
;
93 uint8_t nd_opt_rdnssi_len
;
94 uint16_t nd_opt_rdnssi_pref_flag_reserved
;
95 uint32_t nd_opt_rdnssi_lifetime
;
96 struct in6_addr nd_opt_rdnssi
[0];
99 void send_ipv6_ra(sessionidt s
, tunnelidt t
, struct in6_addr
*ip
)
101 struct nd_opt_prefix_info
*pinfo
;
102 struct ip6_hdr
*p_ip6_hdr
;
103 struct nd_router_advert
*p_nra
;
104 struct nd_opt_rdnss_info_l2tpns
*p_rdnss
;
105 uint8_t b
[MAXETHER
+ 20];
106 struct ipv6_pseudo_hdr pseudo_hdr
;
109 LOG(3, s
, t
, "Sending IPv6 RA\n");
111 memset(b
, 0, sizeof(b
));
112 p_ip6_hdr
= (struct ip6_hdr
*) makeppp(b
, sizeof(b
), 0, 0, s
, t
, PPPIPV6
, 0, 0, 0);
116 LOG(3, s
, t
, "failed to send IPv6 RA\n");
120 p_ip6_hdr
->ip6_vfc
= 0x60; // IPv6
121 p_ip6_hdr
->ip6_plen
= 0; // Length of payload (not header) (calculation below)
122 p_ip6_hdr
->ip6_nxt
= IPPROTO_ICMPV6
; // icmp6 is next
123 p_ip6_hdr
->ip6_hlim
= 255; // Hop limit
125 inet_pton(AF_INET6
, "FE80::1", &p_ip6_hdr
->ip6_src
.s6_addr
);
129 memcpy(p_ip6_hdr
->ip6_dst
.s6_addr
, ip
, 16); // dest = ip
133 // FF02::1 - all hosts
134 inet_pton(AF_INET6
, "FF02::1", &p_ip6_hdr
->ip6_dst
.s6_addr
);
137 // RA message after Ipv6 header
138 p_nra
= (struct nd_router_advert
*) &p_ip6_hdr
[1];
139 p_nra
->nd_ra_type
= ND_ROUTER_ADVERT
; // RA message (134)
140 p_nra
->nd_ra_code
= 0; // Code
141 p_nra
->nd_ra_cksum
= 0; // Checksum
142 p_nra
->nd_ra_curhoplimit
= 64; // Hop count
143 p_nra
->nd_ra_flags_reserved
= (ND_RA_FLAG_MANAGED
|ND_RA_FLAG_OTHER
); // Flags
144 p_nra
->nd_ra_router_lifetime
= 0xFFFF; // Lifetime
145 p_nra
->nd_ra_reachable
= 0; // Reachable time
146 p_nra
->nd_ra_retransmit
= 0; // Retrans timer
147 // Option PI after RA message (rfc4861)
148 pinfo
= (struct nd_opt_prefix_info
*) &p_nra
[1];
149 pinfo
->nd_opt_pi_type
= ND_OPT_PREFIX_INFORMATION
;
150 pinfo
->nd_opt_pi_len
= 4;
151 pinfo
->nd_opt_pi_flags_reserved
= ND_OPT_PI_FLAG_ONLINK
| ND_OPT_PI_FLAG_AUTO
;
152 pinfo
->nd_opt_pi_valid_time
= htonl(2592000);
153 pinfo
->nd_opt_pi_preferred_time
= htonl(604800);
154 pinfo
->nd_opt_pi_reserved2
= 0;
155 pinfo
->nd_opt_pi_prefix_len
= 64; // prefix length
156 if (session
[s
].ipv6address
.s6_addr
[0])
158 // MSB 64bits of assigned IPv6 address to user (see radius attribut Framed-IPv6-Address)
159 memcpy(&pinfo
->nd_opt_pi_prefix
, &session
[s
].ipv6address
.s6_addr
[0], 8);
162 pinfo
->nd_opt_pi_prefix
= config
->ipv6_prefix
;
164 // Length of payload (not header)
165 l
= sizeof(*pinfo
) + sizeof(*p_nra
);
167 if (config
->default_ipv6_dns1
.s6_addr32
[0])
169 struct in6_addr
*ptr_in6_addr
;
170 p_rdnss
= (struct nd_opt_rdnss_info_l2tpns
*) &pinfo
[1];
172 p_rdnss
->nd_opt_rdnssi_type
= 25; //RDNSS OPTION INFORMATION;
173 p_rdnss
->nd_opt_rdnssi_len
= 3; // 1 + 2 * nb DNS
174 p_rdnss
->nd_opt_rdnssi_lifetime
= htonl(config
->dns6_lifetime
);
175 ptr_in6_addr
= &p_rdnss
->nd_opt_rdnssi
[0];
176 memcpy(ptr_in6_addr
, &config
->default_ipv6_dns1
, sizeof(*ptr_in6_addr
));
178 l
+= sizeof(*p_rdnss
) + sizeof(*ptr_in6_addr
);
179 if (config
->default_ipv6_dns2
.s6_addr32
[0])
181 ptr_in6_addr
= &p_rdnss
->nd_opt_rdnssi
[1];
182 memcpy(ptr_in6_addr
, &config
->default_ipv6_dns2
, sizeof(*ptr_in6_addr
));
183 p_rdnss
->nd_opt_rdnssi_len
+= 2; // 1 + 2 * nb DNS
184 l
+= sizeof(*ptr_in6_addr
);
188 // Length of payload (not header)
189 p_ip6_hdr
->ip6_plen
= htons(l
);
191 /* Use pseudo hearder for checksum calculation */
192 memset(&pseudo_hdr
, 0, sizeof(pseudo_hdr
));
193 memcpy(&pseudo_hdr
.src
, &p_ip6_hdr
->ip6_src
, 16);
194 memcpy(&pseudo_hdr
.dest
, &p_ip6_hdr
->ip6_dst
, 16);
195 pseudo_hdr
.ulp_length
= htonl(l
); // Lenght whitout Ipv6 header
196 pseudo_hdr
.nexthdr
= IPPROTO_ICMPV6
;
197 // Checksum is over the icmp6 payload plus the pseudo header
198 p_nra
->nd_ra_cksum
= ipv6_checksum(&pseudo_hdr
, (uint8_t *) p_nra
, l
);
200 // Length + hearder length
201 l
+= sizeof(*p_ip6_hdr
);
203 tunnelsend(b
, l
+ (((uint8_t *) p_ip6_hdr
)-b
), t
); // send it...