1 /* 2 * Copyright 2006-2010, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include <net_datalink.h> 8 #include <net_protocol.h> 9 #include <net_stack.h> 10 #include <net_datalink_protocol.h> 11 #include <NetUtilities.h> 12 #include <NetBufferUtilities.h> 13 14 #include <KernelExport.h> 15 #include <util/list.h> 16 17 #include <netinet/icmp6.h> 18 #include <netinet/in.h> 19 #include <new> 20 #include <stdlib.h> 21 #include <string.h> 22 23 #include <ipv6_datagram/ndp.h> 24 25 26 #define TRACE_ICMP6 27 #ifdef TRACE_ICMP6 28 # define TRACE(x) dprintf x 29 #else 30 # define TRACE(x) ; 31 #endif 32 33 34 typedef NetBufferField<uint16, offsetof(icmp6_hdr, icmp6_cksum)> ICMP6ChecksumField; 35 36 37 net_buffer_module_info *gBufferModule; 38 static net_stack_module_info *sStackModule; 39 static net_ndp_module_info *sIPv6NDPModule; 40 41 42 net_protocol * 43 icmp6_init_protocol(net_socket *socket) 44 { 45 net_protocol *protocol = new (std::nothrow) net_protocol; 46 if (protocol == NULL) 47 return NULL; 48 49 return protocol; 50 } 51 52 53 status_t 54 icmp6_uninit_protocol(net_protocol *protocol) 55 { 56 delete protocol; 57 return B_OK; 58 } 59 60 61 status_t 62 icmp6_open(net_protocol *protocol) 63 { 64 return B_OK; 65 } 66 67 68 status_t 69 icmp6_close(net_protocol *protocol) 70 { 71 return B_OK; 72 } 73 74 75 status_t 76 icmp6_free(net_protocol *protocol) 77 { 78 return B_OK; 79 } 80 81 82 status_t 83 icmp6_connect(net_protocol *protocol, const struct sockaddr *address) 84 { 85 return B_ERROR; 86 } 87 88 89 status_t 90 icmp6_accept(net_protocol *protocol, struct net_socket **_acceptedSocket) 91 { 92 return EOPNOTSUPP; 93 } 94 95 96 status_t 97 icmp6_control(net_protocol *protocol, int level, int option, void *value, 98 size_t *_length) 99 { 100 return protocol->next->module->control(protocol->next, level, option, 101 value, _length); 102 } 103 104 105 status_t 106 icmp6_getsockopt(net_protocol *protocol, int level, int option, 107 void *value, int *length) 108 { 109 return protocol->next->module->getsockopt(protocol->next, level, option, 110 value, length); 111 } 112 113 114 status_t 115 icmp6_setsockopt(net_protocol *protocol, int level, int option, 116 const void *value, int length) 117 { 118 return protocol->next->module->setsockopt(protocol->next, level, option, 119 value, length); 120 } 121 122 123 status_t 124 icmp6_bind(net_protocol *protocol, const struct sockaddr *address) 125 { 126 return B_ERROR; 127 } 128 129 130 status_t 131 icmp6_unbind(net_protocol *protocol, struct sockaddr *address) 132 { 133 return B_ERROR; 134 } 135 136 137 status_t 138 icmp6_listen(net_protocol *protocol, int count) 139 { 140 return EOPNOTSUPP; 141 } 142 143 144 status_t 145 icmp6_shutdown(net_protocol *protocol, int direction) 146 { 147 return EOPNOTSUPP; 148 } 149 150 151 status_t 152 icmp6_send_data(net_protocol *protocol, net_buffer *buffer) 153 { 154 return protocol->next->module->send_data(protocol->next, buffer); 155 } 156 157 158 status_t 159 icmp6_send_routed_data(net_protocol *protocol, struct net_route *route, 160 net_buffer *buffer) 161 { 162 return protocol->next->module->send_routed_data(protocol->next, route, buffer); 163 } 164 165 166 ssize_t 167 icmp6_send_avail(net_protocol *protocol) 168 { 169 return B_ERROR; 170 } 171 172 173 status_t 174 icmp6_read_data(net_protocol *protocol, size_t numBytes, uint32 flags, 175 net_buffer **_buffer) 176 { 177 return B_ERROR; 178 } 179 180 181 ssize_t 182 icmp6_read_avail(net_protocol *protocol) 183 { 184 return B_ERROR; 185 } 186 187 188 struct net_domain * 189 icmp6_get_domain(net_protocol *protocol) 190 { 191 return protocol->next->module->get_domain(protocol->next); 192 } 193 194 195 size_t 196 icmp6_get_mtu(net_protocol *protocol, const struct sockaddr *address) 197 { 198 return protocol->next->module->get_mtu(protocol->next, address); 199 } 200 201 202 static net_domain* 203 get_domain(struct net_buffer* buffer) 204 { 205 net_domain* domain; 206 if (buffer->interface_address != NULL) 207 domain = buffer->interface_address->domain; 208 else 209 domain = sStackModule->get_domain(buffer->source->sa_family); 210 211 if (domain == NULL || domain->module == NULL) 212 return NULL; 213 214 return domain; 215 } 216 217 218 status_t 219 icmp6_receive_data(net_buffer *buffer) 220 { 221 TRACE(("ICMPv6 received some data, buffer length %lu\n", buffer->size)); 222 223 net_domain* domain = get_domain(buffer); 224 if (domain == NULL) 225 return B_ERROR; 226 227 NetBufferHeaderReader<icmp6_hdr> bufferHeader(buffer); 228 if (bufferHeader.Status() < B_OK) 229 return bufferHeader.Status(); 230 231 icmp6_hdr &header = bufferHeader.Data(); 232 233 TRACE((" got type %u, code %u, checksum 0x%x\n", header.icmp6_type, 234 header.icmp6_code, header.icmp6_cksum)); 235 236 net_address_module_info* addressModule = domain->address_module; 237 238 // compute and check the checksum 239 if (Checksum::PseudoHeader(addressModule, gBufferModule, buffer, 240 IPPROTO_ICMPV6) != 0) 241 return B_BAD_DATA; 242 243 switch (header.icmp6_type) { 244 case ICMP6_ECHO_REPLY: 245 break; 246 247 case ICMP6_ECHO_REQUEST: 248 { 249 if (buffer->interface_address != NULL) { 250 // We only reply to echo requests of our local interface; we 251 // don't reply to broadcast requests 252 if (!domain->address_module->equal_addresses( 253 buffer->interface_address->local, buffer->destination)) 254 break; 255 } 256 257 net_buffer *reply = gBufferModule->duplicate(buffer); 258 if (reply == NULL) 259 return B_NO_MEMORY; 260 261 gBufferModule->swap_addresses(reply); 262 263 // There already is an ICMP header, and we'll reuse it 264 NetBufferHeaderReader<icmp6_hdr> header(reply); 265 266 header->icmp6_type = ICMP6_ECHO_REPLY; 267 header->icmp6_code = 0; 268 header->icmp6_cksum = 0; 269 270 header.Sync(); 271 272 *ICMP6ChecksumField(reply) = Checksum::PseudoHeader(addressModule, 273 gBufferModule, buffer, IPPROTO_ICMPV6); 274 275 status_t status = domain->module->send_data(NULL, reply); 276 if (status < B_OK) { 277 gBufferModule->free(reply); 278 return status; 279 } 280 } 281 282 default: 283 // unrecognized messages go to neighbor discovery protocol handler 284 return sIPv6NDPModule->receive_data(buffer); 285 } 286 287 gBufferModule->free(buffer); 288 return B_OK; 289 } 290 291 292 status_t 293 icmp6_deliver_data(net_protocol *protocol, net_buffer *buffer) 294 { 295 // TODO: does this look OK? 296 return icmp6_receive_data(buffer); 297 } 298 299 300 status_t 301 icmp6_error_received(net_error code, net_buffer* data) 302 { 303 return B_ERROR; 304 } 305 306 307 status_t 308 icmp6_error_reply(net_protocol* protocol, net_buffer* buffer, net_error error, 309 net_error_data* errorData) 310 { 311 return B_ERROR; 312 } 313 314 315 // #pragma mark - 316 317 318 static status_t 319 icmp6_init() 320 { 321 sStackModule->register_domain_protocols(AF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6, 322 "network/protocols/icmp6/v1", 323 "network/protocols/ipv6/v1", 324 NULL); 325 326 sStackModule->register_domain_receiving_protocol(AF_INET6, IPPROTO_ICMPV6, 327 "network/protocols/icmp6/v1"); 328 329 return B_OK; 330 } 331 332 333 static status_t 334 icmp6_std_ops(int32 op, ...) 335 { 336 switch (op) { 337 case B_MODULE_INIT: 338 return icmp6_init(); 339 340 case B_MODULE_UNINIT: 341 return B_OK; 342 343 default: 344 return B_ERROR; 345 } 346 } 347 348 349 net_protocol_module_info sICMP6Module = { 350 { 351 "network/protocols/icmp6/v1", 352 0, 353 icmp6_std_ops 354 }, 355 NET_PROTOCOL_ATOMIC_MESSAGES, 356 357 icmp6_init_protocol, 358 icmp6_uninit_protocol, 359 icmp6_open, 360 icmp6_close, 361 icmp6_free, 362 icmp6_connect, 363 icmp6_accept, 364 icmp6_control, 365 icmp6_getsockopt, 366 icmp6_setsockopt, 367 icmp6_bind, 368 icmp6_unbind, 369 icmp6_listen, 370 icmp6_shutdown, 371 icmp6_send_data, 372 icmp6_send_routed_data, 373 icmp6_send_avail, 374 icmp6_read_data, 375 icmp6_read_avail, 376 icmp6_get_domain, 377 icmp6_get_mtu, 378 icmp6_receive_data, 379 icmp6_deliver_data, 380 icmp6_error_received, 381 icmp6_error_reply, 382 NULL, // add_ancillary_data() 383 NULL, // process_ancillary_data() 384 NULL, // process_ancillary_data_no_container() 385 NULL, // send_data_no_buffer() 386 NULL // read_data_no_buffer() 387 }; 388 389 module_dependency module_dependencies[] = { 390 {NET_STACK_MODULE_NAME, (module_info **)&sStackModule}, 391 {NET_BUFFER_MODULE_NAME, (module_info **)&gBufferModule}, 392 {"network/datalink_protocols/ipv6_datagram/ndp/v1", 393 (module_info **)&sIPv6NDPModule}, 394 {} 395 }; 396 397 module_info *modules[] = { 398 (module_info *)&sICMP6Module, 399 NULL 400 }; 401