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 %" B_PRIu32 "\n", 222 buffer->size)); 223 224 net_domain* domain = get_domain(buffer); 225 if (domain == NULL) 226 return B_ERROR; 227 228 NetBufferHeaderReader<icmp6_hdr> bufferHeader(buffer); 229 if (bufferHeader.Status() < B_OK) 230 return bufferHeader.Status(); 231 232 icmp6_hdr &header = bufferHeader.Data(); 233 234 TRACE((" got type %u, code %u, checksum 0x%x\n", header.icmp6_type, 235 header.icmp6_code, header.icmp6_cksum)); 236 237 net_address_module_info* addressModule = domain->address_module; 238 239 // compute and check the checksum 240 if (Checksum::PseudoHeader(addressModule, gBufferModule, buffer, 241 IPPROTO_ICMPV6) != 0) 242 return B_BAD_DATA; 243 244 switch (header.icmp6_type) { 245 case ICMP6_ECHO_REPLY: 246 break; 247 248 case ICMP6_ECHO_REQUEST: 249 { 250 if (buffer->interface_address != NULL) { 251 // We only reply to echo requests of our local interface; we 252 // don't reply to broadcast requests 253 if (!domain->address_module->equal_addresses( 254 buffer->interface_address->local, buffer->destination)) 255 break; 256 } 257 258 net_buffer *reply = gBufferModule->duplicate(buffer); 259 if (reply == NULL) 260 return B_NO_MEMORY; 261 262 gBufferModule->swap_addresses(reply); 263 264 // There already is an ICMP header, and we'll reuse it 265 NetBufferHeaderReader<icmp6_hdr> header(reply); 266 267 header->icmp6_type = ICMP6_ECHO_REPLY; 268 header->icmp6_code = 0; 269 header->icmp6_cksum = 0; 270 271 header.Sync(); 272 273 *ICMP6ChecksumField(reply) = Checksum::PseudoHeader(addressModule, 274 gBufferModule, buffer, IPPROTO_ICMPV6); 275 276 status_t status = domain->module->send_data(NULL, reply); 277 if (status < B_OK) { 278 gBufferModule->free(reply); 279 return status; 280 } 281 } 282 283 default: 284 // unrecognized messages go to neighbor discovery protocol handler 285 return sIPv6NDPModule->receive_data(buffer); 286 } 287 288 gBufferModule->free(buffer); 289 return B_OK; 290 } 291 292 293 status_t 294 icmp6_deliver_data(net_protocol *protocol, net_buffer *buffer) 295 { 296 // TODO: does this look OK? 297 return icmp6_receive_data(buffer); 298 } 299 300 301 status_t 302 icmp6_error_received(net_error code, net_buffer* data) 303 { 304 return B_ERROR; 305 } 306 307 308 status_t 309 icmp6_error_reply(net_protocol* protocol, net_buffer* buffer, net_error error, 310 net_error_data* errorData) 311 { 312 return B_ERROR; 313 } 314 315 316 // #pragma mark - 317 318 319 static status_t 320 icmp6_init() 321 { 322 sStackModule->register_domain_protocols(AF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6, 323 "network/protocols/icmp6/v1", 324 "network/protocols/ipv6/v1", 325 NULL); 326 327 sStackModule->register_domain_receiving_protocol(AF_INET6, IPPROTO_ICMPV6, 328 "network/protocols/icmp6/v1"); 329 330 return B_OK; 331 } 332 333 334 static status_t 335 icmp6_std_ops(int32 op, ...) 336 { 337 switch (op) { 338 case B_MODULE_INIT: 339 return icmp6_init(); 340 341 case B_MODULE_UNINIT: 342 return B_OK; 343 344 default: 345 return B_ERROR; 346 } 347 } 348 349 350 net_protocol_module_info sICMP6Module = { 351 { 352 "network/protocols/icmp6/v1", 353 0, 354 icmp6_std_ops 355 }, 356 NET_PROTOCOL_ATOMIC_MESSAGES, 357 358 icmp6_init_protocol, 359 icmp6_uninit_protocol, 360 icmp6_open, 361 icmp6_close, 362 icmp6_free, 363 icmp6_connect, 364 icmp6_accept, 365 icmp6_control, 366 icmp6_getsockopt, 367 icmp6_setsockopt, 368 icmp6_bind, 369 icmp6_unbind, 370 icmp6_listen, 371 icmp6_shutdown, 372 icmp6_send_data, 373 icmp6_send_routed_data, 374 icmp6_send_avail, 375 icmp6_read_data, 376 icmp6_read_avail, 377 icmp6_get_domain, 378 icmp6_get_mtu, 379 icmp6_receive_data, 380 icmp6_deliver_data, 381 icmp6_error_received, 382 icmp6_error_reply, 383 NULL, // add_ancillary_data() 384 NULL, // process_ancillary_data() 385 NULL, // process_ancillary_data_no_container() 386 NULL, // send_data_no_buffer() 387 NULL // read_data_no_buffer() 388 }; 389 390 module_dependency module_dependencies[] = { 391 {NET_STACK_MODULE_NAME, (module_info **)&sStackModule}, 392 {NET_BUFFER_MODULE_NAME, (module_info **)&gBufferModule}, 393 {"network/datalink_protocols/ipv6_datagram/ndp/v1", 394 (module_info **)&sIPv6NDPModule}, 395 {} 396 }; 397 398 module_info *modules[] = { 399 (module_info *)&sICMP6Module, 400 NULL 401 }; 402