Changes in uspace/srv/net/inetsrv/inet_link.c [3e6a98c5:b417559] in mainline
- File:
-
- 1 edited
-
uspace/srv/net/inetsrv/inet_link.c (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/inetsrv/inet_link.c
r3e6a98c5 rb417559 43 43 #include <stdlib.h> 44 44 #include <str.h> 45 45 #include <net/socket_codes.h> 46 46 #include "addrobj.h" 47 47 #include "inetsrv.h" … … 49 49 #include "pdu.h" 50 50 51 static int inet_link_open(service_id_t sid); 52 static int inet_iplink_recv(iplink_t *ilink, iplink_sdu_t *sdu); 51 static bool first_link = true; 52 static bool first_link6 = true; 53 54 static FIBRIL_MUTEX_INITIALIZE(ip_ident_lock); 55 static uint16_t ip_ident = 0; 56 57 static int inet_iplink_recv(iplink_t *, iplink_recv_sdu_t *, uint16_t); 58 static inet_link_t *inet_link_get_by_id_locked(sysarg_t); 53 59 54 60 static iplink_ev_ops_t inet_iplink_ev_ops = { … … 56 62 }; 57 63 58 static LIST_INITIALIZE(inet_link_list); 59 static FIBRIL_MUTEX_INITIALIZE(inet_discovery_lock); 60 61 static int inet_iplink_recv(iplink_t *iplink, iplink_sdu_t *sdu) 62 { 64 static LIST_INITIALIZE(inet_links); 65 static FIBRIL_MUTEX_INITIALIZE(inet_links_lock); 66 67 static addr128_t link_local_node_ip = 68 {0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xfe, 0, 0, 0}; 69 70 static void inet_link_local_node_ip(addr48_t mac_addr, 71 addr128_t ip_addr) 72 { 73 memcpy(ip_addr, link_local_node_ip, 16); 74 75 ip_addr[8] = mac_addr[0] ^ 0x02; 76 ip_addr[9] = mac_addr[1]; 77 ip_addr[10] = mac_addr[2]; 78 ip_addr[13] = mac_addr[3]; 79 ip_addr[14] = mac_addr[4]; 80 ip_addr[15] = mac_addr[5]; 81 } 82 83 static int inet_iplink_recv(iplink_t *iplink, iplink_recv_sdu_t *sdu, uint16_t af) 84 { 85 log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_iplink_recv()"); 86 87 int rc; 63 88 inet_packet_t packet; 64 int rc; 65 66 log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_iplink_recv()"); 67 rc = inet_pdu_decode(sdu->data, sdu->size, &packet); 89 90 switch (af) { 91 case AF_INET: 92 rc = inet_pdu_decode(sdu->data, sdu->size, &packet); 93 break; 94 case AF_INET6: 95 rc = inet_pdu_decode6(sdu->data, sdu->size, &packet); 96 break; 97 default: 98 log_msg(LOG_DEFAULT, LVL_DEBUG, "invalid address family"); 99 return EINVAL; 100 } 101 68 102 if (rc != EOK) { 69 103 log_msg(LOG_DEFAULT, LVL_DEBUG, "failed decoding PDU"); 70 104 return rc; 71 105 } 72 106 73 107 log_msg(LOG_DEFAULT, LVL_DEBUG, "call inet_recv_packet()"); 74 108 rc = inet_recv_packet(&packet); 75 109 log_msg(LOG_DEFAULT, LVL_DEBUG, "call inet_recv_packet -> %d", rc); 76 110 free(packet.data); 77 111 78 112 return rc; 79 }80 81 static int inet_link_check_new(void)82 {83 bool already_known;84 category_id_t iplink_cat;85 service_id_t *svcs;86 size_t count, i;87 int rc;88 89 fibril_mutex_lock(&inet_discovery_lock);90 91 rc = loc_category_get_id("iplink", &iplink_cat, IPC_FLAG_BLOCKING);92 if (rc != EOK) {93 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed resolving category 'iplink'.");94 fibril_mutex_unlock(&inet_discovery_lock);95 return ENOENT;96 }97 98 rc = loc_category_get_svcs(iplink_cat, &svcs, &count);99 if (rc != EOK) {100 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed getting list of IP links.");101 fibril_mutex_unlock(&inet_discovery_lock);102 return EIO;103 }104 105 for (i = 0; i < count; i++) {106 already_known = false;107 108 list_foreach(inet_link_list, ilink_link) {109 inet_link_t *ilink = list_get_instance(ilink_link,110 inet_link_t, link_list);111 if (ilink->svc_id == svcs[i]) {112 already_known = true;113 break;114 }115 }116 117 if (!already_known) {118 log_msg(LOG_DEFAULT, LVL_DEBUG, "Found IP link '%lu'",119 (unsigned long) svcs[i]);120 rc = inet_link_open(svcs[i]);121 if (rc != EOK)122 log_msg(LOG_DEFAULT, LVL_ERROR, "Could not open IP link.");123 }124 }125 126 fibril_mutex_unlock(&inet_discovery_lock);127 return EOK;128 113 } 129 114 … … 147 132 if (ilink->svc_name != NULL) 148 133 free(ilink->svc_name); 134 149 135 free(ilink); 150 136 } 151 137 152 staticint inet_link_open(service_id_t sid)138 int inet_link_open(service_id_t sid) 153 139 { 154 140 inet_link_t *ilink; 155 i plink_addr_t iaddr;141 inet_addr_t iaddr; 156 142 int rc; 157 143 … … 189 175 goto error; 190 176 } 177 178 /* 179 * Get the MAC address of the link. If the link has a MAC 180 * address, we assume that it supports NDP. 181 */ 182 rc = iplink_get_mac48(ilink->iplink, &ilink->mac); 183 ilink->mac_valid = (rc == EOK); 191 184 192 185 log_msg(LOG_DEFAULT, LVL_DEBUG, "Opened IP link '%s'", ilink->svc_name); 193 list_append(&ilink->link_list, &inet_link_list); 194 195 inet_addrobj_t *addr; 196 197 static int first = 1; 198 /* XXX For testing: set static IP address 192.168.0.4/24 */ 199 addr = inet_addrobj_new(); 200 if (first) { 201 addr->naddr.ipv4 = (127 << 24) + (0 << 16) + (0 << 8) + 1; 202 first = 0; 203 } else { 204 addr->naddr.ipv4 = (192 << 24) + (168 << 16) + (0 << 8) + 4; 205 } 206 addr->naddr.bits = 24; 207 addr->ilink = ilink; 208 addr->name = str_dup("v4a"); 209 rc = inet_addrobj_add(addr); 210 if (rc != EOK) { 211 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed setting IP address on internet link."); 212 inet_addrobj_delete(addr); 213 /* XXX Roll back */ 214 return rc; 215 } 216 217 iaddr.ipv4 = addr->naddr.ipv4; 218 rc = iplink_addr_add(ilink->iplink, &iaddr); 219 if (rc != EOK) { 220 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed setting IP address on internet link."); 221 inet_addrobj_remove(addr); 222 inet_addrobj_delete(addr); 223 /* XXX Roll back */ 224 return rc; 225 } 226 186 187 fibril_mutex_lock(&inet_links_lock); 188 189 if (inet_link_get_by_id_locked(sid) != NULL) { 190 fibril_mutex_unlock(&inet_links_lock); 191 log_msg(LOG_DEFAULT, LVL_DEBUG, "Link %zu already open", 192 sid); 193 rc = EEXIST; 194 goto error; 195 } 196 197 list_append(&ilink->link_list, &inet_links); 198 fibril_mutex_unlock(&inet_links_lock); 199 200 inet_addrobj_t *addr = NULL; 201 202 /* XXX FIXME Cannot rely on loopback being the first IP link service!! */ 203 if (first_link) { 204 addr = inet_addrobj_new(); 205 206 inet_naddr(&addr->naddr, 127, 0, 0, 1, 24); 207 first_link = false; 208 } 209 210 if (addr != NULL) { 211 addr->ilink = ilink; 212 addr->name = str_dup("v4a"); 213 214 rc = inet_addrobj_add(addr); 215 if (rc == EOK) { 216 inet_naddr_addr(&addr->naddr, &iaddr); 217 rc = iplink_addr_add(ilink->iplink, &iaddr); 218 if (rc != EOK) { 219 log_msg(LOG_DEFAULT, LVL_ERROR, 220 "Failed setting IPv4 address on internet link."); 221 inet_addrobj_remove(addr); 222 inet_addrobj_delete(addr); 223 } 224 } else { 225 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed adding IPv4 address."); 226 inet_addrobj_delete(addr); 227 } 228 } 229 230 inet_addrobj_t *addr6 = NULL; 231 232 if (first_link6) { 233 addr6 = inet_addrobj_new(); 234 235 inet_naddr6(&addr6->naddr, 0, 0, 0, 0, 0, 0, 0, 1, 128); 236 first_link6 = false; 237 } else if (ilink->mac_valid) { 238 addr6 = inet_addrobj_new(); 239 240 addr128_t link_local; 241 inet_link_local_node_ip(ilink->mac, link_local); 242 243 inet_naddr_set6(link_local, 64, &addr6->naddr); 244 } 245 246 if (addr6 != NULL) { 247 addr6->ilink = ilink; 248 addr6->name = str_dup("v6a"); 249 250 rc = inet_addrobj_add(addr6); 251 if (rc == EOK) { 252 inet_naddr_addr(&addr6->naddr, &iaddr); 253 rc = iplink_addr_add(ilink->iplink, &iaddr); 254 if (rc != EOK) { 255 log_msg(LOG_DEFAULT, LVL_ERROR, 256 "Failed setting IPv6 address on internet link."); 257 inet_addrobj_remove(addr6); 258 inet_addrobj_delete(addr6); 259 } 260 } else { 261 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed adding IPv6 address."); 262 inet_addrobj_delete(addr6); 263 } 264 } 265 266 log_msg(LOG_DEFAULT, LVL_DEBUG, "Configured link '%s'.", ilink->svc_name); 227 267 return EOK; 228 268 229 269 error: 230 270 if (ilink->iplink != NULL) 231 271 iplink_close(ilink->iplink); 272 232 273 inet_link_delete(ilink); 233 274 return rc; 234 275 } 235 276 236 static void inet_link_cat_change_cb(void) 237 { 238 (void) inet_link_check_new(); 239 } 240 241 int inet_link_discovery_start(void) 242 { 243 int rc; 244 245 rc = loc_register_cat_change_cb(inet_link_cat_change_cb); 246 if (rc != EOK) { 247 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering callback for IP link " 248 "discovery (%d).", rc); 249 return rc; 250 } 251 252 return inet_link_check_new(); 253 } 254 255 /** Send datagram over Internet link */ 256 int inet_link_send_dgram(inet_link_t *ilink, inet_addr_t *lsrc, 257 inet_addr_t *ldest, inet_dgram_t *dgram, uint8_t proto, uint8_t ttl, int df) 258 { 259 iplink_sdu_t sdu;260 inet_packet_t packet;261 i nt rc;262 size_t offs, roffs;263 277 /** Send IPv4 datagram over Internet link 278 * 279 * @param ilink Internet link 280 * @param lsrc Source IPv4 address 281 * @param ldest Destination IPv4 address 282 * @param dgram IPv4 datagram body 283 * @param proto Protocol 284 * @param ttl Time-to-live 285 * @param df Do-not-Fragment flag 286 * 287 * @return EOK on success 288 * @return ENOMEM when not enough memory to create the datagram 289 * @return ENOTSUP if networking mode is not supported 290 * 291 */ 292 int inet_link_send_dgram(inet_link_t *ilink, addr32_t lsrc, addr32_t ldest, 293 inet_dgram_t *dgram, uint8_t proto, uint8_t ttl, int df) 294 { 295 addr32_t src_v4; 296 uint16_t src_af = inet_addr_get(&dgram->src, &src_v4, NULL); 297 if (src_af != AF_INET) 298 return EINVAL; 299 300 addr32_t dest_v4; 301 uint16_t dest_af = inet_addr_get(&dgram->dest, &dest_v4, NULL); 302 if (dest_af != AF_INET) 303 return EINVAL; 304 264 305 /* 265 306 * Fill packet structure. Fragmentation is performed by 266 307 * inet_pdu_encode(). 267 308 */ 309 310 iplink_sdu_t sdu; 311 312 sdu.src = lsrc; 313 sdu.dest = ldest; 314 315 inet_packet_t packet; 316 268 317 packet.src = dgram->src; 269 318 packet.dest = dgram->dest; … … 271 320 packet.proto = proto; 272 321 packet.ttl = ttl; 322 323 /* Allocate identifier */ 324 fibril_mutex_lock(&ip_ident_lock); 325 packet.ident = ++ip_ident; 326 fibril_mutex_unlock(&ip_ident_lock); 327 273 328 packet.df = df; 274 329 packet.data = dgram->data; 275 330 packet.size = dgram->size; 276 277 sdu.lsrc.ipv4 = lsrc->ipv4; 278 sdu.ldest.ipv4 = ldest->ipv4; 279 280 offs = 0; 331 332 int rc; 333 size_t offs = 0; 334 281 335 do { 282 336 /* Encode one fragment */ 283 rc = inet_pdu_encode(&packet, offs, ilink->def_mtu, &sdu.data, 284 &sdu.size, &roffs); 337 338 size_t roffs; 339 rc = inet_pdu_encode(&packet, src_v4, dest_v4, offs, ilink->def_mtu, 340 &sdu.data, &sdu.size, &roffs); 285 341 if (rc != EOK) 286 342 return rc; 287 343 288 344 /* Send the PDU */ 289 345 rc = iplink_send(ilink->iplink, &sdu); 346 290 347 free(sdu.data); 291 292 348 offs = roffs; 293 349 } while (offs < packet.size); 294 350 295 351 return rc; 296 352 } 297 353 354 /** Send IPv6 datagram over Internet link 355 * 356 * @param ilink Internet link 357 * @param ldest Destination MAC address 358 * @param dgram IPv6 datagram body 359 * @param proto Next header 360 * @param ttl Hop limit 361 * @param df Do-not-Fragment flag (unused) 362 * 363 * @return EOK on success 364 * @return ENOMEM when not enough memory to create the datagram 365 * 366 */ 367 int inet_link_send_dgram6(inet_link_t *ilink, addr48_t ldest, 368 inet_dgram_t *dgram, uint8_t proto, uint8_t ttl, int df) 369 { 370 addr128_t src_v6; 371 uint16_t src_af = inet_addr_get(&dgram->src, NULL, &src_v6); 372 if (src_af != AF_INET6) 373 return EINVAL; 374 375 addr128_t dest_v6; 376 uint16_t dest_af = inet_addr_get(&dgram->dest, NULL, &dest_v6); 377 if (dest_af != AF_INET6) 378 return EINVAL; 379 380 iplink_sdu6_t sdu6; 381 addr48(ldest, sdu6.dest); 382 383 /* 384 * Fill packet structure. Fragmentation is performed by 385 * inet_pdu_encode6(). 386 */ 387 388 inet_packet_t packet; 389 390 packet.src = dgram->src; 391 packet.dest = dgram->dest; 392 packet.tos = dgram->tos; 393 packet.proto = proto; 394 packet.ttl = ttl; 395 396 /* Allocate identifier */ 397 fibril_mutex_lock(&ip_ident_lock); 398 packet.ident = ++ip_ident; 399 fibril_mutex_unlock(&ip_ident_lock); 400 401 packet.df = df; 402 packet.data = dgram->data; 403 packet.size = dgram->size; 404 405 int rc; 406 size_t offs = 0; 407 408 do { 409 /* Encode one fragment */ 410 411 size_t roffs; 412 rc = inet_pdu_encode6(&packet, src_v6, dest_v6, offs, ilink->def_mtu, 413 &sdu6.data, &sdu6.size, &roffs); 414 if (rc != EOK) 415 return rc; 416 417 /* Send the PDU */ 418 rc = iplink_send6(ilink->iplink, &sdu6); 419 420 free(sdu6.data); 421 offs = roffs; 422 } while (offs < packet.size); 423 424 return rc; 425 } 426 427 static inet_link_t *inet_link_get_by_id_locked(sysarg_t link_id) 428 { 429 assert(fibril_mutex_is_locked(&inet_links_lock)); 430 431 list_foreach(inet_links, link_list, inet_link_t, ilink) { 432 if (ilink->svc_id == link_id) 433 return ilink; 434 } 435 436 return NULL; 437 } 438 298 439 inet_link_t *inet_link_get_by_id(sysarg_t link_id) 299 440 { 300 fibril_mutex_lock(&inet_discovery_lock); 301 302 list_foreach(inet_link_list, elem) { 303 inet_link_t *ilink = list_get_instance(elem, inet_link_t, 304 link_list); 305 306 if (ilink->svc_id == link_id) { 307 fibril_mutex_unlock(&inet_discovery_lock); 308 return ilink; 309 } 310 } 311 312 fibril_mutex_unlock(&inet_discovery_lock); 313 return NULL; 441 inet_link_t *ilink; 442 443 fibril_mutex_lock(&inet_links_lock); 444 ilink = inet_link_get_by_id_locked(link_id); 445 fibril_mutex_unlock(&inet_links_lock); 446 447 return ilink; 448 } 449 450 /** Get IDs of all links. */ 451 int inet_link_get_id_list(sysarg_t **rid_list, size_t *rcount) 452 { 453 sysarg_t *id_list; 454 size_t count, i; 455 456 fibril_mutex_lock(&inet_links_lock); 457 count = list_count(&inet_links); 458 459 id_list = calloc(count, sizeof(sysarg_t)); 460 if (id_list == NULL) { 461 fibril_mutex_unlock(&inet_links_lock); 462 return ENOMEM; 463 } 464 465 i = 0; 466 list_foreach(inet_links, link_list, inet_link_t, ilink) { 467 id_list[i++] = ilink->svc_id; 468 log_msg(LOG_DEFAULT, LVL_NOTE, "add link to list"); 469 } 470 471 fibril_mutex_unlock(&inet_links_lock); 472 473 log_msg(LOG_DEFAULT, LVL_NOTE, "return %zu links", count); 474 *rid_list = id_list; 475 *rcount = count; 476 477 return EOK; 314 478 } 315 479
Note:
See TracChangeset
for help on using the changeset viewer.
